0

I think this question could of already been answered, which if this is the case I will delete immediately. I'm new to WPF (and new to C# really) and I'm trying as hard as possible to follow MVVM but I'm really struggling with finding a way to NOT implement INotifyPropertyChanged on my Model.

My Model contains a collection of predefined objects which are created from another reference. Within the Model, I have properties which are updated as and when the Task is completed.

CustomObject - API

public class CustomObject
{
  private string _myTaskOutput;

  public CustomObject()
  {
     _myTaskOutput = MyTaskMethod();
  }

   //MyTaskMethod()

  //Get & Setter for _myTaskOutput;
}

Util - API

 public static class Util
 {
     public IEnumerable<CustomObject> GenerateObjects()
     {
         var customObjectCollection = SomeHelperMethod();
         return customObjectCollection;
     }
 }

Model

   public class CustomObjectCollectionModel
   {
     private IEnumerable<CustomObject> _customObjectCollection;

     public CustomObjectCollectionModel()
     {
         _customObjectCollection = Util.GenerateObjects();
     }

     //Get & Setter for IEnumerable<CustomObject>
   }

The object reference does not change so I believe having an ObservableCollection is out of the question (is this correct?) and implementing INotifyPropertyChanged on CustomObject works as intended but I understand this not the correct way of doing things.

Kitson88
  • 2,889
  • 5
  • 22
  • 37
  • "and implementing INotifyPropertyChanged on CustomObject works as intended but I understand this not the correct way of doing things." What makes you say this is not the correct way? – Steven Aug 25 '17 at 09:19
  • 1
    @Steven Most answers on SO regarding MVVM. I'm guessing it's because of binding directly to the Model from View rather than the ViewModel. – Kitson88 Aug 25 '17 at 09:21
  • @Steven To give you some context, I'm creating this application for my portfolio in hopes of landing my first developer role so I want to make sure it's correct. – Kitson88 Aug 25 '17 at 09:24
  • Maybe the answers on this could help you? https://stackoverflow.com/questions/15439841/mvvm-in-wpf-how-to-alert-viewmodel-of-changes-in-model-or-should-i – FakeCaleb Aug 25 '17 at 09:35
  • @FakeCaleb thank you but this is for updating a single object rather than a predefined collection. – Kitson88 Aug 25 '17 at 09:37
  • There is nothing wrong in implementing the `INotifyPropertyChanged` interface in the model. This interface is neither a "WPF specific" nor a "MVVM specific" one (note its namespace - `System.ComponentModel`). – dymanoid Aug 25 '17 at 09:56
  • @dymanoid Does it depend on how your binding from the View? So if your proxying the data from Model to ViewModel and then binding from View to ViewModel (as mm8 as suggested) this is okay. But if your binding directly to Model from View then I'm guessing this is not okay? – Kitson88 Aug 25 '17 at 10:04
  • 1
    If your view model would be a plain proxy with no added value, then why implementing it? MVVM is just a suggestion, so you'd better use DRY (don't repeat yourself) to minimize your boiler plate code rather than implementing a dummy proxy "just because MVVM wants it like that". – dymanoid Aug 25 '17 at 10:10
  • @dymanoid Thank you. I'm favouring your advice and it does make perfect sense. – Kitson88 Aug 25 '17 at 11:54

1 Answers1

1

If CustomObject is some kind of domain or business object, you could wrap it in a view model class in your client application. So instead of binding to an ObservableCollection<CustomObject> you bind to an ObservableCollection<CustomObjectWrapper> where CustomObjectWrapper is a client-specific class that implements the INotifyPropertyChanged interface (provided that you actually need to provide change notifications in your UI).

You will indeed have to create a CustomObjectWrapper for each CustomObject that you receive from your service API - you could do this in your view model class - but at the same time you don't have to pollute your business objects with client-specific code. Binding directly to domain-specific business objects is rarely useful.

mm8
  • 163,881
  • 10
  • 57
  • 88
  • So just to clarify, would I need to just map the properties for each `CustomObject` to a new `CustomObjectWrapper` instance and then bind to the ViewModel property which hosts `CustomObjectWrapper`? – Kitson88 Aug 25 '17 at 09:51
  • Yes, you basically replace CustomObject with CustomObjectWrapper in all properties that the view binds to. – mm8 Aug 25 '17 at 09:52
  • I'm just testing now. – Kitson88 Aug 25 '17 at 10:50
  • I don't think this will work or maybe it's the way I'm implementing the wrapper. Basically I've created a `CustomObjectWrapper` which takes a `CustomObject` as it's constructor param, created new properties referencing the `CustomObject` properties which at that point I realised it's not going to work because the ViewModel has no idea when the `CustomObject`'s properties are being updated. – Kitson88 Aug 25 '17 at 11:49
  • Can you give me an example of how you would implement your wrapper ensuring `CustomObject` property changes are updated. – Kitson88 Aug 25 '17 at 11:57
  • Of course the CustomObject class must tell the outside world when it is being updated somehow, for example by raising an event. How else is someone supposed to know? – mm8 Aug 25 '17 at 12:08
  • I guessed. I'm just going to leave it implementing INotifyPropertyChanged on the Model and pass the property changed events to the wrapper. Wrapping the Object has worked out nice so thanks for your help. – Kitson88 Aug 25 '17 at 12:16