Implementing INotifyPropertyChanged: The Traditional Approach

,

The INotifyPropertyChanged interface has a single event called PropertyChanged. The implementation of INotifyPropertyChanged ordinarily includes the following construct:

public event PropertyChangedEventHandler PropertyChanged;

protected virtual void OnPropertyChanged(
        [CallerMemberName] string propertyName = null)
{
    PropertyChangedEventHandler tempEvent = PropertyChanged;
    if (tempEvent != null)
    {
        tempEvent(this, new PropertyChangedEventArgs(propertyName));
    }
}

The CallerMemberName attribute is used by a new compiler feature that automatically passes the name of the calling member to the target method. No longer is it necessary in most cases to pass the name of a property as a loosely typed string.


Note

To determine whether the PropertyChanged event field has any subscribers, it is copied to a temporary local variable, which allows you to then test whether it is null in a thread-safe manner. Without first obtaining a copy, another thread could potentially unsubscribe from the event after the null check but before the event is raised, which would inadvertently lead to a NullReferenceException being thrown.

An alternative that avoids the null check is to assign the event to an empty handler, as shown:

public event PropertyChangingEventHandler PropertyChanging = delegate {};


A property is then able to signal to a subscriber of the event that a property value needs updating, like so:

string foo;

public string Foo
{
    get
    {
        return foo;
    }
    set
    {
        if (foo != value)
        {
            foo = value;
            OnPropertyChanged();
        }
    }
}

When setting a property that is the source property of a data binding, the update must occur on the UI thread or an UnauthorizedAccessException will ensue. Source properties can be set from non-UI threads using the application’s Dispatcher as shown in the following excerpt:

Deployment.Current.Dispatcher.BeginInvoke(
    delegate
        {
            Foo = "bah";
        });

There are a number of reasons why peppering your code with BeginInvoke calls is not a good idea. First, it imposes an unnecessary threading model on your viewmodel code. Second, it can lead to code that need not be executed on the UI thread, creeping in to the delegate. And, third, it is pretty ugly and decreases the readability of your code.

The next section looks at extracting INPC into a reusable and UI thread friendly class.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.43.149