0

Reading up on SO answers regarding what WPF, MMVM model classes contains, it is clear, that in larger applications the general recommendation is to avoid NotifyPropertyChanged and INotifyCollectionChanged outside the presentation layer.

But how would I practically implement this? Say I have a Model.Student class and a StudentService class that returns IList<Student>> from a service layer. My view model would look something like this:

public class StudentViewModel : ViewModelBase
{
   private readonly ObservableCollection<Student> students;
   public StudentViewModel(IStudentService service)
   {
       students = new ObservableCollection<Student>(service.GetAllStudents());  
   }
}

How would I DataBind properties from a single student? Say one of the student names is changed and should be reflected in the View. Would I have to translate the Student classes into some other class that implements INotifyPropertyChanged (and INotifyCollectionChanged if there are collection properties)?

How do you recommend dealing with this if you want to keep the (business) model free from presentation specific details?

Stefan
  • 17,448
  • 11
  • 60
  • 79
Werner
  • 1,229
  • 1
  • 10
  • 24
  • I think you have some misunderstanding here, your `Student` model, not the collection of its models, should reflect to `StudentViewModel`. – Yurii N. Jun 20 '18 at 11:55
  • 1
    MVVM says nothing about where to implement INotifyPropertyChanged and where not. IMO, it is perfectly valid that class Student implements it. It's all just opinions and personal preferences. – Clemens Jun 20 '18 at 11:56
  • Developers generally agree that models should be POCOs. However, they usually disagree what falls under "POCO". I think implementing INotifyPropertyChanged does not violate the POCO principle. – Freggar Jun 20 '18 at 11:59
  • @Freggar but you could argue that INotifyCollectionChanged is to be in presentation only. If not for anything else, then to avoid thread problems? – Werner Jun 20 '18 at 12:19
  • Well as I said its somewhat controversial. Just look at this https://stackoverflow.com/questions/772214/in-mvvm-should-the-viewmodel-or-model-implement-inotifypropertychanged/4574762 and this https://stackoverflow.com/questions/6922130/in-mvvm-model-should-the-model-implement-inotifypropertychanged-interface post. One top answer argues against it and the other in favor of it. That being said I argue that you *can* implement `INotifyPropertyChanged` inside your model since it's neither UI nor WPF specific but just an interface that you implement. – Freggar Jun 20 '18 at 12:27
  • @YuriyN.not sure I understand, should the ViewModel not contain the ObservableCollection? Could you elaborate? – Werner Jun 20 '18 at 12:31
  • @Stefan yes that is what I'm concerned about. The link you have suggest that I have something in my ViewModel that translates, conceptually like "Translate(DomainStudent from, PresentationStudent to)" right? – Werner Jun 20 '18 at 12:37
  • @Werner: so the short version *" like "Translate(DomainStudent from, PresentationStudent to)" right"* : yes indeed. – Stefan Jun 20 '18 at 12:43
  • 1
    There are even automatic mappers available (e.g. AutoMapper). By the way, this looks like a chat here. – dymanoid Jun 20 '18 at 12:48
  • @dymanoid: thanks for the heads up, fixed that ;-) – Stefan Jun 20 '18 at 12:57
  • 1
    As for the close votes: I disagree with the argument of *opinion based*, a question like *"How to keep INotifyPropertyChanged and INotifyCollectionChanged in Presentation layer"* seems very concrete to me. Too broad?, maybe. – Stefan Jun 20 '18 at 12:59
  • 1
    The pattern exists to serve us, not the other way around. If it makes your life convenient to have your objects implement an interface (and, believe me, using Automapper is not convenient on large evolving projects), then *implement the interface*. Having two exact copies of the same object but with one implementing a particular interface becomes pretty sad quickly. Don't fall into that pit of failure. –  Jun 20 '18 at 15:37

1 Answers1

1

From comments:


In general, you should avoid business objects in your viewmodel, in your case your viewmodel has a business object in it which is a violation of the sepperation of layers. See also this post: ViewModels in MVC / MVVM / Seperation of layers- best practices?

Furthermore,

you describe the mapping from your viewmodel to your domain model and visa versa. For the sake of simplicity, it might be best to create a simple function, maybe static, somewhere that can perform the mapping (2 if you want to do it both ways).

Note that @dymanoid suggests a library like automapper to perform such tasks.

Some other thing I want to point out: your StudentViewModel has multiple Students, so it might be best to rename that model to StudentSViewModel, and create a collection of the new StudentViewModel. This last StudentViewModel is new, and most likely will have 90%+ of all the properties which are also present in Student class.

You will gain 2 benefits (and yes, people always like to address an over engineering argument): 1) your viewmodel doesn't expose unnecessary business logic/data and visa versa, and 2) if something changes, you know where to fix it, namely: in the translation of the models. It keeps things "simple" ;-)

so basically, the answer goes beyond the question "should I use INotifyPropertyChanged", but addresses the more conceptual part: "if I manage to separate the layers, do I need to implement INotifyPropertyChanged and has it business value?"

Stefan
  • 17,448
  • 11
  • 60
  • 79