Reputation: 1015
I have started learning MVVM with some basic applications and I just encountered below issue with binding.
I have 2 textboxes in my View say- Student_name and Student_year. I have a Student class implemented in my viewmodel with its properties. But, the actual Student class is in my Model layer.
<TextBox x:Name="StuName"
Text="{Binding Path=MyStudent.Name, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
<TextBox x:Name="StuYear"
Text="{Binding Path=MyStudent.Year, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
ViewModel:
private Student _myStudent = new Student();
public Student MyStudent
{
get { return _myStudent ; }
set
{
if (value != _myStudent )
{
_myStudent = value;
OnPropertyChanged("MyStudent");
}
}
}
Model (Student Class):
public string Name
{
get { return _name; }
set
{
if (_name!= value)
{
_name= value;
OnPropertyChanged("Name");
}
}
}
I can see everything working fine on binding the values from VM to View. But, the other way is behaving little tricky here..
Wheneven I change Name/Year in the textbox, the control has to land on Viewmodel's Set property? Rather, it straight away goes to Model's Set property.
For Instance, When I modify txtbox 'StuName', SET method of Student class is invoked. But not SET method of Viewmodel(MyStudent object).
I am not sure why this behaves in such a way. Is it because I have directly bounded Student.Name to the textbox? What are the alternatives to handle this SET operation in Viewmodel class..
Thanks in advance.
PS: I have implemented INotifyPropertyChanged interface properly and rest other bindings(of primitive data type) are working fine with other controls.
Upvotes: 0
Views: 1457
Reputation: 7419
As Philip Stuyck correctly pointed out in his answer, the ViewModel only has a setter for the Student
instance, which never changes. So the setter on the ViewModel is never invoked. The binding goes to the name property of that instance.
A different approach would be to wrap the name property in you ViewModel explicitly. This allows for a clearer separation of concerns between Model and ViewModel. I.e. right now your Model implements INotifyPropertyChanged
which IMO belongs into the ViewModel, because in general it is only used for triggering View updates. Your ViewModel would look like this:
class StudentViewModel
{
private Student _myStudent = new Student();
public string Name
{
get { return _myStudent.Name ; }
set
{
if (value != _myStudent.Name )
{
_myStudent.Name = value;
OnPropertyChanged("Name");
}
}
}
}
Your Model on the other hand becomes simpler, because it doesn't have to implement INotifyPropertyChanged
anymore.
Upvotes: 2
Reputation: 7467
That is normal behavior because your binding is to MyStudent.Name. So the Mystudent setter is never called because the instance never changes. The setter of the name is called because in fact that is where your binding is going to.
Upvotes: 1