28

I know that there are solutions out there for implementing INotifyPropertyChanged, but none of them are as simple as: reference this library, create/add this attribute, done (I'm thinking Aspect-Oriented Programming here). Does anyone know of a really simple way to do this? Bonus points if the solution is free.

Here are some relevant links (none of which provide a simple enough answer):

bummi
  • 27,123
  • 14
  • 62
  • 101
Pat
  • 16,515
  • 15
  • 95
  • 114

6 Answers6

31

Try this https://github.com/Fody/PropertyChanged

It will weave all properties of types that implement INotifyPropertyChanged and even handles dependencies.

Your Code

public class Person : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public string GivenNames { get; set; }
    public string FamilyName { get; set; }

    public string FullName
    {
        get
        {
            return string.Format("{0} {1}", GivenNames, FamilyName);
        }
    }

}

What gets compiled

public class Person : INotifyPropertyChanged
{

    public event PropertyChangedEventHandler PropertyChanged;

    private string givenNames;
    public string GivenNames
    {
        get { return givenNames; }
        set
        {
            if (value != givenNames)
            {
                givenNames = value;
                OnPropertyChanged("GivenNames");
                OnPropertyChanged("FullName");
            }
        }
    }

    private string familyName;
    public string FamilyName
    {
        get { return familyName; }
        set 
        {
            if (value != familyName)
            {
                familyName = value;
                OnPropertyChanged("FamilyName");
                OnPropertyChanged("FullName");
            }
        }
    }

    public string FullName
    {
        get
        {
            return string.Format("{0} {1}", GivenNames, FamilyName);
        }
    }    

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

Or you can use attributes for more fine grained control.

Simon
  • 33,714
  • 21
  • 133
  • 202
  • Fody capabilities are limited, it handles dependencies only in class itself and doesn't propagate properties dependent on a property of some nested view model. This is something that PostSharp can offer. – KolA May 27 '14 at 03:33
3

Here is an article showing how to handle this via PostSharp.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • Thanks Reed. I added a note clarifying that the ideal solution would be much cheaper than $200 (for PostSharp). I know that there is a PS version that is free, but I wasn't able to achieve my goal with that version. – Pat Jan 17 '11 at 20:18
3

Simon's answer is the solution, but here's my code and a screenshot for reference. I am using Prism (with MEF - ignore the attributes on the class), so I inherit from NotificationObject for INotifyPropertyChanged. (It defines a RaisePropertyChanged method, so you have to tell NotifyPropertyWeaver that in your project file.)

The Class

using System.ComponentModel.Composition;
using Microsoft.Practices.Prism.ViewModel;

[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class SignControllerViewModel : NotificationObject
{
    public string Uri { get; set; }
}

The Project File

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <!-- snipped -->
    <UsingTask TaskName="NotifyPropertyWeaverMsBuildTask.WeavingTask" AssemblyFile="$(SolutionDir)lib\NotifyPropertyWeaverMsBuildTask.dll" />
    <Target Name="AfterBuild">
        <NotifyPropertyWeaverMsBuildTask.WeavingTask
                    TargetPath="$(TargetPath)"
                    TryToWeaveAllTypes="true"
                    EventInvokerName="RaisePropertyChanged"
                    MessageImportance="High"/>
    </Target>
</Project>

The Reflector Code

Code after INPC has been weaved into it.

Community
  • 1
  • 1
Pat
  • 16,515
  • 15
  • 95
  • 114
  • I will be creating a new wiki page shortly that shows the recommended settings for Prism, Caliburn, Caliburn Micro and MVVMLight – Simon Jan 17 '11 at 22:20
  • I would recommend trying not using NotificationObject. All it gives you is the RaisePropertyChanged method. If you just implement INotifyPropertyChanged in a model NotifyPropertyWeaver will inject that method for you. – Simon Jan 17 '11 at 22:22
2

There is a project called Polymod. Which offers what you are looking for. It does have some some cool features such as defining self-updating formulas. E.g. If Sum = A + B, then PropertyChanged is called on Sum when A or B is changed.

It also works with Rules Engine out-of-the-box to give you validation as well. Because it is extensible, it is possible to use other Validation Frameworks as well.

Aspect-Orientated programming at its best!

Arnaud
  • 430
  • 1
  • 3
  • 13
2

There is also UpdateControls.NET. I haven't used it, and it looks like more work than notifypropertyweaver, but it might be good. From the website:

Data binding without INotifyPropertyChanged

Update Controls does not require that you implement INotifyPropertyChanged or declare a DependencyProperty. It connects controls directly to CLR properties. It discovers dependencies upon data through layers of intermediate code. This makes it perfect for the Model/View/ViewModel pattern; no extra code is needed in the ViewModel, which sits between the Model and the View.

Wrap the DataContext of your Window. The wrapper not only implements INotifyPropertyChanged for all of your object's properties, it also automatically detects their dependencies on other properties. There is no base class or interface to implement.

Pat
  • 16,515
  • 15
  • 95
  • 114
  • 1
    Thanks for the mention. Update Controls is a dependency tracking library. But it is not a drop-in implementation of INotifyPropertyChanged. Yes, it is more work than Notify Property Weaver. So it's not exactly what you were asking for in the question. – Michael L Perry Nov 06 '13 at 21:49
1

There is also KindOfMagic which is very simple to use. Just create a "Magic" attribute and apply it. https://www.nuget.org/packages/KindOfMagic

bN_
  • 772
  • 14
  • 20