Hands-on MVVM 2: Dependent properties

I will be presenting this material at Dallas XAML tonight (May 4, 2010). If you are in the area, please come by. If not, just download the demo code and follow along.

In part 1 we created a model and a view. Now we start adding features and seeing how our code changes.

Window title
The first feature to add is to display the name of the person in the title bar of the window. The view is a user control, but it’s hosted inside of a window. We already set the DataContext of the window so that it would be inherited by the user control. So we can just data bind the title.

<Window x:Class="Step2.PersonWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:view="clr-namespace:Step2.View"
    Title="{Binding Title}" Height="300" Width="468">
    <view:PersonUserControl/>
</Window>

Bound property

The data context that we set was the Person model object. So we have to add this Title property to the Person.

public class Person
{
    private string _firstName;
    private string _lastName;
    private string _email;
    private string _phone;

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

    public string LastName
    {
        get { return _lastName; }
        set { _lastName = value; }
    }

    public string Email
    {
        get { return _email; }
        set { _email = value; }
    }

    public string Phone
    {
        get { return _phone; }
        set { _phone = value; }
    }

    public string Title
    {
        get
        {
            return string.Format("Person - {0}, {1}", _lastName, _firstName);
        }
    }
}

Run the program and you’ll see that the title properly displays the person’s name. It looks like everything is working. But change the name and see what happens.

change_name

The title doesn’t update when the name changes. That’s because the view doesn’t know that the title depends upon the name. Unless you have a system that automatically discovers dependencies (not discussed in this series), you have to notify the view.

As you can see, INotifyPropertyChanged is not strictly necessary for data binding to work. The view worked just fine up until now. The properties were not notifying the view when they themselves were changing. That’s because it was the view that was changing them. The view already knows. You only really need INotifyPropertyChanged to notify the view when:

  1. Something other than the view changes the property, or
  2. The property depends upon another property.

Dependent property

In this case, the Title property depends upon the FirstName and LastName properties. So we notify the view that Title has changed when one of those properties change.

public class Person : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private string _firstName;
    private string _lastName;
    private string _email;
    private string _phone;

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

    public string LastName
    {
        get { return _lastName; }
        set { _lastName = value; FirePropertyChanged("Title"); }
    }

    public string Email
    {
        get { return _email; }
        set { _email = value; }
    }

    public string Phone
    {
        get { return _phone; }
        set { _phone = value; }
    }

    public string Title
    {
        get
        {
            return string.Format("Person - {0}, {1}", _lastName, _firstName);
        }
    }

    private void FirePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

And now the title updates when you change the name.

We are starting to see the need for a view model. The Title property has nothing to do with our data model. But we’ll let that slide for now.

Today we saw what problem INotifyPropertyChanged solves, and we wrote the simplest thing that works. This is not the best thing, nor is it the right thing. We are watching the code evolve to see why we need MVVM.

Next time we will add another feature to the system and see how the code responds to another change. Stay tuned.

Leave a Reply

You must be logged in to post a comment.