MVVM - observing changes in the Model?

noutramnoutram Member ✭✭

Hi

For MVVM, I've heard suggestions of a case for a binding layer between the Model and ViewModel objects. What is the consensus around doing this (maybe where there are asynchronous changes to the model data)?

I've read one opinion that said it's not good practise to expose the Model properties directly to the view, which I can appreciate rather breaks the architecture. Is there a clean platform-independent way for the VM to observe changes is the model?

Nick

Tagged:

Posts

  • NMackayNMackay GBInsider, University mod

    If you want your models that bind to the view to handle property changes you need to implement INPC in the model object. In prism for example, your model just has to inherit BindableBase and it's taken care of.

     public class Contact : BindableBase
        {
            private string _title;
            public string Title
            {
                get => _title;
                set => SetProperty(ref _title, value);
            }
    

    Normally I'd have objects that are purely for binding and optimised/flattened to make binding easier and have a service layer that has DTO's etc.

  • JohnHardmanJohnHardman GBUniversity mod
    edited July 22

    @noutram said:
    I've read one opinion that said it's not good practise to expose the Model properties directly to the view

    I agree that exposing the Model to the View is not good practice. You expose the Model to the View Model, and expose the View Model to the View.

    @noutram said:
    Is there a clean platform-independent way for the VM to observe changes is the model?

    It's the usual mechanisms - INotifyPropertyChanged and INotifyCollectionChanged

    Note that you rarely see this done in code shared on the forums. IMHO, many people implement VVM rather than MVVM.
    TBH, in simple apps, it's possible to get away with one less layer, but in enterprise scale apps, having the extra layer is IMHO a whole lot better. There may be some duplicated code, but the increased testability etc makes up for it.

  • noutramnoutram Member ✭✭

    Thank's John

    That's really clear and helpful. I can implement INotifyPropertyChanged on my model - but I'm missing the VM part - how to "observe"?

    As a model might be updated asynchronously (e.g. network response), I can see value in doing this.

    Nick

    @JohnHardman said:

    @noutram said:
    I've read one opinion that said it's not good practise to expose the Model properties directly to the view

    I'd agree that exposing the Model to the View is not good practice. You expose the Model to the View Model, and expose the View Model to the View.

    @noutram said:
    Is there a clean platform-independent way for the VM to observe changes is the model?

    It's the usual mechanisms - INotifyPropertyChanged and INotifyCollectionChanged

    Note that you rarely see this done in code shared on the forums. IMHO, many people implement VVM rather than MVVM.
    TBH, in simple apps, it's possible to get away with one less layer, but in enterprise scale apps, having the extra layer is IMHO a whole lot better. There may be some duplicated code, but the increased testability etc makes up for it.

  • JohnHardmanJohnHardman GBUniversity mod

    @noutram said:
    I'm missing the VM part - how to "observe"?

    INotifyPropertyChanged exposes an event PropertyChanged.

    Your View Model would do:

    model.PropertyChanged += OnPropertyChanged
    

    and then:

    private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        // React to model property changes by checking e.PropertyName to see which property has been updated
    }
    
  • noutramnoutram Member ✭✭

    Wow - it's that simple. I assumed it would be more work. I shall go and try immediately :)

    @JohnHardman said:

    @noutram said:
    I'm missing the VM part - how to "observe"?

    INotifyPropertyChanged exposes an event PropertyChanged.

    Your View Model would do:

    model.PropertyChanged += OnPropertyChanged
    

    and then:

    private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
      // React to model property changes by checking e.PropertyName to see which property has been updated
    }
    
  • JohnHardmanJohnHardman GBUniversity mod

    @noutram said:
    Wow - it's that simple. I assumed it would be more work. I shall go and try immediately :)

    Once you've got it going, you may find that you want to create a base data model class, in the same way that you probably have a base view model class. As @NMackay said, if you are using Prism, you can use BindableBase for this. If not using Prism then you'll want to roll your own (I currently have BaseDataModel and BaseViewModel, although I'll probably re-factor those into a single class in future).

  • noutramnoutram Member ✭✭
    edited July 22

    @JohnHardman said:

    @noutram said:
    Wow - it's that simple. I assumed it would be more work. I shall go and try immediately :)

    Once you've got it going, you may find that you want to create a base data model class, in the same way that you probably have a base view model class. As @NMackay said, if you are using Prism, you can use BindableBase for this. If not using Prism then you'll want to roll your own (I currently have BaseDataModel and BaseViewModel, although I'll probably re-factor those into a single class in future).

    Definitely want to roll my own for now, especially has I have to teach Xamarin.Forms next year (I like to understand what goes on under the hood).

    Prism seems to come recommended by many people, and I appreciate the suggestion (it's on my list of todo's), but I'm less about productivity and more about understanding right now. I like to take my time and ingest what's going on first.

    I sincerely appreciate the (rapid!) response from both @JohnHardman and @NMackay here. What a great introduction to the Xamarin community this has been.

  • NMackayNMackay GBInsider, University mod

    @noutram said:

    @JohnHardman said:

    @noutram said:
    Wow - it's that simple. I assumed it would be more work. I shall go and try immediately :)

    Once you've got it going, you may find that you want to create a base data model class, in the same way that you probably have a base view model class. As @NMackay said, if you are using Prism, you can use BindableBase for this. If not using Prism then you'll want to roll your own (I currently have BaseDataModel and BaseViewModel, although I'll probably re-factor those into a single class in future).

    Definitely want to roll my own for now, especially has I have to teach Xamarin.Forms next year (I like to understand what goes no under the hood).

    Prism seems to come recommended by many people, and I appreciate the suggestion (it's on my list of todo's), but I'm less about productivity and more about understanding right now. I like to take my time and ingest what's going on first.

    I sincerely appreciate the (rapid!) response from both @JohnHardman and @NMackay here. What a great introduction to the Xamarin community this has been.

    That's 100% the right approach and refreshing to hear.

Sign In or Register to comment.