Aaron Thomas
Aaron Thomas

Reputation: 5281

Make a class suitable for Property Change Notification

To implement data binding in WPF, according to MS a "class needs to provide the proper property changed notifications." [ref here]

AFAIK, part of setting this up means taking the following steps, if not already set up in the class (ref this article on MSDN):

...

// Create the OnPropertyChanged method to raise the event 
protected void OnPropertyChanged(string name)
{
    PropertyChangedEventHandler handler = PropertyChanged;
    if (handler != null)
    {
        handler(this, new PropertyChangedEventArgs(name));
    }
}

If I already have many existing classes that do not take any of these steps, what is the best way to change these classes so they change only so far as is needed to make them meet these standards?

Upvotes: 5

Views: 3018

Answers (5)

Noman Khan
Noman Khan

Reputation: 92

I love this implementation with [CallerMemberName] in C# 5 as described here

protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
    ...
}

Just make the parameter optional and decorate it with the CallerMemberName attribute.

Your property now looks like this:

public DateTime Time
{
    get { return this.model.DateTime; }
    set
    {
        this.model.DateTime = value;
        NotifyPropertyChanged();
    }
}

Upvotes: 5

Dan Puzey
Dan Puzey

Reputation: 34198

If you want the minimum-possible-code-impact solution, then you want the Fody PropertyChanged weaver. This is installed as a NuGet package with Install-Package PropertyChanged.Fody, or through the VS package manager dialogue.

Once installed, you can mark a class with the [ImplementPropertyChanged] attribute, and your job is basically done. The weaver will add the relevant event calls at compile time by manipulating the generated IL, which means that you don't have to explicitly implement the interface or the event calls in code. You can keep your auto-implemented property syntax, too!

The linked docs provide details of more advanced cases but, in my experience, the out-of-box behaviour is sufficient for almost all needs.

Upvotes: 5

Patrick
Patrick

Reputation: 736

i usually like to use this implementation to notify the changes in my properties

class IWillNotifyYou : INotifyPropertyChanged
{
    private int _firstProperty;
    public int FirstProperty
    {
        get { return _firstProperty; }
        set
        {
            if (value != _firstProperty)
            {
                _firstProperty = value;
                OnPropertyChanged("FirstProperty");
            }
        }
    }

    private string _secondProperty;
    public string SecondProperty
    {
        get { return _secondProperty; }
        set
        {
            if (value != _secondProperty)
            {
                _secondProperty = value;
                OnPropertyChanged("SecondProperty");
            }
        }
    }

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


    public event PropertyChangedEventHandler PropertyChanged;
}

note that you could create a specialized event with the name of the property like FirstPropertyChanged

Upvotes: 1

TyCobb
TyCobb

Reputation: 9089

You'll need to identify what role your existing classes play now. WPF is most beneficial using MVVM (Model-View-ViewModel). Identifying the role of your current classes will help determine what needs to be changed (if anything).

Assuming your existing classes are Business Objects, it is up to you to decide whether or not you even need to implement INotifyPropertyChanged. WPF is easiest to work with by binding to ViewModel. The ViewModel is what actually handles the data between the View (WPF screen) and the Model.

The Model can implement INotifyPropertyChanged, but it does not have to. The ViewModel will hold whatever properties are needed for that specific screen (or control) and is probably the path you will want to explore so you do not completely 180* your existing business objects.

Upvotes: 0

Contango
Contango

Reputation: 80272

Add ": INotifyPropertyChanged" after your class definition:

Public class Test : INotifyPropertyChanged 
{
}

Accept ReSharpers recommendation to implement the interface for this class (you might have to install ReSharper for this to work).

Then, in the setter for any property, add this:

OnPropertyChanged("PropertyName")

This means that you can now bind properties in the XAML to this property in this class.

Upvotes: -1

Related Questions