Why WPF binding handles INotifyPropertyChanged in two different ways? - wpf

I recently find out that wpf handles INotifyPropertyChanged in two different ways. I just wanna know what's the reason.
Let us take a normal twoway binding with validation true.
if you set a property from ui to viewmodel it goes like this.
setter call started
value set
INotifyPropertyChanged started
INotifyPropertyChanged done
setter done
getter called and done
IDataErrorInfo called and done
but if you set the property in your viewmodel it goes like this
setter call started
value set
INotifyPropertyChanged started
getter called and done
IDataErrorInfo called and done
INotifyPropertyChanged done
setter done

Changing property from UI to ViewModel may lead to deadlock kind of situation which might run into end less recursive calls in two way scenarios. In order to block this from happening, when WPF is making change to model, it will continue to track changes via INotifyPropertyChanged ,but this change will be queued in dispatcher queue, and it will be executed after its current update is finished.
Since the change in viewmodel is not initiated by WPF, WPF will not queue the operation, it will immediately execute the change.

Related

Combine CollectionChanged and PropertyChanged notifications in ObservableForPropertyHelper with ReactiveUI

I have a ReactiveObject ViewModel that contains an IObservableCollection and a regular property that raises INPC when it is modified (ie, vanilla WPF).
I want to implement an ObservableForPropertyHelper backed read-only that will re-evaluate whenever the regular property changes, or the collection changes (raises its CollectionChanged) event.
I know I can implement this using WhenAnyValue for the regular property, FromEventPattern to create an observable for the collectionchanged event, and then stitching them together with a CombineLatest. My question is - is there a less god-awful way to do this? Is there a built in ReactiveUI functionality that will help me achieve this?
You could swap the ObservableCollection for ReactiveUI's ReactiveCollection which exposes an IObservable for when the collection changes.
You could also use ReactiveUI's ObservableForProperty instead of WhenAny, which will be a little more succinct as you are only observing 1 property.
Other than that, what you have described is how I would do it.

MVVM: Notify view when model status changed

This is a specific question about the MVVM pattern best practice. I'm using MvvmLight Library.
It goes like this:
My model, say "Flight", implements some business logic that can start, pause and stop flights via methods. Each method does its logic to make the functionality happen whether it's playing stopping or pausing the flight. One important variable that changes is a status enum which indicates the flight status - playing, stopped, or paused. As said the status variable (and property) are defined in the Model.
On the other side the flight class is wrapped by a ViewModel class which contains a Status property that wraps the status variable in the flight model, and also RelayCommands that connect to the flight model play stop pause methods.
Here the problem begins:
When I execute one of the commands through the view, it executes the method in the model so that the status variable itself changes directly, but it only changes in the model.. The status property in the ViewModel doesn't know whether the wrapped variable have been changed, as it was changed directly... That means if some view element is binded to the status property, it won't change upon command execution..
I know several means to solve this but I'm asking for a fair solution that won't break the MVVM pattern (like using INotifyPropertyChanged in the flight class in the Model )
There is no magic bullet solution to this type of problem. Your ViewModel and Model need to be designed in a way that allows the information to propagate to the View; if this is not possible, then the design is flawed and needs to change.
Here's a couple of things you should look into:
If the Model's state-modifying methods are documented to execute synchronously, create methods on the ViewModel that forward the action to the Model and then immediately query its state. Use these methods for the implementation of the RelayCommands.
If the Model's methods are not synchronous then there should be some mechanism available to the Model's clients to notify them when the methods have completed. This can be done through continuation callbacks, events, or perhaps even with INotifyPropertyChanged.
As you mentioned above, your ViewModel should wrap Model at the following way:
class Model
{
public int State{get;private set;}
public void Fly()
{
State=1;
}
public void Stop()
{
State = 2;
}
}
class ViewModel : ViewModelBase
{
int State{ get{ Model.State;}}
...
OnFlyCommand()
{
Model.Fly();
NotifyPropertyChanged("State");
}
}
You could just call OnNotifyPropertyChanged just after the ViewModel executed the method on Model. That's not very elegant, but you just can't get any simpler without refactoring your Model class.
Do you know what properties have changed after the command is executed? I mean, can you explicitly raise change notification on specific set of properties or the set of modified properties is changing?
In the former case you invoke command and raise the event for those properties explicitly:
command.Execute();
NotifyPropertyChanged("PropA");
...
NotifyPropertyChanged("PropN");
In the second case you can either raise change notification event for every property of the Model class using reflection or you can use a smarter solution like PostSharp.Domain.Toolkit.
Best practice is to call viewmodel from command execution, than call model change from viewmodel, after which mark viewmodel state as changed

Initiate change of a DependencyProperty of a ViewModel with a Event of another Thread

I want to change a DependencyProperty of my ViewModel from a class which connects the application to a database.
This class raises events which should initiate a change of some properties in my ViewModel.
How can I realize that? I don't have the Dispatcher of the View.
I'm assuming you don't really have dependency properties on your viewmodels but rather normal C# properties which raises the PropertyChanged event.
If so, you should be fine already. Modify your properties from your background thread (normal concurrency issues apply obviously) and when they are bound to a WPF element's Dependency Property the runtime system will take care of marshalling the change to the proper thread (by using the view's Dispatcher object)
This works for normal properties, I'm not sure it works for ObservableCollections.
There are also different approaches for doing the marshalling inside the viewmodels. The simplest way is to just store the value of Dispatcher.CurrentDispatcher in your viewmodel's constructor. This works as long as your viewmodels are created on the UI thread.
One immediate solution to the problem is to capture the view's Dispatcher and store it on the view model when you create it, so you can Invoke/BeginInvoke the change to it in response to the event.
That being said, you should consider making your viewmodels use INotifyPropertyChanged with CLR properties rather than DependencyProperties to avoid issues like this. That way, any thread can make changes to your viewmodel and have the results reflected in the view.

Should I leave out INotifyPropertyChanged?

when I have a ViewModel, could there be cases where I can leave out INotifyPropertyChanged? I seem to get that this interface is used when you have multiple displays of a property in a GUI, so that when this property is edited, all the displays of the adjusted property get the new value. But what if you are fairly certain that UI will only have one display of the property?
I use NotifyPropertyWeaver - it generates property notification code for you. Then there is no reason why not to implement it in types that might potentially need it.
I'd always implement INotifyPropertyChanged because requirements might change.
The binding mode supports OneWay and OneTime so overhead can be reduced.
Inheriting from a base class will make it easy to implement the interface so I see no real advantages of not implementing INotifyPropertyChanged on a ViewModel.
It is OK to leave out INotifyPropertyChanged in two cases:
The property is not databound
The value of the property is never changed after the data binding is set up.
This is unlickly to be the case for a WPF ViewModel.

Does WPF-DataBinding support asynchronous updates

I changed accidentally the value of a BusinessObject-property that implements INotifyPropertyChanged from within a BackgroundWorker (BackgroundWorker.DoWork).
Amazingly, this led not to an error but actualized the text of the TextBlock that was bound to the property without any complaint.
Is the execution of asynchronous bindings part of the WPF binding engine or is this only a special case where the CheckAccess-test have been forgotten or ommited due to other considerations.
Bindings on scalar properties support updates from other threads, so you don't need to call Dispatcher.Invoke when updating a property of the model (or ViewModel). However, this is not true for binding to a collection: if you have a ItemsControl bound to an ObservableCollection<T>, changes to this collection must be done on the UI thread, as CollectionChanged events are not automatically forwarded to the UI thread. Alternatively, you could use a variant of ObservableCollection<T> that raises the event on the UI thread (here's a implementation)

Resources