Although there is nothing manifestly wrong with adding the OnPropertyChanged
method to every class that implements INotifyPropertyChanged
(apart from violating the DRY principle), it makes sense to extract the change notification code into a reusable class, because this allows you to not only reduce boilerplate code but also to add other features to the event-raising code, such as improving support for multithreaded apps and implementing INotifyPropertyChanging
(as well as INotifyPropertyChanged
).
The WPUnleashed project in the downloadable sample code includes such a class, named PropertyChangeNotifier
. The ViewModelBase
class delegates change notification to a PropertyChangeNotifier
instance.
Throughout this book you frequently see viewmodel properties (with backing fields) resembling the following:
string foo;
public string Foo
{
get
{
return foo;
}
set
{
Assign(ref foo, value);
}
}
Here, the name of the property, the current value, and the new value are passed to the base class’s Assign
method. The following excerpt shows the signature of the Assign
method:
public AssignmentResult Assign<TField>(
ref TField field,
TField newValue,
[CallerMemberName] string propertyName = "")
{
...
}
The Assign
method updates the field value, while also offering the following advantages:
The application’s Dispatcher
automatically raises the PropertyChanged
event on the UI thread if called from a non-UI thread. This eliminates the need to add Dispatcher.BeginInvoke
calls to a viewmodel to avoid cross-thread errors.
The Assign
method also raises a PropertyChanging
event. PropertyChangeNotifier
implements INotifyPropertyChanging
interface as well as INotifyPropertyChanged
and allows a subscriber to cancel an update if desired.
PropertyChangeNotifier
assists the viewmodel in remaining UI technology agnostic. That is, retrieving an application’s Dispatcher
in a Windows Phone app is done differently in a WPF application.
PropertyChangeNotifier
uses a weak reference to its owner, thereby preventing memory leaks from occurring when targets fail to unsubscribe from events.
The single line Assign
method reduces the amount of boilerplate code in properties.
The return value of the Assign
method is an AssignmentResult
enum value, whose values are described in the following list:
Success—The assignment occurred and the field value now equals the new value.
Cancelled—A subscriber to the PropertyChanging
event cancelled the assignment. This relies on a custom extension to the INotifyPropertyChanging
event.
AlreadyAssigned—No assignment was made because the existing field value was already equal to the new value.
OwnerDisposed—The PropertyChangeNotifier
uses a weak reference to the object for which it is providing property changing monitoring. This value indicates that no assignment was performed because the owner object has been disposed.
Because property change notification is such a common requirement of model and viewmodel classes, for the sake of convenience a NotifyPropertyChangeBase
class is also provided in the downloadable sample code. It leverages an instance of the PropertyChangeNotifier
, and can be used as a base class for any class that needs INotifyPropertyChanged
to be implemented.
In particular, the ViewModelBase
class inherits from this class (see Figure 2.10).
The implementation details of the PropertyChangeNotifier
are lengthy and are not included in this section. However, you can find an article already covering the topic at http://danielvaughan.org/post/Property-Change-Notification-using-a-Weak-Referencing-Strategy.aspx.
Before moving on to commanding, be assured that you do not need to use the property notification system presented here in your own projects. If you are happy using the traditional approach to INPC, that is perfectly fine. Be mindful, however, that a lot of the phone SDK APIs have events that do not always return on the UI thread, and you may need to rely more heavily on the Dispatcher
to prevent cross-thread errors.
3.145.131.238