Skip to content

NotificationInterception

SimonCropp edited this page Mar 21, 2013 · 4 revisions

Introduction

Sometimes it is helpful to be able to intercept call to OnPropertyChanged. For example

  • Logging all property sets
  • Performing some action before or after OnPropertyChanged
  • Choose to not fire OnPropertyChanged under certain circumstances
  • Executing OnPropertyChanged on the UI thread

Enter PropertyChangedNotificationInterceptor

All the points above can be achieved by having a static class named PropertyChangedNotificationInterceptor in your assembly. The class should look as follows

public static class PropertyChangedNotificationInterceptor
{
  public static void Intercept( object target, Action onPropertyChangedAction, string propertyName)
  {
    onPropertyChangedAction();
  }
}

The parameters are as follows

  • target: the instance of the object that OnPropertyChanged is being fired on
  • onPropertyChangedAction: a delegate used to fire OnPropertyChanged
  • propertyName: the name of the property being notified

Example Usage : Executing OnPropertyChanged on the UI thread

Often properties will be changed on a different thread to the UI. This is particularly common in Silverlight applications. Unfortunately changing the UI, which occurs when a databound property changes, is not supported in Silverlight or WPF. The workaround is to "dispatch" the property changed event to the UI thread.

PropertyChangedNotificationInterceptor

public static class PropertyChangedNotificationInterceptor
{
  public static void Intercept(object target, Action onPropertyChangedAction, string propertyName)
  {
    Application.Current.Dispatcher.Invoke(onPropertyChangedAction);
  }
}

Your Class

public class Person : INotifyPropertyChanged
{
  public string Name { get; set; }

  public event PropertyChangedEventHandler PropertyChanged;
}

What Gets Compiled

public class Person : INotifyPropertyChanged
{
  private string name;

  public event PropertyChangedEventHandler PropertyChanged;

  public virtual void InnerOnPropertyChanged(string propertyName)
  {
    var propertyChanged = PropertyChanged;
    if (propertyChanged != null)
    {
      propertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
  }

  public virtual void OnPropertyChanged(string propertyName)
  {
    Action action = () => InnerOnPropertyChanged(propertyName);
    PropertyChangedNotificationInterceptor.Intercept(this, action, propertyName);
  }

  public string Name
  {
    get
    {
      return name;
    }
    set
    {
      name = value;
      OnPropertyChanged("Name");
    }
  }
}

Property values

If you want to get access to the property values without reflection you can use a similar approach to what is described in BeforeAfter. To achieve this change the signature of PropertyChangedNotificationInterceptor.Intercept to be as follows.

public static class PropertyChangedNotificationInterceptor
{
  public static void Intercept(object target, Action onPropertyChangedAction, 
                               string propertyName, object before, object after)
  {
    onPropertyChangedAction();
  }
}

Where before and after with be the values of the property before and after it is set.

Implementing your own OnPropertyChanged

For classes that already implement OnPropertyChanged method then having a PropertyChangedNotificationInterceptor class will have no effect on those classes. If you want to dispatch event to the UI thread then you can do this yourself in OnPropertyChanged.