Taoffi's blog

prisonniers du temps

Xamarin forms – extending the BindableObject

 

This a follow up to my post about avoiding strings in notifying property change events.

In fact, objects deriving from BindableObject (Views, Pages…) are some of the most common places where we do notify property changes.

These notifications are naturally done using the OnPropertyChanged method of the root BindableObject. Which is presented as:

 

protected virtual void OnPropertyChanged([string propertyName = null])

Member of Xamarin.Forms.BindableObject
Summary:

Call this method from a child class to notify that a change happened on a property.
Parameters:

propertyName: The name of the property that changed.
Remarks:

A Xamarin.Forms.BindableProperty triggers this by itself. An inheritor only needs to call this for properties without Xamarin.Forms.BindableProperty as the backend store.

 

So if you have a property that requires change notification, you would write:

    this.OnPropertyChanged("myPropertyName");

 

Which brings again the string constant problem: if you, one day, change the name of your property, you should remember visiting all code that may use this name in a string constant… hard and risky labor!

 

I thought of extending the BindableObject by providing a new OnPropertyChanged method using the Linq.Expressions to avoid string constants. That cannot be straightforward though because the BindableObject's OnPropertyChanged is protected!

 

For now, I found this solution. Please feel free to change or adapt to your needs. If you may find a better way, I would be happy to hear about your solutions!

 

The recipe

Define a delegate signature of a method to be called:

    public delegate void PropertyChangedHandler(string propertyName); 

 

 

Define a class for this (and future) extensions:

    public static class BindableObjectExtensions 

 

 

Include this extension method in the class:

 

public static void OnPropertyChangedExt<TProperty>(this BindableObject obj,
                    Expression<Func<TProperty>> property,
                    PropertyChangedHandler propertyChangedHandler)
{
        if (property == null || propertyChangedHandler == null)
            return;


        string        name = GetPropertyName(property);
        propertyChangedHandler.Invoke(name);
}

 

The GetPropertyName helper method:

 

public static string GetPropertyName<TProperty>(Expression<Func<TProperty>> property)
{
    if (property == null)
        return null;


    var expression = property.Body as MemberExpression;


    if (expression == null || expression.Member == null)
        return null;


    return expression.Member.Name;
}



 

Sample usage

 

public class TestBindableExtension: BindableObject
{
    string        _test        = "Test";


    public string TestProperty
    {
        get { return _test; }
        set
        {
            _test = value;
            this.OnPropertyChangedExt(() => TestProperty, this.OnPropertyChanged);
        }
    }



 

Comments are closed