0

C# allows the creation of a property as below:

public string SomeRandomText
{
    get; set;
}

The framework handles the creation of the backing variable for this property. How can I have such a property and still have change notification?

Is this allowed in a class that implements INotifyPropertyChanged?

public string SomeRandomTextBeingNotified
{
    get;
    set
    {
        NotifyPropertyChanged("SomeRandomTextBeingNotified");
    }
}
Harsha
  • 661
  • 1
  • 8
  • 21
  • 1
    You just can't. You need to use fields and refer to them explicitely in your property for both getter and setter. + Do all other processing required like calling `NotifyPropertyChanged`. – Guillaume Nov 27 '12 at 06:36
  • 2
    Actually you CAN but you need to post process the bytecode, much like postsharp does. – TomTom Nov 27 '12 at 06:38
  • @TomTom That's true, but I'm not sure it worth the trouble in this case. – Guillaume Nov 27 '12 at 06:39

5 Answers5

3

You can't use automatic properties when trying to use this. You'll need to creating a backing store:

private string _someRandomText;
public string SomeRandomText {
    get { return _someRandomText; }
    set 
    {
        _someRandomText = value;
        NotifyPropertyChanged("SomeRandomText");
    }
}
Rob
  • 3,276
  • 2
  • 22
  • 25
  • Oh. Wish it were allowed. Code would have looked cleaner. :( – Harsha Nov 27 '12 at 06:39
  • Would appreciate it if you marked the answer as accepted. Possibly more important: you may want to submit this as feedback at the Microsoft Connect site for Visual Studio. http://connect.microsoft.com/VisualStudio – Rob Nov 27 '12 at 06:41
  • @Harsha I don't think it would be cleaner. If we assume the second example in your question is possible, how does the compiler know if it's auto-properties or you are actually doing something and not setting whatever backing field? – Guillaume Nov 27 '12 at 06:41
  • Ah - code analysis? Like any non stupid tool would do. If PostSharp can do it, the Compiler also can do it. – TomTom Nov 27 '12 at 06:44
  • @Guillame: True. I understand that part of it. It was just to confirm that for myself that I asked the question. :) – Harsha Nov 27 '12 at 06:45
  • One further question. I am using an ObservableCollection of for a items control. Do I need to implement the property with NotifyPropertyChanged for all changes to reflect? – Harsha Nov 27 '12 at 06:45
  • @TomTom In this case, how does the developer reading this line of code 3 years after it was written knows what is supposed to happen...? I don't *feel* it's clean. – Guillaume Nov 27 '12 at 06:47
  • @Rob: It didn't allow me although I tried as soon as I got the answer. I need to wait for about another 5-10 minutes before it allows me to accept the answer. :) – Harsha Nov 27 '12 at 06:48
1

To make code look cleaner, you can use attributes for INotifyPropertyChanged.

Easy usage of INotifyPropertyChanged with Property-Attribute

Have a look at this Use of Attributes... INotifyPropertyChanged

Community
  • 1
  • 1
Tilak
  • 30,108
  • 19
  • 83
  • 131
1

Actually you can, but you basically need to change the bytecode post C# compiler.

This may sound like a lot of work, but this is one of the easier postprocessing steps that for example PostSharp includes.

http://www.sharpcrafters.com/solutions/notifypropertychanged

http://www.sharpcrafters.com/blog/post/Recording-Automate-INotifyPropertyChanged-with-Karol-Waledzik-from-Internetium.aspx

A lot more functionality is available ;)

Otherwise note that

enter code hereenter code here`NotifyPropertyChanged("SomeRandomTextBeingNotified");

is bad code. I do all that in one field update method:

set 
{
    OnUpateField (ref _someRandomText, value);
}

The update method does all - check for equality (you do NOT want to trigger when new value = old value), then trigger updates as needed. It gets the property name through the calling method third parameter that is automatically set by the compiler. Alternatives are using a LINQ statement ( ref someRandomText, value, this->SomeRandomText). I never would love a string there that does not get renamed on refactoring ;)

TomTom
  • 61,059
  • 10
  • 88
  • 148
1

If you don't have a base class, something like this is cake and very flexible:

public class NotificationObject : INotifyPropertChanged
{
    private readonly Dictionary<string, object> Properties = new Dictionary<string, object>();

    public event PropertyChangedEventHandler PropertyChanged;

    protected TType Get<TType>(string propertyName)
    {
        object value;
        return Properties.TryGetValue(propertyName, out value) ? (TType)value : default(TType);
    }

    protected void Set<TType>(TType value, string propertyName, params string[] dependantPropertyNames)
    {
        Properties[propertyName] = value;
        OnPropertyChanged(propertyName);
        if (dependantPropertyNames != null)
        {
            foreach (string dependantPropertyName in dependantPropertyNames)
            {
                OnPropertyChanged(dependantPropertyName);
            }
        }
    }

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

This can be used like this:

public SomeObjectThatNeedsToNotifySomething : NotificationObject
{
    public int SomeValue
    {
        get { return Get<int>("SomeValue"); }
        set { Set<int>(value, "SomeValue", "SomeAggregateValue"); }
    }

    public int SomeOtherValue
    {
        get { return Get<int>("SomeOtherValue"); }
        set { Set<int>(value, "SomeOtherValue", "SomeAggregateValue"); }
    }

    public int SomeAggregateValue
    {
        get { return SomeValue + SomeOtherValue; }
    }
}

If you already have a base class and need to just implement the INotifyPropertyChanged interface, @Rob is correct, provide a backing field and fire the event.

taylorjonl
  • 869
  • 9
  • 15
1

There is no such thing as semi-automatic properties. Nevertheless, there are quite a few ways to implement INotifyPropertyChanged that don't require the burdensome imperative code.

1) Mentioned before: PostSharp, an aspect oriented and commercial project.

2) Creating a Castle DynamicProxy solution. A sample can be found here, actually there's plenty of others out there.

It's worthwhile investing some time in a generic solution, the boilerplate code can get vexing after a while and is prone to errors.

Sebastian Edelmeier
  • 4,095
  • 3
  • 39
  • 60