Jounce Part 8: Raising Property Changed

This will be a shorter bit for an interesting topic. I’ve noticed a few posts and discussion around raising the property changed notification. This continues to be the sore spot for MVVM. It creates quite a bit of ceremony for what is a fairly common piece of functionality that shouldn’t be so hard to create.

Jounce supports all of the common ways of doing this, but there is a third that I learned from a colleague of mine (Keith Rome) that I added and think bears some attention.

The most common approach is to use the “magic string” technique (which many developers automatically cringe at) and do something like this:

public string FirstName
{
    get { return _firstName; }
    set
    {
        _firstName = value;
        RaisePropertyChanged("FirstName");
    }
}

The problem there of course is that it is too easy to type the property wrong. Coders who typically “cut and paste” might forget to update this and then they’ll find themselves raising the wrong property.

The next iteration types the property a bit and gets rid of magic strings. It does this by allowing a lambda expression to be passed in. The expression tree is parsed and the property name is extracted. Some extra validation can even make sure it’s inside a property – but there is still no guarantee you aren’t raising the wrong property, you just know you are raising some property.

public string FirstName
{
    get { return _firstName; }
    set
    {
        _firstName = value;
        RaisePropertyChanged(()=>FirstName);
    }
}

So the third method is a little more safe. Not only does it avoid magic strings, but I can get out of the ceremony of passing a weird lambda expression, and I can guarantee it will raise the notification for the correct property. Before I talk about how this works, let me show you the code:

public string FirstName
{
    get { return _firstName; }
    set
    {
        _firstName = value;
        RaisePropertyChanged();
    }
}

This will throw an exception if it’s not in a setter. And it will always capture the current property. I still have to make a call, but no magic strings and we’ve reduced the ceremony somewhat. How does it work?

The trick is the context of execution. All of these methods have a little overhead (the string method actually has the best performance) but in most applications if the performance hit is in your setters, you’ve probably got worse issues farther up the stack.

Speaking of the stack, that’s exactly what we use. We simply walk the stack frames up from the setter to find the name of the setter method itself. The convention for properties is set_propName so we look up where we are at and grab the propName.

Here’s the code:

public virtual void RaisePropertyChanged()
{
    var frames = new System.Diagnostics.StackTrace();
    for (var i = 0; i < frames.FrameCount; i++)
    {
        var frame = frames.GetFrame(i).GetMethod() as MethodInfo;
        if (frame != null)
            if (frame.IsSpecialName && frame.Name.StartsWith("set_"))
            {
                RaisePropertyChanged(frame.Name.Substring(4));
                return;
            }
    }
    throw new InvalidOperationException("NotifyPropertyChanged() can only by invoked within a property setter.");
}

Notice once we extract the property name, we just pass it along to the method that takes a happy string.

There you have it – another way to do the deed with a little more overhead but a lot less ceremony.

Jeremy Likness

Stay Informed

Sign up for the latest blogs, events, and insights.

We deliver solutions that accelerate the value of Azure.
Ready to experience the full power of Microsoft Azure?

Atmosera is thrilled to announce that we have been named GitHub AI Partner of the Year.

X