Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Raising a propertychanged event without adding a private variable

Tags:

c#

I have a property which looks like this.

public int NumberOfElephants { get; set; }

this property is in an observablecollection and it has to notify another property that it has changed.

how would i do the following

public int NumberOfElephants { get; set { OnPropertyChanged("totalAnimals"); }

without the code needing to be like this

private int _numberOfElephants;
public int NumberOfElephants { 
    get { 
        return _numberOfElephants; 
    } 

    set { 
        _numberOfElephants = value; 
        OnPropertyChanged("totalAnimals"); 
    } 
}
like image 379
Joseph Le Brech Avatar asked Oct 21 '11 08:10

Joseph Le Brech


People also ask

How do you implement PropertyChanged?

To implement INotifyPropertyChanged you need to declare the PropertyChanged event and create the OnPropertyChanged method. Then for each property you want change notifications for, you call OnPropertyChanged whenever the property is updated.

What is INotifyPropertyChanged in C#?

The INotifyPropertyChanged interface is used to notify clients, typically binding clients, that a property value has changed. For example, consider a Person object with a property called FirstName .

What is OnPropertyChanged in WPF?

INotifyPropertyChanged is an interface used by binding sources (i.e. the DataContext) to let the user interface or other components know that a property has been changed. WPF automatically updates the UI for you when it sees the PropertyChanged event raised.


2 Answers

You don't. You can't.

Automatically implemented propertieS only work when the property is trivial - when no code is needed for the get/set beyond "return the variable's value" or "set the variable's value". You can make it shorter with reformatting, of course... I'd write that as:

private int numberOfElephants;
public int NumberOfElephants {
    get { return numberOfElephants; }

    set {
        _numberOfElephants = value; 
        OnPropertyChanged("totalAnimals"); 
    } 
}

Actually, I'd use "opening brace on a line on its own" for the start of the set and the start of the property, but I've kept your favoured style for those. But having "single expression get/set implementations" on a single line can make classes with lots of properties much cleaner.

like image 153
Jon Skeet Avatar answered Sep 21 '22 22:09

Jon Skeet


As an alternative to Jon's answer, you can get tools that will do this via IL weaving, such as NotifyPropertyWeaver, also available as a tool through the VS Gallery

For your sample, you should be able to have something like the following, according to their doco on Attributes:

[NotifyProperty(AlsoNotifyFor = new[] { "TotalAnimals" })]
public int NumberOfElephants { get; set; }

public int TotalAnimals { get; set; }

However, based on the example below from their site it might not be required depending on the implementation of TotalAnimals:

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;

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

    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 virtual void OnPropertyChanged(string propertyName)
    {
        var propertyChanged = PropertyChanged;
        if (propertyChanged != null)
        {
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
like image 33
jeffora Avatar answered Sep 23 '22 22:09

jeffora