Is it workable Properties.Settings.Default.Save() in ViewModel? - c#

Weirdly enough, but I can't to get it workable in ViewModel.
public class SmallWindow_ViewModel
{
public string My_property
{
get { return _my_property; }
set { Set(ref _my_property, value); }
}
private string _my_property;
public void SmallWindow_unloaded()
{
Properties.Settings.Default.My_property_setting = My_property;
Properties.Settings.Default.Save();
}
}
If it is placed in Code Behind it works.

Related

How to set set and get for Textbox control?

I want to get value of TextBox in Form1, to another class.
I try to make a set and get, but I can't do this, because VS shows me error about ambiguity in code.
public partial class Form1 : Form
{
private TextBox _textBox1;
public Form1()
{
this._textBox1 = textBox1;
InitializeComponent();
}
public string _textBox1
{
get { return _textBox1.Text; }
set { _textBox1.Text = value; }
}
}
How to make this correct? My control is private.
You have one field and one property in you class with the same name, change the name of the property, for instance to
public string FormTextBox1
{
get { return _textBox1.Text; }
set { _textBox1.Text = value; }
}
as naming standard the public properties must be Pascal Case notation
Capitalization Conventions
You can pass textBox1.Text to a variable, and make a getter/setter for it.
Like this:
public class A : Form1
{
// assuming it's a string. If it's not, change the type
// for the getter method below accordingly
private string textBoxValue;
// at some point, you'll have to make this line below:
textBoxValue = textBox1.Value;
public string GetTextBoxValue()
{
return textBoxValue;
}
}
public class B
{
A aReference = new A();
// you can get the value you want by doing
// aReference.GetTextBoxValue();
}
public void yourFormLoadMethod()
{
//this instantiates a new object of your class
nameOfYourClass newYourObject = new nameOfYourClass(//put any params you need here);
txtNameOfYourTextBox.DataBindings.Add("Enabled", newLTDObjectBenInt, "YourTextBoxEnabled", true, DataSourceUpdateMode.OnPropertyChanged);
txtNameOfYourTextBox.DataBindings.Add("Value", newLTDObjectBenInt, "YourTextBoxEntered", true, DataSourceUpdateMode.OnPropertyChanged);
txtNameOfYourTextBox.DataBindings.Add("Visible", newLTDObjectBenInt, "YourTextBoxVisible", true, DataSourceUpdateMode.OnPropertyChanged);
}
public class nameOfYourClass
{
//constructor
public nameOfYourClass(//same params here from the Load method)
{
//place any logic that you need here to load your class properly
//this sets default values for Enable, Visible and the text
//you use these fields to manipulate your field as you wish
yourTextBoxVisible = true;
yourTextBoxEnabled = true;
yourTextBoxEntered = "this is the default text in my textbox";
}
private bool yourTextBoxEnabled;
public bool YourTextBoxEnabled
{
get
{
return yourTextBoxEnabled;
}
set
{
yourTextBoxEnabled = value;
}
}
private bool yourTextBoxVisible;
public bool YourTextBoxVisible
{
get
{
return yourTextBoxVisible;
}
set
{
yourTextBoxVisible = value;
}
}
private string yourTextBoxEntered;
public string YourTextBoxEntered
{
get
{
return yourTextBoxEntered;
}
set
{
yourTextBoxEntered = value;
}
}
}

Implementing RaiseCanExecuteChanged method inside setter of a class object

I am still not sure if my approach is correct, but in an attempt to implement the MVVM pattern, I have created a model class 'Test' in the following way:
public class Test : BindableBase
{
private int testNumber;
public int TestNumber
{
get { return testNumber; }
set { SetProperty(ref testNumber, value) }
}
...
}
Then I created an instance of this class in my ViewModel:
class ViewModel : BindableBase
{
private Test testVM;
public Test TestVM
{
get { return testVM; }
set { SetProperty(ref testVM, value); }
}
...
And in the XAML code of the View I bind all the properties of the Test class through the TestVM property. Although this works fine, I ran into a problem when trying to implement a DelegateCommad.
public DelegateCommand StartTestCommand { get; private set; }
So far, when implementing DelegateCommands, if I want to trigger the CanExecute method when a property has changed, I include DelegateCommand.RaiseCanExecuteChanged() inside the property's setter. Like so:
...
private bool duringTest;
public bool DuringTest
{
get { return duringTest; }
set
{
SetProperty(ref duringTest, value);
StartTestCommand.RaiseCanExecuteChanged();
}
}
...
This works fine for properties declared in the ViewModel, but when using the same approach for the Test properties, this no longer works.
...
private Test testVM;
public Test TestVM
{
get { return testVM; }
set
{
SetProperty(ref testVM, value);
StartTestCommand.RaiseCanExecuteChanged();
}
}
}
I would expect that every time a property from TestVM was changed, the setter would be called, but instead the model is updated directly.
What am I doing wrong? What is the correct approach when using a Model object in the ViewModel?
Changing a property value of an object doesn't change the object's reference.
Declaring this
public Test TestVM
{
get { return testVM; }
set
{
SetProperty(ref testVM, value);
StartTestCommand.RaiseCanExecuteChanged();
}
}
you are basically telling the compiler: when the reference to the TestVM object is changed (even to the same value), update the StartTestCommand's state.
But obviously you don't change the reference to that object once you assigned it.
If you want to update the commands in your parent view-model (ViewModel) when some child view-model's (Test) properties change, you can use the PropertyChanged event:
public Test TestVM
{
get { return testVM; }
set
{
Test oldValue = testVM;
if (SetProperty(ref testVM, value))
{
if (oldValue != null)
{
oldValue.PropertyChanged -= TestPropertyChanged;
}
if (testVM!= null)
{
testVM.PropertyChanged += TestPropertyChanged;
}
}
}
}
void TestPropertyChanged(object sender, PropertyChangedEventArgs e)
{
// filter if necessary
if (e.PropertyName == "...")
{
StartTestCommand.RaiseCanExecuteChanged();
}
}

MvvmCross - handle button click in viewmodel

I'm new to xamarin and mvvmcross and I would like to wire up a simple button click from my ios project to my viewmodel.
using System;
using MvvmCross.Binding.BindingContext;
using MvvmCross.iOS.Views;
using Colingual.Core.ViewModels;
namespace Colingual.iOS
{
public partial class LoginView : MvxViewController
{
public LoginView() : base("LoginView", null)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
// Perform any additional setup after loading the view, typically from a nib.
var set = this.CreateBindingSet<LoginView, LoginViewModel>();
set.Bind(Username).To(vm => vm.Username);
set.Bind(Password).To(vm => vm.Password);
set.Bind(btnLogin).To(vm => vm.MyAwesomeCommand);
set.Apply();
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
// Release any cached data, images, etc that aren't in use.
}
}
}
I would like to wire up btnlogin to myawesomecommand.
using MvvmCross.Core.ViewModels;
namespace Colingual.Core.ViewModels
{
public class LoginViewModel : MvxViewModel
{
readonly IAuthenticationService _authenticationService;
public LoginViewModel(IAuthenticationService authenticationService)
{
_authenticationService = authenticationService;
}
string _username = string.Empty;
public string Username
{
get { return _username; }
set { SetProperty(ref _username, value); }
}
string _password = string.Empty;
public string Password
{
get { return _password; }
set { SetProperty(ref _password, value); }
}
public bool AuthenticateUser() {
return true;
}
MvxCommand _myAwesomeCommand;
public IMvxCommand MyAwesomeCommand
{
get
{
DoStuff();
return _myAwesomeCommand;
}
}
void DoStuff()
{
string test = string.Empty;
}
}
}
As you can see I've got mvxCommand with the name of MyAwesomecommand but I want to handle some logic from a button click in my other project. Anyone know what I should do?
I've done more looking around and found an answer here.
MvxCommand _myAwesomeCommand;
public IMvxCommand MyAwesomeCommand
{
get { return new MvxCommand(DoStuff); }
}
void DoStuff()
{
string test = string.Empty;
}
The idea is to have your mvxcommand getter which returns a new command that takes the method as a parameter.
When clicking the button btnLogin, you can access void DoStuff in viewmodel.

2 class inheritance NotifyPropertyChanged fails update UI

I have currently the problem that my UI doesnt update as I like to do so, hope you can help me out.
I have a simulated "2 class inheritance" as recommended in this page
http://www.codeproject.com/Articles/10072/Simulated-Multiple-Inheritance-Pattern-for-C
My real life app looks like the following:
public class Item : INotifyPropertyChanged
{
private bool _isVisible;
public bool IsVisible
{
get
{
return _isVisible;
}
set
{
if (_isVisible == value)
return;
_isVisible = value;
OnPropertyChanged("IsVisible");
}
}
//NotifyPropertyChanged Implementation removed so the focus stays on problem...
}
public class ObjectItem : INotifyPropertyChanged
{
private bool _isExpanded;
public bool IsExpanded
{
get
{
return _isExpanded;
}
set
{
if (_isExpanded== value)
return;
_isExpanded= value;
OnPropertyChanged("IsExpanded");
}
}
//NotifyPropertyChanged Implementation removed so the focus stays on problem...
}
public class CombinedItem : Item
{
private readonly ObjectItem _objectItem = new ObjectItem();
public bool IsExpanded
{
get { return _objectItem.IsExpanded; }
set { _objectItem.IsExpanded = value; }
}
public static implicit operator ObjectItem(CombinedItem combinedItem)
{
return combinedItem._objectItem;
}
}
I am now facing the problem that the Property IsExpanded doesnt get Notified to the UI correctly when I have a CominedItem as the DataContext, the IsVisible Property works as expected.
To overcome the problem I have changed the CominedItem to the following:
public class CombinedItem : Item
{
private readonly ObjectItem _objectItem = new ObjectItem();
public bool IsExpanded
{
get { return _objectItem.IsExpanded; }
set
{
if (_objectItem.IsExpanded == value)
return;
_objectItem.IsExpanded = value;
OnPropertyChanged("IsExpanded");
}
}
public static implicit operator ObjectItem(CombinedItem combinedItem)
{
return combinedItem._objectItem;
}
}
Is there a way to avoid writing the OnPropertyChanged("IsExpanded") again, with this approach.
(I know there are libaries/tools, where you dont need to write it at all and just have to declare a attribute, pls dont suggest those)
Actually you should subscribe to ObjectItem PropertyChanged and raise the matching event on CombinedItem.
If _objectItem.IsExpanded is modified without using CombinedItem.IsExpanded, your UI will not see the change.
Without some magic attribute/tool if you want to wrap a property, you will have to handle changes notification.
public class CombinedItem : Item
{
private readonly ObjectItem _objectItem = new ObjectItem();
public CombinedItem()
{
_objectItem.PropertyChanged += (s, e) =>
{
if (e.PropertyName == "IsExpanded")
OnPropertyChanged("IsExpanded");
}
}
public bool IsExpanded
{
get { return _objectItem.IsExpanded; }
set { _objectItem.IsExpanded = value; }
}
public static implicit operator ObjectItem(CombinedItem combinedItem)
{
return combinedItem._objectItem;
}
}
You could expose ObjectItem as a property and bind to that
public class CombinedItem : Item
{
private readonly ObjectItem _objectItem = new ObjectItem();
public bool IsExpanded
{
get { return _objectItem.IsExpanded; }
set { _objectItem.IsExpanded = value; }
}
public ObjectItem ObjectItem
{
get { return _objectItem; }
}
public static implicit operator ObjectItem(CombinedItem combinedItem)
{
return combinedItem._objectItem;
}
}
<Expander IsExpanded={Binding ObjectItem.IsExpanded}/>

Binding label content to a value in nested class not in Datacontext

My view (InformationView) Binded to InformationViewModel and I use a nested class to maintain current Bank
My nested class :
public class MainController : NotificationObject
{
public MainController()
{
Initialize();
}
private void Initialize()
{
// TODO implement
}
public static MainController Instance
{
get { return Nested.instance; }
}
private BankModel _currentBank;
public BankModel CurrentBank
{
get { return _currentBank; }
set
{
if (_currentBank== value)
{
return;
}
_currentBank= value;
RaisePropertyChanged(() => CurrentBank);
}
}
private class Nested
{
static Nested()
{
}
internal static readonly MainController instance = new MainController();
}
}
My BankModel :
private string _name ="test";
public string Name
{
get
{
return _name;
}
set
{
if (_name == value)
{
return;
}
_name= value;
RaisePropertyChanged(()=>Name);
}
}
My XAML
xmlns:Controller="clr-namespace:MyProject.Controller"
/****/
<Label Content="{Binding Controller:MainController.CurrentBank.Name}"/>
first I can't see the "test" in my label and if I execute I change this value and always my label is empty, how I do this with the correct approach
You need to use a combination of "Path" and "Source" in your binding declaration. You also need to alert the binding engine to the fact that you're accessing static members.
<Label Content="{Binding Source={x:Static Controller:MainController.Instance}, Path=CurrentBank.Name}" />

Categories

Resources