Through talking to people and monitoring both internal and external forums, I have compiled a list of questions people often have when first learning about WPF data binding. If you have any questions, please leave a comment and let me know!

 

What is target and what is source?

In WPF, you typically use data binding to establish a connection between the properties of two objects. In this relationship, one object is referred to as the source and one object is referred to as the target. In the most typical scenario, your source object is the object that contains your data and your target object is a control that displays that data.

 

For instance, consider a Person class with a Name property. If you want to show the Name property value in the UI and have the UI automatically change when the Name property value changes at run-time, you can bind the TextBlock.Text property to the Name property of the Person object. In the following example, the Person class is declared in the BindingSample namespace. When you run this, your window shows “Joe”.

 

<Window

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

  xmlns:local="clr-namespace:BindingSample">

 

  <Window.Resources>

    <!-- Instantiates the Person class with the Name value "Joe"-->

    <!-- Giving it an x:Key so it's available as a resource -->

    <local:Person x:Key="myDataSource" Name="Joe"/>

  </Window.Resources>

 

  <!-- Binding the Text property to the Name property -->

  <TextBlock Text="{Binding Source={StaticResource myDataSource}, Path=Name}"/>

 

</Window>

 

So, in this example:

  • The TextBlock is the target object.
  • The Text property is the target property.
  • The Person object is the source object.
  • The Name property is the source property.

You bind a target to a source.

 

 

What’s bindable?

A target property must be a dependency property. This means that your target object must be a DependencyObject. Fortunately, most UIElement properties are dependency properties and most dependency properties, except read-only ones, support data binding by default. To find out if a property is a dependency property, check to see if it has a corresponding field that ends with “Property”. For example, the Text property is a dependency property and has a corresponding field named “TextProperty”. Alternatively, if you are using the SDK documentation, see if the property page has a “Dependency Property Information” section. If it does, then it is a dependency property. For an example, check out the Background property page.

 

Your source can be any CLR object or XML data:

  • You can bind to any CLR objects, including list objects. You can bind to the entire object or public properties, sub-properties, and indexers of the object. Fields are not supported. The binding engine uses CLR reflection to get the values of the properties. Alternatively, objects that implement ICustomTypeDescriptor or have a registered TypeDescriptionProvider also work with the binding engine.
  • You can bind to ADO.NET objects such as DataTable.
  • You can bind to an XmlNode, XmlDocument, or XmlElement, and run XPath queries on them.

 

When do I use Source and when do I use DataContext?

There are many ways to specify your binding source, that is, to specify where your data is coming from. The simplest way is to instantiate the source object as a resource in XAML and then the Source property of the Binding to that resource (as in the last example).

 

Using the Source property is simpler and more readable. However, if multiple properties bind to the same source, consider using the DataContext property. The DataContext property provides a convenient way to establish a data scope. Say you have many controls and you want all of them to bind to the same source.

 

<Window . . .>

  <Window.Resources>

    <local:Person x:Key="myDataSource" Name="Joe"/>

  </Window.Resources>

 

  <StackPanel>

    <StackPanel.DataContext>

      <Binding Source="{StaticResource myDataSource}"/>

    </StackPanel.DataContext>

 

    <TextBox Text="{Binding Path=Name}"/>

    <TextBlock Text="{Binding Path=Name}"/>

    <!-- ...

         Other controls that are also

         interested in myDataSource.

         ...

    -->

  </StackPanel>

</Window>

 

In this case, you set the DataContext property of your StackPanel to that source so that all elements in that StackPanel inherit that common source. The TextBox and TextBlock in this example both inherit the binding source from the StackPanel. When you run this, you see a TextBox with “Joe” and a TextBlock with “Joe”.

 

 

How do I make my data-bound TextBox update the source value as I type?

By default, TextBox.Text has an UpdateSourceTrigger value of LostFocus. This means if you have a data-bound TextBox, the default behavior is that the source does not get updated until the TextBox loses focus. If you want the source to update as you type into the TextBox, set the UpdateSourceTrigger property to PropertyChanged:

 

    <TextBox Text="{Binding Path=Name, UpdateSourceTrigger=PropertyChanged}"/>

 

One thing that’s really easy to miss is that the UpdateSourceTrigger default value varies for different properties. For most properties, the UpdateSourceTrigger property defaults to PropertyChanged. However, for TextBox.Text, it is LostFocus.

 

This table provides a summary of the UpdateSourceTrigger value for TextBox.Text. Again, remember that this is only true for the TextBox.Text property. 

 

UpdateSourceTrigger value

When the Source Value Gets Updated

Example Scenario for TextBox

LostFocus (default for TextBox.Text)

When the TextBox control loses focus

A TextBox that is associated with validation logic

PropertyChanged

As you type into the TextBox

TextBox controls in a chat room window

Explicit

When the application calls UpdateSource

TextBox controls in an editable form (updates the source values only when the user clicks the submit button)

 

 

What does OneWay or TwoWay binding mean?

These are binding Mode values. In the simplest terms, the OneWay mode is read-only (with respect to the source) and the TwoWay mode is read-write. For instance, in a stock ticker application, your controls are only “reading” and displaying the source values, so the controls only need to have OneWay bindings. The read-write scenario with TwoWay bindings is more applicable to a business application that allows users to both view and edit data.

 

Similar to UpdateSourceTrigger, the default value for the Mode property varies for each property. User-editable properties such as TextBox.Text, ComboBox.Text, MenuItem.IsChecked, etc, have TwoWay as their default Mode value. To figure out if the default is TwoWay, look at the Dependency Property Information section of the property. If it says BindsTwoWayByDefault is set to true, then the default Mode value of the property is TwoWay. To do it programmatically, get the property metadata of the property by calling GetMetadata and then check the boolean value of the BindsTwoWayByDefault property.

 

There’s also OneWayToSource and OneTime. If you’re interested, see the Mode page in the SDK.

 

 

My target binds to a property on my custom object but the binding does not refresh when the source value changes.

Your custom object needs to implement a mechanism to provide notifications when a property changes. The recommended way to do that is to implement INotifyPropertyChanged. Here’s an example:

 

using System.ComponentModel;

 

namespace BindingSample

{

  public class Person : INotifyPropertyChanged

  {

    private string name;

    // Declare the event

    public event PropertyChangedEventHandler PropertyChanged;

 

    public Person()

    {

    }

 

    public Person(string value)

    {

        this.name = value;

    }

     

    public string Name

    {

      get { return name; }

      set

      {

        name = value;

        // Call OnPropertyChanged whenever the property is updated

        OnPropertyChanged("Name");

      }

    }

 

    // Create the OnPropertyChanged method to raise the event

    protected void OnPropertyChanged(string name)

    {

      PropertyChangedEventHandler handler = PropertyChanged;

      if (handler != null)

      {

        handler(this, new PropertyChangedEventArgs(name));

      }

    }

  }

}

Also, remember that the properties you are binding to need to be public and you cannot bind to fields.

 

 

How do I create a binding in code?

One way is to call the SetBinding method on the target object:

Person myDataSource = new Person("Joe");     

Binding myBinding = new Binding("Name");

myBinding.Source = myDataSource;

// myText is an instance of TextBlock

myText.SetBinding(TextBlock.TextProperty, myBinding);

 

Only FrameworkElements and FrameworkContentElements have a SetBinding method. Their SetBinding method is actually calling the BindingOperations.SetBinding method. Therefore, you can always use the BindingOperations.SetBinding method, especially when your target object is not a FrameworkElement or a FrameworkContentElement.

 

 

How do I bind to an existing object instance?

In some cases the source object that you bind to can only be created at run-time, such as a DataSet object that’s created in response to a database query. In those cases, you need to set the DataContext property of your target object to the instantiated object programmatically. Example:

 

      // myListBox is a ListBox control

      // myCustomBizObject is your custom business object

      myListBox.DataContext = myCustomBizObject;

 

There are two special cases. First, if you are binding to a property of another element in the same scope, then you use the ElementName property to specify the source. For example, you can bind the TextBlock.Text property to the content of the SelectedItem of a ComboBox:

 

      <ComboBox Name="myComboBox" SelectedIndex="0">

        <ComboBoxItem>1</ComboBoxItem>

        <ComboBoxItem>2</ComboBoxItem>

        <ComboBoxItem>3</ComboBoxItem>

      </ComboBox>

      <TextBlock Text="{Binding ElementName=myComboBox, Path=SelectedItem.Content}"/>

 

Second, if you are binding between properties of the same control, then you use the RelativeSource property. Specially, you set RelativeSource to Self: RelativeSource={x:Static RelativeSource.Self}.

 

In the next data-binding post we’ll get into common questions that deal with binding to collections and other more advanced scenarios. In the meantime, there’s always the Data Binding Overview in the SDK docs and Beatriz’s excellent blog.

 

Happy binding,

Tina

 


About Us

We are the Windows Presentation Foundation SDK writers and editors.