BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Windows Presentation Foundation
.NET 4.0+

WPF Data Binding - INotifyPropertyChanged

The ninety-third part of the Windows Presentation Foundation Fundamentals tutorial continues to look at data binding using the DataContext property. This article considers the INotifyPropertyChanged interface, which lets classes send notifications when property values are modified.

Data Binding

In the previous instalment in this tutorial we looked at the DataContext property of WPF controls. This property can is set to an object to use as the source for its data bindings and those of its children. In the earlier article we used simple bindings to display string and integer values that were controlled directly by the controls in a window.

When controls update a property that is also the direct source of other bindings, the user interface can update automatically. We saw this with a Slider and a TextBlock that were bound to the same value. As the Slider was manipulated, the TextBlock showed the changing value.

In some situations, it is not possible for a control to realise that the value to which it is bound has been changed. For example, if a read-only property is calculated according to other, data-bound properties, controls that are linked to the calculated value will not normally update. If the source object is updated programmatically, these changes will not normally be reported to the user interface, which will continue to show old values.

To remove this problem, WPF makes use of the INotifyPropertyChanged interface. If the object held in the DataContext property of a control implements this interface, the control will listen for its PropertyChanged event. This event signals changes to property values. When the event is raised and indicates a change to a control binding, the on-screen value changes accordingly.

You can use this automatic behaviour to tell the user interface to update. When an action happens that causes a property to change that would not normally cause an update in the WPF controls bound to it, you raise the event and name the modified property. WPF handles the rest for you.

To demonstrate, we need a sample project. Create a new WPF application project in Visual Studio named, "INotifyPropertyChangedDemo". Once ready replace the XAML of the main window with the code below:

<Window x:Class="INotifyPropertyChangedDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Personal Details"
        Height="180"
        Width="250"
        ResizeMode="NoResize">
    <Grid Margin="5">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <TextBlock>First Name</TextBlock>
        <TextBox Grid.Column="1" Margin="5 0 0 5" Text="{Binding FirstName}"/>

        <TextBlock Grid.Row="1">Last Name</TextBlock>
        <TextBox Grid.Column="1" Grid.Row="1" Margin="5 0 0 5" Text="{Binding LastName}"/>

        <TextBlock Grid.Row="2">Full Name</TextBlock>
        <TextBlock Grid.Column="1" Grid.Row="2" Margin="5 0 0 5" Text="{Binding FullName}"/>
    </Grid>
</Window>

The XAML defines a window with two TextBox controls that allow the user to specify a first and last name. In the third row of the Grid is a TextBlock bound to the property FullName. This property will be a read-only string, based upon the FirstName and LastName properties of the data class.

We need a class containing the properties to which the window's controls will be bound. Add a new class named, "PersonalDetails". Use the following code for the class:

public class PersonalDetails
{
    string _firstName = "Bob";
    string _lastName = "Smith";

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

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

    public string FullName
    {
        get { return string.Format("{0} {1}", FirstName, LastName); }
    }
}

You can see that this is a simple data class. It contains the two writeable properties for the first and last names, and a read-only FullName property that combines the first and last names into a single string.

The final task for the first example is to set up the DataContext for the controls. As in the last article, we'll set the DataContext for the Window. The value will be inherited by the key TextBoxes and TextBlock. Modify the constructor for the window, as follows:

public MainWindow()
{
    InitializeComponent();
    DataContext = new PersonalDetails();
}

You can now run the program to see the results. You can see that the bindings are connecting correctly because all three key controls contain names on loading. However, if you modify the first or last names, the full name text block does not change.

The problem here does not lie with the FullName property. If you were to call it you would see the correct, updated full name. However, although the controls are aware that you have changed the FirstName and LastName properties, they do not know that the logic of FullName is based upon their values. As such, the controls do not know that FullName may have changed and do not re-read the property and refresh.

WPF calculated data binding not updated in user interface

3 September 2014