In Mvvm Should the Viewmodel or Model Implement Inotifypropertychanged

In MVVM should the ViewModel or Model implement INotifyPropertyChanged?

I'd say quite the opposite, I always put my INotifyPropertyChanged on my ViewModel - you really don't want to be polluting your model with a fairly WPF specific feature like INotifyPropertyChanged, that stuff should sit in the ViewModel.

I'm sure others would disagree, but that's the way I work.

Should I have one ViewModel class implementing INotifyPropertyChanged for each Model class?

You don't need a ViewModel-Class for each Model-Class you have. Your Model-Classes should implement the INotifyPropertyChanged-Interface.

You need ViewModels to interact with your Views. In the ViewModels you can have instances of your Model-Classes.

Btw.: To avoid writing the code for INotifyPropertyChanged every time in each ViewModel and Model i've created an abstract base class where everything is derived from. This class looks like:

public abstract class NotifyBase : INotifyPropertyChanged
{
private readonly Dictionary<string, object> mapping;

protected NotifyBase()
{
mapping = new Dictionary<string, object>();
}

protected void Set<T>(T value, [CallerMemberName] string propertyName = "")
{
mapping[propertyName] = value;
OnPropertyChanged(propertyName);
}

protected T Get<T>([CallerMemberName] string propertyName = "")
{
if(mapping.ContainsKey(propertyName))
return (T)mapping[propertyName];
return default(T);
}

public event PropertyChangedEventHandler PropertyChanged;

protected virtual void OnPropertyChanged([CallerMemeberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if(handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}

MVVM - PropertyChanged in Model or ViewModel?

The INotifyPropertyChanged (INPC) interface is used for Binding.

So, in the average case, you want to implement it in your ViewModel.

The ViewModel is used to decouple the Model from your View, so there is no need to have INPC in your Model, as you do not want Bindings to your Model.

In most cases, even for smaller properties, you still have a very small ViewModel.

If you want a solid base for MVVM, you are probably going to use some kind of MVVM Framework like caliburn.micro. Using it will give you a ViewModelBase (or here NotifyPropertyChangedBase) so that you do not have to implement those interface members yourself and can just use NotifyOfPropertyChange(() => MyProperty), which is way easier and less error prone.

UPDATE
As there seem to be many Windows Forms developers out there, here is an excellent
article that will give deeper understanding of what MVVM is about:
MSDN Magazine on MVVM

I have linked especially the part about the datamodel, that the question is about.

Should ViewModel class implement INotifyPropertyChanged or can I use Object composition?

Well, ... ViewModels are best to be viewed as Composition, but the notification part should be an implementation of the Interface (or in your case inheritance). You have your DTOs and your ViewModels would be a composition of the DTOs, depending on the scenario.

This implementation of the same stuff can be tedious, but for WPF is still necessary. What you can do to simplify the process is to use Veawrs like Fody. It changes your observation of the ViewModel. All of the properties of the VM are by default observable properties, but you exclude the ones you do not want to, or you can define for one property to let the UI know that it should also update others.

It keeps the code very clean and simple. You will not need to implement the Interface, but it will be inherited in build time if you give the class the needed attribute.

Adding INotifyPropertyChanged to Model?

Option1.

Separate entities, which being transferred between client and server (DTO), from entities, which are models on the client side. Implement INPC in models. Use mapping between these entities.

Option2.

Bind view to view model properties only. Make view model properties, which wrap corresponding model properties.

Option 3.

Is a mix of first two options. Do not aggregate model in view model. Use mapping between model and view model. Make view model properties, which correspond to model properties.

WPF MVVM INotifyPropertyChanged Implementation - Model or ViewModel

The thing is that if you were following MVVM, you would have a BookViewModel for your Book model class. So you would have a INotifyPropertyChanged implementation on that view model. Exactly for that purpose MVVM exists (but not only).

That being said, the INotifyPropertyChanged has to be implemented on view model classes, not models.

UPDATE: In response to your update and our discussion in comments...

By BookViewModel I meant something else. You need to wrap in this view model not the whole collection of Book objects but an individual Book:

public class BookViewModel : INotifyPropertyChanged
{
private Book book;

public Book Book {
get { return book; }
}

public string Title {
get { return Book.Title; }
set {
Book.Title = value;
NotifyPropertyChanged("Title");
}
}

public BookViewModel(Book book) {
this.book = book;
}

public event PropertyChangedEventHandler PropertyChanged;

protected void NotifyPropertyChanged(String info) {
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}

And your BookProvider will return ObservableCollection<BookViewModel> instead of ObservableCollection<Book>:

public class BookProvider
{
public ObservableCollection<BookViewModel> GetBooks() {
ObservableCollection<BookViewModel> books = new ObservableCollection<BookViewModel>();

books.Add(new BookViewModel(new Book {
Title = "Book1",
Authors = new List<Author> { new Author { Name = "Joe" }, new Author { Name = "Phil" } }
}));

books.Add(new BookViewModel(new Book {
Title = "Book2",
Authors = new List<Author> { new Author { Name = "Jane" }, new Author { Name = "Bob" } }
}));

return books;
}
}

As you can see, when you are updating the Title property of the Book you will be doing it through the Title property of the corresponding view model that will raise the PropertyChanged event, which will trigger the UI update.



Related Topics



Leave a reply



Submit