Click here to Skip to main content
Click here to Skip to main content
Go to top

Everything you wanted to know about databinding in WPF, Silverlight, and WP7 (Part One)

, 26 Apr 2012
Rate this:
Please Sign up or sign in to vote.
Databinding is a fundamental part of the WPF, Silverlight, and the Silverlight for Windows Phone 7 frameworks. It is a powerful concept that once mastered allows you to write concise and elegant code.

OK, so the title is a little ambitious, but there is nothing wrong with setting yourself lofty aims! Because of the depth of this topic I have decided to split this tutorial up into a series of blog posts, each of which explore a different aspect of the binding framework.

I don’t usually write tutorial blog posts and series, preferring instead to develop new controls or novel techniques. However, I really felt this subject needed an in-depth tutorial. Databinding is a fundamental part of the WPF, Silverlight, and the Silverlight for Windows Phone 7 frameworks. It is a powerful concept that once mastered allows you to write concise and elegant code. Yet for all its power, it is a little complex and that is my reason for launching into this blog series.

The rough outline for this series is as follows:

  • Part One – Life before binding, INotifyPropertyChanged and creating bindings in code-behind
  • Part Two – The binding markup extensions, the DataContext and path syntax
  • Part Three – Other binding sources, ElementName, TemplatedParent, TemplateBinding
  • Part Four – Value converters
  • Part Five – List binding

Life before binding

To understand what databinding is and the service it provides us with, it is worth looking at how you wire-up a user-interface without using databinding. We’ll start with a simple model object, or business object, and see how we can take the properties that this object exposes and display them in the UI using standard controls. We will also see how we can respond to event raised by these controls in order to update our model.

Note, that I am making the assumption that your code will contain some sort of model object. This doesn’t have to be the case! You could store your data within the UI controls directly, however this rapidly becomes un-maintainable. There are a whole host of UI patterns that have been developed in order to keep the model and the view separate (MVP, MVC, MVVM etc…)

We’ll look at how to manage the interactions between the model and the view without the help of a binding framework. For our example we’ll look at a very simple UI which displays the details of an event, its name and the date of the event:

The model that supports this view is shown below:

/// <summary>
/// A simple model object that represents an event
/// </summary>
public class EventModel : INotifyPropertyChanged
{
  private string _title;
 
  /// <summary>
  /// Gets / sets the event title
  /// </summary>
  public string Title
  {
    get { return _title; }
    set
    {
      if (value == _title)
        return;
 
      _title = value;
      OnPropertyChanged("Title");
    }
  }
 
  private DateTime _date;
 
  /// <summary>
  /// Gets / sets the date of this event
  /// </summary>
  public DateTime Date
  {
    get { return _date; }
    set
    {
      if (value == _date)
        return;
 
      _date = value;
      OnPropertyChanged("Date");
    }
  }
 
  public event PropertyChangedEventHandler  PropertyChanged;
 
  protected void OnPropertyChanged(string propertyName)
  {
    if (PropertyChanged != null)
    {
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
  }
}

In our case the model implements INotifyPropertyChanged, allowing us to detect changes in its properties. We will use this to update the view when the model changes.

The view has the following XAML (with the various layout properties omitted for clarity):

<TextBlock Text="Name:"/>
<TextBox x:Name="EventTitle"
          TextChanged="EventTitle_TextChanged"
 
<TextBlock Text="Date:"/>
<sdk:DatePicker x:Name="EventDate"
                SelectedDateChanged="EventDate_SelectedDateChanged"/>
 
<Button Content="Modify Event"
        Click="Button_Click"/>

The code-behind that supports this view is given below:

public partial class MainPage : UserControl
{
  private EventModel _event;
 
  public MainPage()
  {
    InitializeComponent();
 
    // create a model object
    _event = new EventModel()
    {
      Date = new DateTime(2011, 7, 1),
      Title = "Silverlight User Group"
    };
 
    // copy our model object state to the UI
    EventDate.SelectedDate = _event.Date;
    EventTitle.Text = _event.Title;
 
    // 'listen' to changes in the model
    _event.PropertyChanged += Event_PropertyChanged;
  }
 
  /// <summary>
  /// Handles changes in the model, reflecting this change in the UI (view)
  /// </summary>
  private void Event_PropertyChanged(object sender, PropertyChangedEventArgs e)
  {
    if (e.PropertyName == "Title")
    {
      EventTitle.Text = _event.Title;
    }
    if (e.PropertyName == "Date")
    {
      EventDate.SelectedDate = _event.Date;
    }
  }
 
  /// <summary>
  /// Handles the TextChanged event updating the model accordingly
  /// </summary>
  private void EventTitle_TextChanged(object sender, TextChangedEventArgs e)
  {
    _event.Title = EventTitle.Text;
  }
 
  /// <summary>
  /// Handles the SelectedDateChanged event updating the model accordingly
  /// </summary>
  private void EventDate_SelectedDateChanged(object sender, SelectionChangedEventArgs e)
  {
    _event.Date = EventDate.SelectedDate.Value;
  }
 
  private void Button_Click(object sender, RoutedEventArgs e)
  {
    // make some change to our event
    _event.Title = _event.Title.ToLower();
    _event.Date = _event.Date.AddDays(1);
  }
}

In order to wire-up the model with our view, the above code performs the following distinct tasks for each of the model’s properties:

  1. Sets the state of the UI controls to the initial state of the model. In the above example this is done in the constructor.
  2. Subscribes to the event that the UI control exposes to indicate a change in state. For the TextBox this is the TextChanged event, for the DatePicker this is the SelectedDateChanged event. When a change occurs, the UI state used to update the mode.
  3. Subscribes to PropertyChanged events from the model object. The handler for this event detects the property that has changed and updates the state of the corresponding UI control.

If we consider the model object to be the source of the data and the UI control to be the target. We can see that we have three separate flows of data:

The code for each of these three steps is distributed throughout our code, in the constructor and a variety of event handler. For each model property that we wish to expose to our user via the view, we have to add code to perform each of these three tasks. This leads to code that is hard to maintain and dataflow that are hard to trace.

Databinding – less code, greater clarity

Databinding provides an alternative to the manual coupling of the model to the UI controls in our view. The idea being that the binding framework takes care of all three of the tasks above. We simply state that we wish to synchronise a model property with a property of a UI control, and it does the rest. Our complex diagram above simply becomes the following:

Changes in the source property values are pushed to the target property by the binding framework, and (optionally) changes in the target are pushed to the source.

Modifying the code for our example to use the WPF / Silverlight framework results in the following code:

public MainPage()
{
  InitializeComponent();
 
  // create a model object
  _event = new EventModel()
  {
    Date = new DateTime(2011, 7, 1),
    Title = "Silverlight User Group"
  };
 
  // bind the Date to the UI
  EventDate.SetBinding(DatePicker.SelectedDateProperty, new Binding("Date")
  {
    Source = _event,
    Mode = BindingMode.TwoWay
  });
 
  // bind the Title to the UI
  EventTitle.SetBinding(TextBox.TextProperty, new Binding("Title")
  {
    Source = _event,
    Mode = BindingMode.TwoWay
  });
}

This is a big improvement on the previous ‘manual’ example where three separate event handlers were required to maintain synchronization between the model and the view. Databinding allows us to declare how the model is connected to the view, with the databinding framework taking care of the mechanics.

We’ll take a closer look at the databinding syntax in order to understand its various component parts. We can highlight these components by re-writing one of the bindings as follows:

FrameworkElement targetObject = EventTitle;
DependencyProperty targetProperty = TextBox.TextProperty;
object sourceObject = _event;
string sourceProperty = "Title";
 
var binding = new Binding(sourceProperty)
{
  Source = sourceObject,
  Mode = BindingMode.TwoWay
};
targetObject.SetBinding(targetProperty, binding);

From the above we can clearly see the following components:

  • The source object – this is the object which contains the data which we want to render within the UI
  • The source property – the property of the above object which we wish to render
  • The target object – this is a UI control which has a property which we are going to use to display our model property
  • The target property – the property of the UI control which visualises our data
  • The binding - this is used to indicate the source and source property, together with other information relating to the binding like the direction of data flow, value converters etc… (more on these later).
  • SetBinding – this is the method used to associate a databinding with a specific property on the target. Note that the first argument is the dependency property that is defined on TextBox and is public static.

Once a binding has been created and associated with a dependency property, the initial value is propagated from the source to the target. Following this, if the source object implements INotifyPropertyChanged, subsequent changes in the source property value are automatically propagated. If a BindingMode.TwoWay binding is used, changes to the target property, which typically occur due to user interactions, are propagated from the target to the source.

A brief digression into dependency properties

As you can see from the above, databinding is a feature of WPF and Silverlght dependency property mechanism. The type of properties that developers are used to from other .NET languages are typically termed ‘CLR properties’ (Where CLR refers to the Common Language Runtime) so that we know which type of property we are talking about!

CLR properties are simply shorthand for methods used to access a backing field. You cannot use the databinding framework to bind together two CLR properties. Dependency properties are something much more powerful, they provide property inheritance within the visual tree, animation support, precedence rules, coercion and, most importantly for the purposes of this article, databinding.

In the example below, a dependency property ‘TotalGoals’ is defined on a dependency object. By convention, this dependency property is exposed as a public static field on the dependency object. It is this static field that we use to identify the dependency property when binding to it:

public class MatchResult : DependencyObject
{
  /// <summary>
  /// Identifies the TotalGoals Dependency Property.
  /// <summary>
  public static readonly DependencyProperty TotalGoalsProperty =
      DependencyProperty.Register("TotalGoals", typeof(int),
      typeof(MatchResult), new PropertyMetadata(0));
 
}

Once a dependency property has been defined, its value can be get / set via the GetValue / SetValue methods:

var result = new MatchResult();
// set the property
result.SetValue(MatchResult.TotalGoalsProperty, 10);
 
// get the property
Debug.WriteLine(result.GetValue(MatchResult.TotalGoalsProperty))

Because the syntax to get or set a dependency property is not terribly friendly, using the GetValue / SetValue methods, dependency objects typically provide CLR properties that wrap the dependency property access, providing a better API for manipulating the state form code-behind.

/// <summary>
/// Gets or sets the total score. This is a dependency property.
/// </summary>
public int TotalScore
{
  set
  {
    SetValue(MatchResult.TotalGoalsProperty, value);
  }
  get
  {
    return (int)GetValue(MatchResult.TotalGoalsProperty);
  }
}

However, this is purely convention.

Whilst the target for a binding must be a dependency property (which must be defined on a dependency object), the source can be either a dependency property or a CLR property. In practice, unless you are creating your own controls, you will not need to create your own dependency properties. Instead, you will be binding your model to the properties of the various UI elements that are supplied with the WPF / Silverlight frameworks, for example TextBlock.Text. These are all dependency properties.

A quick note about INotifyPropertyChanged

Whilst dependency properties always notify the binding framework of any changes in value, CLR properties only notify of changes if the class which the belong to implements the INotifyPropertyChanged interface (as the class used in the example above does). It is not mandatory that you implement this interface, or raise the PropertyChanged event, for properties that your bind to your UI. However, if you do not, the binding framework will only perform a one-time update, pushing the property value from source to target at the point when the binding is created.

BindingModes

You can specify which direction you want property changes to propagate by setting the BindingMode on a binding. This is probably easiest to illustrate with a simple diagram:

OneWay bindings only propagate changes in the source value to the target (assuming the source implements INotifyPropertyChanged), whereas a TwoWay binding propagates changes in both directions, ensuring that the two values are always synchronized. There are a few other binding modes (OneWayToSource, OneTime…) but one / two way are by far the most commonly used.

WARNING: The default BindingMode for Silverlight is OneWay, whereas in WPF it is BindingMode.Default which means … it depends! From MSDN:

“The default value varies for each dependency property. In general, user-editable control properties, such as those of text boxes and check boxes, default to two-way bindings, whereas most other properties default to one-way bindings.”

This is very confusing if you are writing cross-platform WPF / Silverlight code! In this case I would always recommend specifying the BindingMode explicity.

Summary

So far we have seen what life was like before databinding, where we had to write code to handle changes from both the source and target properties, manually synchronizing the two. With binding, the framework handles this for us, allowing for a more declarative approach to wiring-up our UI to the model that backs it (you do have a model behind your view don’t you?!).

However, you might be wondering why there has been no mention of binding in XAML yet? This was intentional, I wanted to first show how bindings work under-the-hood, introducing the concept of source and target, before leaping into creating them in XAML … which is the subject of the next blog post …

You can download the example code here: BindingExamples.zip

Regards, Colin E.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Colin Eberhardt
Architect Scott Logic
United Kingdom United Kingdom
I am CTO at ShinobiControls, a team of iOS developers who are carefully crafting iOS charts, grids and controls for making your applications awesome.
 
I am a Technical Architect for Visiblox which have developed the world's fastest WPF / Silverlight and WP7 charts.
 
I am also a Technical Evangelist at Scott Logic, a provider of bespoke financial software and consultancy for the retail and investment banking, stockbroking, asset management and hedge fund communities.
 
Visit my blog - Colin Eberhardt's Adventures in .NET.
 
Follow me on Twitter - @ColinEberhardt
 
-
Follow on   Twitter   Google+

Comments and Discussions

 
QuestionCan't help but think.... [modified] PinmemberMember 456543328-Apr-12 0:05 
QuestionSomething messed up PinmvpRichard MacCutchan25-Apr-12 22:33 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140916.1 | Last Updated 26 Apr 2012
Article Copyright 2012 by Colin Eberhardt
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid