Updating the user interface when changing the model of an object in the ViewModel

I am trying to come up with a good way to implement the MVVM pattern using Entity-Framework, where my objects are my models. My DataContext is my view model. This is a small reproduction of the problem.

View

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

ViewModel

I have a need to navigate through records from my database. When a button is clicked in the view, the command is sent to the Viewmodel, which executes nextRecord() . EF does its magic, and _myObject 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 } } 

Auto-generated entity model

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

Because the view does not know the _myObject change, it does not update when the _myObject changes. A few approaches that I thought of.

  • I have not tested moving my objects to the INotifyPropertyChanged wrapper INotifyPropertyChanged , but I am afraid to do this because I have many entity objects.

  • I could call OnPropertyChanged("...") for all properties, but some of my entities have many properties for them, which would be ugly. You can use reflection to make it cleaner, but I may have properties that are not database bound.

  • I could defer this to the user interface, somehow updating the bindings when I click "Next Entry", but this interrupts MVVM and looks dirty

How can I make the user interface recognize changes from _myObject ?

+4
source share
4 answers

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

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

This means that you can simply add an OnPropertyChanged("") call when updating the object to force WPF to re-evaluate all the bindings to your view model:

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

Having said that, I will still go with the @Anand (+1) solution. There the discussion continues about whether or not it is good for the viewmodel to display the model as a property, and I tend to expose it until you need to introduce a certain logic of the view model. In most cases, you don’t have to do this, and don’t worry about wrapping the model’s properties.

+5
source

The problem with your code is that when _myObject changed, the _myObject property change event does not MyText . The work around will be to create a new property to hold you and make this property like your Grid DataContext in your view, as shown below. Now that this line is executed MyObject = myEntitiesObject.NextRecord() , your view will be notified of the change.

 public class myViewModel : INotifyPropertyChanged { private MyEntityObject _myObject; public MyEntityObject MyObject { get { return _myObject; } set { if (_myObject != value) { _myObject = value; OnPropertyChanged("MyObject"); } } } private void _nextRecord() { MyObject = myEntitiesObject.NextRecord() //pseudocode } } 

View:

  <Grid DataContext="{Binding MyObject}"> <TextBlock Text="{Binding MyText}"/> </Grid> 
+3
source

An extremely simple, but not very elegant solution, which, in my opinion, will meet the needs: when switching records, set the DataContext to null, and then return to ViewModel.

However, there are perhaps more elegant alternatives that require more work to meet all requirements. See Ananda's answer for improving this.

0
source

The tag in the view must have the mode attribute and UpdateSourceTrigger with values.

-one
source

Source: https://habr.com/ru/post/1502721/


All Articles