I was given hints in an other questions on how to implement a MVVM. I had problems passing bind update to the GUI when changes are made in the Student class itself (which occure quiet a lot in my project). Is there a way to easy these things up and have it in a more compact way than implemented yet? Or is this the state of the art to implement MVVM?
class MainWindowViewModel : INotifyPropertyChanged
{
ObservableCollection<StudentViewModel> studentViewModels = new ObservableCollection<StudentViewModel>();
public ObservableCollection<StudentViewModel> StudentViewModels
{
get { return studentViewModels; }
}
public MainWindowViewModel()
{
studentViewModels.Add(new StudentViewModel());
studentViewModels.Add(new StudentViewModel());
studentViewModels.Add(new StudentViewModel());
}
public event PropertyChangedEventHandler PropertyChanged;
internal void OnPropertyChanged(String propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
class StudentViewModel : INotifyPropertyChanged
{
Student model;
public String StudentFirstName
{
get { return model.StudentFirstName; }
set { model.StudentFirstName = value; }
}
public String StudentLastName
{
get { return model.StudentLastName; }
set { model.StudentLastName = value; }
}
public StudentViewModel()
{
model = new Student();
this.model.PropertyChanged += (sender, e) =>
{
switch (e.PropertyName)
{
case "StudentFirstName": OnPropertyChanged("StudentFirstName"); break;
case "StudentLastName": OnPropertyChanged("StudentLastName"); break;
default: break;
}
};
}
public StudentViewModel(Student model)
{
this.model = model;
this.model.PropertyChanged += (sender, e) =>
{
switch (e.PropertyName)
{
case "StudentFirstName": OnPropertyChanged("StudentFirstName"); break;
case "StudentLastName": OnPropertyChanged("StudentLastName"); break;
default: break;
}
;
}
public void changeStudent()
{
model.changeStudent();
}
public event PropertyChangedEventHandler PropertyChanged;
internal void OnPropertyChanged(String propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
class Student : INotifyPropertyChanged
{
public String studentFirstName;
public String StudentFirstName
{
get { return studentFirstName; }
set
{
if (studentFirstName != value)
{
studentFirstName = value;
OnPropertyChanged("StudentFirstName");
}
}
}
public String studentLastName;
public String StudentLastName
{
get { return this.studentLastName; }
set
{
if (studentLastName != value)
{
studentLastName = value;
OnPropertyChanged("StudentLastName");
}
}
}
public Student() { }
public void changeStudent()
{
StudentLastName = "McRonald";
}
public event PropertyChangedEventHandler PropertyChanged;
internal void OnPropertyChanged(String propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
I agree with other answers that you should have a look at a MVVM framework. I use MVVM Foundation for my work.
Wall of text is to follow. I started with MVVM not too long ago as well. This code was of great help for me on my last project.
Recently I had to work on a class which also needed IEditableObject to manage editing/saving/discarding the object as well as PropertyChanged notifications. Since you mention a way “to easy things up” I am going to post the base classe I used to tie MVVM and Editable Object together. It was a big time saver for me for implementing all other classes.
The EditableObject inherits from ObservableObject that is part of MVVM Foundation. It takes a struct for the object you are working with as a typeparam.
If you are familiar with implementation of IEditabeObject, there are editData and backupData variables which hold the data you are currently working with (I am not inheriting from this, I created my own EditableObject). I am using AutoMapper to, basically, create a deep copy (backup) of the data I am working with so that it can be restored. There are other ways to do this (look up Serialization or Value Injection), but I already had AutoMapper in the project so no need for more dlls.
The EditableObject has abstract methods SaveObject and RemoveObject, which you implement to handle database calls, etc, to remove and save the objects. The Edit of your object is done using BeginEdit and DiscardChanges and SaveChanges.
The magic happens with the RaisePropertiesChanged method which raises PropertyChanged methods on all decorated properties in your class. So whenever you edit your object and (lets say) discard the changes. The UI is refreshed with back to original values. It also includes IsEditEnabled flag you can bind your UI to. Originally I used PropertyChanged with an empty string, but this would raise it on all properties. Using attributes I ensure it changes only on the properties that I need to update.
I used your Student Class to implement this and attached the base class below.
Hope it helps!
This is the EditableObject class