DCSIMG
NotifyingObject for WPF & Silverlight - Essential XAML

NotifyingObject for WPF & Silverlight

There are many ways notifying on property changed, and I think the most popular one is using the lambda expression solution:

public class Ball : Model 
{
    private double _velocity;

    public double Velocity
    {
        get { return _velocity; }
            
        set
        {
            if (_velocity != value)
            {
                _velocity = value;
                NotifyPropertyChanged(() => Velocity);
            }
        }
    }
}

I’ve to say that using the lambda solution is cool and type safety.

But, why should I bother creating a field member for each property, set it only if not equals to the new value and only then call the NotifyPropertyChanged method?

I would like to do something like this:

public class Ball : Model
{
    public double Velocity
    {
        get { return GetValue(() => Velocity); }
        set { SetValue(() => Velocity, value); }
    }
}

And to do so the Model class should derive from this class:

public abstract class NotifyingObject : INotifyPropertyChanged
{
    private readonly Dictionary<string, object> _values = new Dictionary<string, object>();

    public event PropertyChangedEventHandler PropertyChanged;

    protected void SetValue<T>(Expression<Func<T>> propertySelector, T value)
    {
        string propertyName = GetPropertyName(propertySelector);

        _values[propertyName] = value;
        NotifyPropertyChanged(propertySelector);
    }

    protected T GetValue<T>(Expression<Func<T>> propertySelector)
    {
        string propertyName = GetPropertyName(propertySelector);

        object value;
        if (_values.TryGetValue(propertyName, out value))
        {
            return (T)value;
        }

        return default(T);
    }

    protected void NotifyPropertyChanged<T>(Expression<Func<T>> propertySelector)
    {
        var propertyChanged = PropertyChanged;
        if (propertyChanged != null)
        {
            string propertyName = GetPropertyName(propertySelector);
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

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

    private string GetPropertyName(LambdaExpression expression)
    {
        var memberExpression = expression.Body as MemberExpression;
        if (memberExpression == null)
        {
            throw new InvalidOperationException();
        }

        return memberExpression.Member.Name;
    }
}

Of course you can extend this solution by adding actions before and after changing the value, add coercing, validation and other goodies from WPF DependencyProperty in generic, new fashion way.

public double Velocity
{
    get { return GetValue(() => Velocity); }
    set
    {
        SetValue(
            () => Velocity,
            value,
            (oldValue, newValue) => Debug.WriteLine(string.Format("{0}, {1}", oldValue, newValue)), // Callback
            newValue => Math.Max(Math.Min(10, newValue), 0), // Coercing
            newValue => newValue != null); // Validation
    }
}

Nice Coding!

Published Monday, October 11, 2010 5:16 PM by Tomer Shamam

Comments

# re: NotifyingObject for WPF & Silverlight

Tuesday, October 12, 2010 8:14 AM by Maxim

nice and simple :)

thanks.

# re: NotifyingObject for WPF & Silverlight

Tuesday, October 12, 2010 9:12 AM by Maxim

The "Big Hit" can be a solution for notification without passing property name or lambada expression, auto-extraction of property without any involvement of programmer. "Reflection" is "Heavy", "Postsharp" costs money and also "Heavy" during build process. Any ideas?

# re: NotifyingObject for WPF & Silverlight

Tuesday, October 12, 2010 10:41 AM by Tomer Shamam

Yes Maxim, you are right about the property name or lambda expression penalties.

I have another solution, which is using System.Diagnostics.StackFrame to extract the property name in the Get/Set or NotifyPropertyChanged base class method, so you can call it without parameters. Using this solution, you should check if the performance hit is fine for you.

Btw, if you're concerning about the performance of your application and not the syntactic sugar, don't forget that you’re using DataBinding which is already reflection based mechanism ;)

# re: NotifyingObject for WPF & Silverlight

Tuesday, October 12, 2010 1:26 PM by Maxim

I tested the option of extraction from "StackFrame", it's much slower in compare to manual notification.

# re: NotifyingObject for WPF & Silverlight

Tuesday, October 12, 2010 2:42 PM by Tomer Shamam

Yes I know, but comparing to string, it's safer. You should compare the perf to the lambda solution. Still, you're using data-binding which already has performance issues.

# re: NotifyingObject for WPF & Silverlight

Wednesday, February 16, 2011 4:04 PM by Saragani

The "Model" as you describe here is the actual model, or is it the ViewModel that the View is binded to?

Assuming that we have a true View -> ViewModel -> Model architecture and some logic of the application changes a property in the Model.

What would be the best way to reflect the changes to the view?

1) Have the XAML be for example: <TextBlock Text="{Binding Model.Text}" />

2) Raising a specific event for each property that get changed, so the ViewModel will update only the specific property within itself

3) Raising an event that will tell the ViewModel to refresh all it's properties from the model.

4) Having the Model inherit from INotifyPropertyChanged, and raise OnPropertyChanged("SomePropertyName") (Or use the Lambda Expression solution),

 and then have the ViewModel register to the PropertyChanged event and raise a OnPropertyChanged(e.PropertyName)?

Any other solutions/suggestions?

# re: NotifyingObject for WPF & Silverlight

Wednesday, February 16, 2011 4:21 PM by Tomer Shamam

Hi Saragani,

Both the Model and ViewModel can derive from NotifyingObject.

It's really depends on if you design the Model from scratch or it is generated by a tool.

In case that the Model is ready to be rendered and there is no need for additional “formatting” or “preparing” I would expose it from the ViewModel as is, but use DataTemplate to render it. In such case make sure it implements the INotifyPropertyChanged interface.

In case that the Model is not appropriate for rendering by the view, need additional UI related properties, you should wrap it with an appropriate view-model. In such case I would expose only relevant properties as new properties from the view-model. As for Model notification, it would be nice to have only one event unless it will be much harder to maintain.

Consider of using or creating a tool for handling the boilerplate code. Maybe t4 or something else.

Regards,

Tomer

# re: NotifyingObject for WPF & Silverlight

Wednesday, February 16, 2011 4:27 PM by Saragani

Thanks :-)

Leave a Comment

(required) 
(required) 
(optional)
(required) 

Enter the numbers above:
Powered by Community Server (Commercial Edition), by Telligent Systems