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.

Clone this wiki locally