Linking Property Change Notifications in Xamarin Forms (or WPF/Silverlight)

I’d like to share a really awesome bit of code that I’ve been using in my XAML applications for a while now… there are many frameworks and examples out there, but I’ve not yet seen anyone else using this exact technique before…

MVVM in XAML UI Applications

If you are building app UIs using XAML, then you are more likely than not also using the MVVM design pattern. The general idea is that your code which handles application logic, business rules, etc. gets placed into ViewModel classes, and all visual widgets/controls get placed into XAML views. Typically we would have one View per ViewModel, but that’s not a requirement at all (more like a generalized observation), and in fact there are some situations where we might want to have multiple Views for the same ViewModel (or break a complex ViewModel into multiple parts while still connecting to a single View). The ViewModels are supposed to capable of standing alone, and we use data bindings and command bindings to connect the two. This way, we can unit test our ViewModels thoroughly, and (sometimes) allow UX designers to dictate the XAML layout directly.

That’s all fairly normal and typical.

As we dig a little more deeply into the mechanisms of data binding, we learn that part of the “magic” is achieved by way of the INotifyPropertyChanged interface (which includes only one thing – an event named PropertyChanged). Whenever we modify the value of any property on our ViewModel, we are supposed to raise that PropertyChanged event, and the XAML runtime will respond by automatically updating the visual state of any controls which are being used to display that property’s data. There are countless example snippets of how to do this – some are rather extensive, but most are some variation on a standard boilerplate template. Typically, there would be some code that you need to add to a base class of your ViewModels, and then call a helper method in each of your property setters to raise the corresponding event. It’s not hard to imagine code that ends up looking like this:

public abstract class BaseViewModel : INotifyPropertyChanged {
    public event PropertyChangedEventHandler PropertyChanged;
    protected void RaisePropertyChanged([CallerMemberName] string propertyName) {
        var handler = PropertyChanged;
        if (handler == null) return;
        handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

public class MyViewModel : BaseViewModel {
    string _firstName;
    string _lastName;
    public string FirstName {
        get { return _firstName; }
        set {
            if (value == _firstName) return;
            _firstName = value;
            RaisePropertyChanged();
        }
    }
    public string LastName {
        get { return _lastName; }
        set {
            if (value == _lastName) return;
            _lastName = value;
            RaisePropertyChanged();
        }
    }
}

This all tends to work really well for simple scenarios… but what if your ViewModels need to be a lot more complicated than that? What if you have read-only properties that are computed from the values of other properties? What if you want to update commands as well (maybe changing a property value should also enable/disable a command)?

For those things we need something with a little more “oomph”.

Understanding Property Dependencies

Building upon the previous example, let’s suppose that we now want to add a “FullName” property. We might first naively define it as such:

    string _fullName;
    public string FullName {
        get { return _fullName; }
        set {
            if (value == _fullName) return;
            _fullName = value;
            RaisePropertyChanged();
        }
    }

But we would quickly see that this isn’t a wise implementation. Every time we assign either First or Last name, then we would need to recalculate and reassign the value for FullName. We might do this in our property setters, or we might do it elsewhere. And then what happens when something sets FullName directly? Do we parse the components back out? Bah!

No, we would change our design a bit. Clearly, FullName should be a read-only property – thus eliminating the need to parse anything. Our second version might look like this:

public class MyViewModel : BaseViewModel {
    string _firstName;
    string _lastName;
    string _fullName;
    public string FirstName {
        get { return _firstName; }
        set {
            if (value == _firstName) return;
            _firstName = value;
            _fullName = $"{_firstName} {_lastName}";
            RaisePropertyChanged();
            RaisePropertyChanged("FullName");
        }
    }
    public string LastName {
        get { return _lastName; }
        set {
            if (value == _lastName) return;
            _lastName = value;
            _fullName = $"{_firstName} {_lastName}";
            RaisePropertyChanged();
            RaisePropertyChanged("FullName");
        }
    }
    public string FullName {
        get { return _fullName; }
    }
}

Better, but still not great – we are computing the Full Name in two places. Our third iteration likely looks like this:

public class MyViewModel : BaseViewModel {
    string _firstName;
    string _lastName;
    public string FirstName {
        get { return _firstName; }
        set {
            if (value == _firstName) return;
            _firstName = value;
            RaisePropertyChanged();
            RaisePropertyChanged("FullName");
        }
    }
    public string LastName {
        get { return _lastName; }
        set {
            if (value == _lastName) return;
            _lastName = value;
            RaisePropertyChanged();
            RaisePropertyChanged("FullName");
        }
    }
    public string FullName {
        get { return String.Format ("{0} {1}", _firstName, _lastName); }
    }
}

And this is where we would normally stop, but something is still not right here. We still need to keep track of which properties affect which other properties, and then we need to make sure that we have the right series of RaisePropertyChanged() calls in each property setter. If we forget just one, or misspell one, then our ViewModel will not work correctly. And this is still a rather overly simplistic ViewModel example – code in the real world is significantly more complicated. A real app ViewModel could easily become difficult to maintain if we continue down this path.

Of course, the real problem isn’t the MVVM pattern, nor is it really in our ViewModel design itself. The real problem here is that the code which describes the dependencies between our various properties is scattered throughout the class. This is where my solution comes in – centralized management of the relationships between properties.

PropertyDependency

My solution to this problem is to abstract away the concept of what it means for one property to be dependent upon another property – and then take care of cascading the update notifications automatically. The idea is that you can configure the ViewModel in one place (the constructor), and in an easy-to-read form, and then the rest “just works”.

I also had a few other extra features in mind that are closely tied to this concept:

  1. In order to support complex linking scenarios where one property might be used as an input into multiple others, the mechanism should have a “fluent” API.
  2. Why stop with cascading property change notifications? When a property changes then I should also be able to run an arbitrary Action.
  3. And along those lines – I should also be able to generate and run an async Task.
  4. The code that needs to be written for classes that use this solution should be minimized as much as possible.
  5. Should not rely on the developer needing to specify strings where property names are needed.
  6. It seems useful to also be able to link property changes and actions/tasks to changes that originate in other ViewModel objects.

Let’s walk through how to use this solution, and explain things as we go…

Returning to the example above, the first thing is that we need to inherit from a class that understands this property dependency system. I have written a class named ObservableObject that serves this purpose (full source can be found in the link below) – but of course this code could just as well be relocated to your own ViewModel base class.

ObservableObject provides two key things: a way to define property dependencies, and a way to assign property values.

Assigning property values

When writing property setters for a ViewModel in a typical MVVM application, we find ourselves writing the same boilerplate code over and over. Every property needs a backing field. Every property should compare the newly assigned value with the current value, and only react if the value is actually changing. It should update the private field first, and then raise one or more change notifications. In ObservableObject, I have provided a function named SetPropertyValue() that performs all of these steps. It returns a boolean (indicating whether the value was actually modified), but you will almost never care about that. Using this is very simple – here is what our example class looks like with this new structure:

public class MyViewModel : ObservableObject {
    string _firstName;
    string _lastName;
    public string FirstName {
        get { return _firstName; }
        set { SetPropertyValue(ref _firstName, value); }
    }
    public string LastName {
        get { return _lastName; }
        set { SetPropertyValue(ref _lastName, value); }
    }
    public string FullName {
       get { return String.Format ("{0} {1}", _firstName, _lastName); }
    }
}

Declaring property dependencies

But how do we ensure that property change notifications are raised for the FullName property? This is where the PropertyDependency class comes in – it allows us to specify what else should happen when a property is updated. We access PropertyDependency definitions using the WhenPropertyChanges() method of ObservableObject. This would typically be done within the constructor:

    public MyViewModel() {
        WhenPropertyChanges(() => FirstName)
            .AlsoRaisePropertyChangedFor(() => FullName);
        WhenPropertyChanges(() => LastName)
            .AlsoRaisePropertyChangedFor(() => FullName);
    }

Awesome 🙂

Kicking it up a notch

Thus far we have established a link between these properties – in this case, updating the FirstName or LastName property will result in change notifications for that property as well as for the FullName property. For this trivial example it might not be obvious how useful this is, but let us consider making our ViewModel slightly more complicated. Perhaps we have a requirement to show the FullName in either “First_Last” format or “Last,_First” format. And perhaps we also have a requirement to show the person’s initials. And lastly, suppose we have a Save button in our UI design that should disable when either FirstName or LastName is left blank? That’s quite a few extra requirements, but also it’s much more like the kind of requirements a real-world application might have.

Let’s look at what it might take to implement these new requirements.

We will introduce a new boolean property called ShowLastNameFirst to control the formatting of the FullName property. We also need an Initials property and a command that is used when the user taps on our Save button. Let’s add those:

    bool _showLastNameFirst;
    public bool ShowLastNameFirst {
        get { return _showLastNameFirst; }
        set { SetPropertyValue(ref _showLastNameFirst, value); }
    }
    public string Initials {
        get { return (String.IsNullOrEmpty(FirstName) ? "" : FirstName.Substring(0,1)) + (String.IsNullOrEmpty(LastName) ? "" : LastName.Substring(0,1)); }
    }
    public DelegateCommand SaveCommand { get; private set; }
    public MyViewModel() {
        SaveCommand = new DelegateCommand(() => {
                // Save Data
            },
                () => !(String.IsNullOrEmpty (FirstName) || String.IsNullOrEmpty (LastName)));
        // ... existing constructor code
    }

And of course we need to modify the FullName property to apply the correct formatting:

    public string FullName {
        get { return ShowLastNameFirst ? String.Format ("{0}, {1}", _lastName, _firstName) : String.Format ("{0} {1}", _firstName, _lastName); }
    }

Finally, we add the new requirements to our property dependency declarations in the constructor. The complete finalized version of our example’s code is thus:

public class MyViewModel : ObservableObject {
    string _firstName;
    string _lastName;
    bool _showLastNameFirst;</pre>
<pre><code>public string FirstName {
    get { return _firstName; }
    set { SetPropertyValue(ref _firstName, value); }
}

public string LastName {
    get { return _lastName; }
    set { SetPropertyValue(ref _lastName, value); }
}

public string FullName {
    get { return ShowLastNameFirst ? String.Format (&quot;{0}, {1}&quot;, _lastName, _firstName) : String.Format (&quot;{0} {1}&quot;, _firstName, _lastName); }
}

public bool ShowLastNameFirst {
    get { return _showLastNameFirst; }
    set { SetPropertyValue(ref _showLastNameFirst, value); }
}

public string Initials {
    get { return (String.IsNullOrEmpty(FirstName) ? &quot;&quot; : FirstName.Substring(0,1)) + (String.IsNullOrEmpty(LastName) ? &quot;&quot; : LastName.Substring(0,1)); }
}

public DelegateCommand SaveCommand { get; private set; }

public MyViewModel() {
    SaveCommand = new DelegateCommand(() =&gt; {
            // Save Data
        },
            () =&gt; !(String.IsNullOrEmpty (FirstName) || String.IsNullOrEmpty (LastName)));


   WhenPropertyChanges(() =&gt; FirstName)
        .AlsoRaisePropertyChangedFor(() =&gt; FullName)
        .AlsoRaisePropertyChangedFor(() =&gt; Initials)
        .AlsoInvokeAction(SaveCommand.ChangeCanExecute);
    WhenPropertyChanges(() =&gt; LastName)
        .AlsoRaisePropertyChangedFor(() =&gt; FullName)
        .AlsoRaisePropertyChangedFor(() =&gt; Initials)
        .AlsoInvokeAction(SaveCommand.ChangeCanExecute);
    WhenPropertyChanges(() =&gt; ShowLastNameFirst )
        .AlsoRaisePropertyChangedFor(() =&gt; FullName);
}
</code></pre>
<pre>} 

As you can see – very compact and easy to understand exactly how all of the components interact with each other. To demonstrate how this hypothetical ViewModel would work when combined with a simple XAML page, we could bind each of the properties to visual controls like so:

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns_x="http://schemas.microsoft.com/winfx/2009/xaml" x_Class="PropertyDependencyDemo.MyPage">
    <ContentPage.ToolbarItems>
        <ToolbarItem Text="Save" Command="{Binding SaveCommand}" Order="Primary"/>
    </ContentPage.ToolbarItems>
    <TableView Intent="Data">
        <TableSection Title="Inputs">
            <EntryCell Label="First Name" Text="{Binding FirstName}"/>
            <EntryCell Label="Last Name" Text="{Binding LastName}"/>
            <SwitchCell Text="Last Name First" On="{Binding ShowLastNameFirst}"/>
        </TableSection>
        <TableSection Title="Outputs">
            <EntryCell Label="Full Name" Text="{Binding FullName}"/>
            <EntryCell Label="Initials" Text="{Binding Initials}"/>
        </TableSection>
    </TableView>
</ContentPage>

Simulator Screen Shot Oct 18, 2015, 12.13.27 AM_iphone6_silver_portrait

And lastly, you might recall from above that I felt it was an important feature to also be able to establish dependencies on properties of other objects (not just the ViewModel you are working in). Suppose for instance that we want to add a Children property to our ViewModel, and display the total number of Sons or Daughters? It turns out that the API for doing this is nearly the same – there is an extension method provided for any object that implements INotifyPropertyChanged. The only limitation is that the extension method can only invoke Actions and Tasks – it cannot directly raise other notification events (although you could do so from with an Action or Task).

Conclusion

In this post, I introduced the concept of centralized property dependency management, and offered code examples to illustrate the idea. As ViewModel complexity increases, this technique can really help keep your code manageable. Hopefully the benefits of using this in your own Xamarin Forms, WPF or Silverlight code are clear and you will be able to make use of it. I’ve been using this design for many years now, and it has never let me down – not even with the most complicated of business requirements.

Source code: https://github.com/Wintellect/XamarinSamples/tree/master/PropertyDependencyDemo

Need Xamarin Help?

Xamarin Consulting  Xamarin Training

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