INotifyPropertyChanged with PostSharp 1.5

If you are doing WPF development, most likely you are tired of writing property implementations that raise PropertyChanged event manually:

public class MainWindowViewModel : ViewModel
{
    private string _message;

    public string Message
    {
        get
        {
            return _message;
        }
        set
        {
            _message = value;
            OnPropertyChanged("Message");
        }
    }

    // ...
}

PostSharp is a great tool to make such things simplier.

Let’s look at the specific ViewModel class that has a Message property that is bound to some UI element using XAML:

public class MainWindowViewModel : ViewModel
{
    [RaisePropertyChanged]
    public string Message { get; set; }

    // ...
}

Notice the RaisePropertyChanged attribute, which we’ll implement later.

Here’s our base ViewModel class that provides actual implementation of the INotifyPropertyChanged interface:

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged
        = delegate { };

    public void OnPropertyChanged(string propertyName)
    {
        PropertyChanged(this,new PropertyChangedEventArgs(propertyName));
    }
};

Finally the PostSharp attribute:

[Serializable]  // required by PostSharp
public class RaisePropertyChangedAttribute : OnMethodBoundaryAspect
{
    private string _propertyName;

    /// <summary>
    /// Executed at runtime, after the method.
    /// </summary>
    public override void OnExit(MethodExecutionEventArgs eventArgs)
    {
        ViewModel viewModel = (ViewModel)eventArgs.Instance;
        viewModel.OnPropertyChanged(_propertyName);
    }

    public override bool CompileTimeValidate(MethodBase method)
    {
        if (IsPropertySetter(method))
        {
            _propertyName = GetPropertyName(method);
            return true;
        }
        return false;
    }

    private static string GetPropertyName(MethodBase method)
    {
        return method.Name.Replace"set_", "");
    }

    private static bool IsPropertySetter(MethodBase method)
    {
        return method.Name.StartsWith("set_");
    }
};

Note that we are validating if the method is in fact a property only during compilation time using CompileTimeValidate method.

During compile time appropriate invocations of OnPropertyChanged method will be injected after every set operation applied to the Message property.

Tags: , , ,

5 Responses to “INotifyPropertyChanged with PostSharp 1.5”

  1. Marcin Obel Says:

    Does the PostSharp allow to put such attribute on class definition instead of property?
    It would be nice to have this attribute on base ViewModel and nothing on properties (less work and convention over configuration at the same time).

  2. Limilabs support Says:

    Yes, you can put the attribute on the class level.
    In such case all class properties will raise appropriate PropertyChanged events.

    Although I think that in PostSharp 1.5 it can not be the base class – PostSharp attributes are not inherited.

  3. Blog » Blog Archive » INotifyPropertyChanged with lambdas Says:

    […] One that I particularly like is by using PostSharp to implement INotifyPropertyChanged. […]

  4. INotifyPropertyChanged with custom targets Says:

    […] can use PostSharp for that, you should at least use lambda expressions instead of […]

  5. TimothyP Says:

    Thnx for the example… seen other examples out there much more complicated to start out with. One thing I’d like to note is that you could use “dynamic instance = args.Instance;” to expand the use to anything that has an OnPropertyChanged(string); method. For example I have objects that need change notification.

Questions?

Consider using our Q&A forum for asking any questions.