Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update UI when Entity Model changes in ViewModel

I am trying to come up with a good way of implementing the MVVM pattern using Entity-Framework where my entities are my models. My DataContext is my viewmodel. This is a small reproduction of the problem.

View

<TextBox Text="{Binding MyText}" />

ViewModel:

I have the requirement of needing to navigate record by record from my DB. When a button is clicked in the View a command is sent to the Viewmodel that executes nextRecord(). EF does its magic and _myObject is the next row/record from the database

public class myViewModel: INotifyPropertyChanged
{
    private MyEntityObject _myObject;

    public string MyText
    {
        get { return _myObject.MyText; }
        set
        {
            if (_myObject.MyText != value)
            {
                _myObject.MyText = value;
                OnPropertyChanged("MyText");
            }
        }
    }

    private void _nextRecord()
    {
      _myObject = myEntitiesContext.NextRecord() //pseudocode
    }
}

Autogenerated Entity Model

public partial class MyEntityObject
{
     public string MyText { get; set; }
}

Since the View has no knowledge of _myObject changing, it doesn't update when _myObject changes. A few approaches I have thought of.

  1. I haven't tested wrapping my entities in a INotifyPropertyChanged wrapper class but am wary to do this as I have a lot of entity objects.

  2. I could call OnPropertyChanged("...") for all properties, but some of my entities have a lot of properties to them, which would be ugly. Possible to use reflection to make it cleaner, but I may have properties that aren't databound.

  3. I might be able to defer this to the UI, somehow refreshing the bindings when I click "Next Record", but this breaks MVVM and looks dirty

How can I get the UI to recognize changes from _myObject?

like image 471
James Sampica Avatar asked Mar 23 '23 09:03

James Sampica


1 Answers

As I've mentioned in the comments, calling OnPropertyChanged("") or OnPropertyChanged(null) invalidates all properties and is equivalent to calling OnPropertyChanged for each and every property. This behavior is also documented here:

The PropertyChanged event can indicate all properties on the object have changed by using either null or String.Empty as the property name in the PropertyChangedEventArgs.

This means that you can simply add a call to OnPropertyChanged("") when you update your object to force WPF to reevaluate all bindings to your view model:

private void _nextRecord()
{
    _myObject = myEntitiesContext.NextRecord();
    OnPropertyChanged("");
}

That being said, I'd still go with @Anand's solution (+1). There's an ongoing debate on whether it's OK or not for the viewmodel to expose the model as a property, and I tend to go with exposing it until you need to introduce some view model specific logic. Most of the time you won't have to and it's not worth the trouble of wrapping model properties.

like image 52
Adi Lester Avatar answered Apr 01 '23 06:04

Adi Lester