8

I've read various approaches to communicating changes in model data to the view model. Some suggest that the model should implement INotifyPropertyChanged where possible, so that it may notify the view model of changed properties. Some suggest a service layer between model and view model, with the service layer implementing INPC, method calls being routed through this service layer to the model so that the service layer notifies the view model.

I consider the latter to be a more granular revision of the former and have begun implementing INPC in my model classes. It feels wrong because

a) I now have to write an event handler in my view model for notifications from the model. This takes the form of a long switch(propertyName) which sets the corresponding property(s) on the view model causing NPC to be sent upwards again. I feel like I'm writing a lot of boiler plate code here.

b) View model is now coupled to my model via a bunch of strings that are regulated solely by convention i.e no 'interface' defined. Not to mention the difficulty this causes IDEs.

c) My model has to be modified to accomodate this context! What if it was closed for some reason? I thought patterns like this were designed to increase code reusability & seperation of concerns. Not only this but the code required to fire the INPC events is tedious and repetetive and not really abstractable.

I'm really keen to know how WPF pros approach this problem whether by dependency properties etc. I get the feeling I am missing something. I'm not keen on using a framework as would like to learn 'from the ground up'. I've been away from WPF for a year or two and working with AngularJS recently has made me question my methods here.

Thanks!

Sheridan
  • 68,826
  • 24
  • 143
  • 183
Drew R
  • 2,988
  • 3
  • 19
  • 27
  • What exactly are you referring to when you say `Model`? Do you mean the business objects/data type classes, the code that connects with the data source, or both? – Sheridan Aug 28 '13 at 15:51
  • I'm referring to the business data and functionality. In this case my model classes are "Test" (properties like "Description","Result", methods like "Run") and "TestPlan" with VMs "TestViewModel" "TestPlanViewModel". – Drew R Aug 28 '13 at 15:54
  • You don't need INPC for your model, only your view model. That's the entire point of your VM - I have seen people put INPC in their models but it strikes me as just making it a view model, rather than a model. – Ryan Amies Aug 28 '13 at 17:34
  • +1. I've been struggling with this for a while now, and I eventually went for option **a)**. It is indeed boilerplate code, but I found that preferable to breaking the modularity. I generally found that in answers to this question people tend to say that the `ViewModel` should check for updates from the `Model` rather than being notified, but if my `Model` is chewing away asynchronously in the background, I don't want to have to sit there "polling" it for updates. I'd love to switch to something cleaner if a better solution exists. – Will Faithfull Aug 28 '13 at 19:55
  • you don't have to have a messy observer in your VM (`This takes the form of a long switch(propertyName)`). Use something like [This](http://joshsmithonwpf.wordpress.com/2009/07/11/one-way-to-avoid-messy-propertychanged-event-handling/) and you save yourself some headache – Viv Aug 28 '13 at 20:23
  • Everything else is very abstract, if your VM and Model are so coupled, then that indicates you "do" need a service encapsulating those functionality to one item. It boils down to your app's requirement and how you've structured it – Viv Aug 28 '13 at 20:30
  • @Sheridan: What do you suggest as an alternative? – Drew R Aug 29 '13 at 00:09
  • @Viv I do like the PropertyObserver solution, but would you agree that it is a workaround? I wonder what the Microsoft WPF developers intentions were on this. – Drew R Aug 29 '13 at 00:14
  • @DrewR I wouldn't call it a "workaround". Depends on what you call a workaround tbh. Are managed languages a "workaround" to languages like c++ for making things easier(memory management, ...)? Is a derived type a "workaround" to the base type? `PropertyObserver` also incorporates a weak event observing pattern which is not only better but also takes the hassle out of having to know when to subscribe and unsubscribe from dependent object. Overall in my books it's an "enhancement" and not a "workaround" to out-of-the-box functionality. – Viv Aug 29 '13 at 08:10

1 Answers1

7

For the purpose of this answer, I will call the business object classes 'data types'.

In my personal experience, view models are always tied to the data types. You have to have properties of the types that you want to display, so there will always be a reference from the view models namespace to the data types namespace.

What you call a model (from your description in your comment) sounds like my view models. My view models have properties, mostly of the type of the various data type classes, and methods, whereas my data type classes just hold properties for the most part... they're just holders of data and reporters of changes really.

You seem to be under the impression that the INotifyPropertyChanged interface performs some duties between the 'model' as you call it and the view model classes... in my opinion, that is optional at best... from the INotifyPropertyChanged Interface page at MSDN:

The INotifyPropertyChanged interface is used to notify clients, typically binding clients, that a property value has changed.

Therefore, I see the INotifyPropertyChanged interface as being the 'life-blood' that goes between the views and the view models and data objects. Some developers prefer to 'wrap' each data type in its own view model, but I prefer to implement the INotifyPropertyChanged interface in my data types directly.

The main reason that I do this is so that I can hook into this framework in custom collection classes that I have. This enables me to have collections that are aware of any changes made to any property in any item in the collection among other things. It also enables me to build data synchronisation into my base classes, so that objects know when they have any changes.

It also saves time in creating matching view model classes for each data type class. Why have two classes to do what one can do? I've never needed that level of separation. If I understand you correctly, implementing this interface in your data type classes would negate the need to perform your point a).

Some of your points b) and c) may also be rendered invalid if you can use .NET 4.5 as there is a new CallerMemberNameAttribute attribute that you can use to automatically feed the name of each property to the PropertyChanged handler. I found a good article called C# 5–Making INotifyPropertyChanged Easier with a good description about it.

I've written several large scale WPF applications now and a few frameworks and I've never had a problem with implementing the INotifyPropertyChanged interface in my data type classes. In fact, I don't think that I could have written them in the same time if I had to implement wrapper view model classes for each data type class. This method has served me well so far and I'm planning on sticking with it, until I find a better way at least. However this is all just one developer's opinion and you have to go with what feels right for you.

Sheridan
  • 68,826
  • 24
  • 143
  • 183
  • Wow great answer, thanks for taking the time to write it. Am I interpreting you correctly in saying that your view models expose instances of your model classes aka data types which are themselves notifiers, as opposed to the view model proxying each property individually? My understanding of MVVM is to model the data displayed on screen. You could do that on a per model class / data type basis or per VIEW basis, I think the latter lines up with what you suggest? – Drew R Aug 29 '13 at 00:05