All applications are dependent on data in some form and most developers find themselves writing reams of data access code.

Microsoft has been building data binding frameworks for years. Each one promises to solve our data binding woes forever. We're still waiting for the perfect one. Is WPF data binding the one we've been waiting for?

Windows Presentation Foundation (WPF) is full of surprises for seasoned .NET developers. There is a new UI composition model, a brand new XAML markup language, and the perplexing dependency property system to learn. There is so much to learn, where do you start? For starters, check out Wei-Meng Lee's “An Overview of Windows Presentation Foundation” article (CoDe Magazine, Mar/Apr 2006). I have my own short list of favorite concepts to learn in WPF. Here are two. First, learn about Templates and their close cousin Styles. They are an astoundingly good way to design and render a user interface. Second, invest some time in understanding the new data binding model. It's time well spent

Binding Frameworks

Data binding has been around in some form for years. Both Windows Forms and ASP.NET have binding implementations available. The motivation behind creating a binding framework is that it reduces the amount of code that the application developer must write. You rely on the teams at Microsoft to produce the mountains of code necessary to simplify your daily coding tasks.

WPF is a complete rethinking of how to construct a UI development platform. Since Microsoft started with a blank slate, it provided the WPF architects with the opportunity to engineer interesting ideas into their binding engine.

The central idea behind binding is simple. You “bind” some UI controls to a data object and rely on the binding framework to push the data to the controls and ensure that changed data is saved back to the business object properties.

So what is WPF data binding anyway? I'd define it as follows: the ability to register two items, a data source and a data target, with the binding framework. The binding framework is responsible for synchronizing the data between the two items and providing us with indispensable services like validation and data conversion.

That simple explanation hardly reveals the power of WPF binding. WPF is a complete rethinking of how to construct a UI development platform. Since Microsoft started with a blank slate, it provided the WPF architects with the opportunity to engineer interesting ideas into their binding engine. Binding in WPF is pervasive and built-in to every corner of the system. It permits better abstraction of code and UI by allowing complete separation of UI design from business object code. Data templates are another unique idea within WPF. If you are coming from a Windows Forms or ASP.NET background, templates will force you to change the way you think about developing and designing user interfaces.

Data Binding Collaborators

There are three main participants in the WPF data binding model; the framework, the data target, and the data source. Configuring a binding with the framework is simply a matter of telling the WPF dependency property system the details about the desired binding. You do this via the Binding markup extension class:

<TextBlock Text='{Binding Path=StreetAddress}' />

This short XAML (pronounced "zammel") snippet is all you need to bind the Text property to the StreetAddress property.

Data Targets

Bindings are always set on the “binding target”. The target is usually a WPF UI element, though there is no requirement for it to be a visual element.

The data target is the destination for the bound data. You have to specify both the target object and target property. The target property must be a dependency property. Dependency properties are a core part of the WPF dependency property system. They are the enablers for many of the exciting WPF features like animation, styles, templates, and property inheritance. They also provide the glue for data binding.

Any type can serve as a data target as long as it provides one or more “dependency properties”. To find out which properties are eligible, here's a simple LINQ query that returns all the dependency properties in the TextBlock class.

In C#:

// using System.Windows.Controls
var q = from member
  in typeof(TextBlock).GetFields
   (BindingFlags.Public | BindingFlags.Static |
    BindingFlags.FlattenHierarchy)
  where member.FieldType ==
    typeof(System.Windows.DependencyProperty)
  orderby member.Name
  select member.Name;
    
  // Examples
  // BackgroundProperty
  // CursorProperty

In Visual Basic:

  ' using System.Windows.Controls
  Dim q = From member In
GetType(TextBlock).GetFields(BindingFlags.Public _
   Or BindingFlags.Static _
   Or BindingFlags.FlattenHierarchy) _
   Where member.FieldType Is _ GetType(System.Windows.DependencyProperty) _
   Order By member.Name _
   Select member.Name
    
  ' Examples
  ' BackgroundProperty
  ' CursorProperty

If you run the “List of Dependency Properties” item in the included sample project you can see a detailed list of available dependency properties for each Framework element.

There are a variety of WPF elements that can serve as data targets. Some of these elements are designed for showing single values. The TextBlock and Slider elements are prime examples of this type of element. ItemsControls are elements that show lists of data. WPF includes a number of these list-friendly controls including ComboBox, ListBox, and TreeView.

Data Sources

One of the splendid aspects of the WPF data binding engine is that it can bind to nearly any data source including XML data, ADO.NET classes, LINQ queries, WPF elements, and types that implement IEnumerable or IList.

As has been discussed earlier, every binding must have a binding target and target property. The binding isn't complete unless you also specify the data source and source property.

Sometimes you want to show a single value from a data source. It might be showing a font name in a label or an invoice date in a calendar control. Perhaps you'd like to bind the value of one control to the input of another. I'll call this “single property” binding though there is no such official name in WPF. Single property binding is easy to do in WPF. Here is an example showing how to bind the Value property of a Slider control to the FontSize property of a TextBlock:

<Slider x:Name='sizeSlider'
        Orientation='Vertical'
        Minimum='10'
        Maximum='80'
        Value='25' />
<TextBlock Text='Sample Text - abcde'
           Margin='5,0'
           FontSize=
'{Binding ElementName=sizeSlider, Path= Value}'/>

A binding source is usually a property on an object so you need to provide both the data source object and the data source property in your binding XAML. In the above example the ElementName attribute signifies that you want data from another element on the page and the Path signifies the appropriate property. A binding path can be a complex value, drilling into the member hierarchy, but in this case it's just the name of the property.

Change Notification

Nearly any .NET property can serve as a data source. In the previous example the data source is the Value property on the Slider element which returns a Double value. The data is loaded into the data target on initialization. If you establish a two-way binding (details later in this article) the data will flow back to the data source. The WPF dependency system can also keep the data synchronized back to the data target in the event that the source property changes. This is not automatic however. To accomplish this, the source property must implement some form of change notification. Your type must tell the framework that the underlying data has changed. There are a several ways to accomplish this in your data source:

  • INotifyPropertyChanged: Implement this .NET 2.0 interface and create the PropertyChanged event. In your property setters, raise the PropertyChanged event whenever the value changed. This is the preferred technique in WPF.
  • DependencyProperty: Derive from DependencyObject and create a DependencyProperty. All change notification is handled by the WPF dependency property system. A side effect of this approach is that you create a dependency on the WPF assemblies in your business class assembly.
  • xxxPropertyChanged events: In .NET 1.x you can create an event with the same name as your property (WidthChanged) and raise the event when the property (Width) changes. Microsoft made sure that this scenario works in WPF because it makes it possible to bind to older .NET types. While it is usable, you'll find the INotifyPropertyChanged is easier to work with.

See Listing 1 for a sample business object that implements INotifyPropertyChanged and Listing 2 for an example of the DependencyProperty approach.

Data Context

Naturally WPF is not limited to employing UI elements as data sources. WPF offers the ability to bind to non-UI data too.

Every binding requires a data source object and a path to the source property. A data context allows the framework to look for a source object further up the logical tree. All FrameworkElements and FrameworkContentElements have a DataContext property. Here is an example:

<TextBlock Text='{Binding Path=Salary}' />

What's going on here? The Path property points to the Salary property but where is the XAML that specifies the data source? To answer that question, look at the following code.

In C#:

  // in the Loaded event procedure
  var emp = new Employee();
  emp.FirstName = "Johnny";
  emp.LastName = "Appleseed";
  emp.Salary = 15000M;
    
  // sets the Datacontext for the Page
  this.DataContext = emp;

In Visual Basic:

  ' in the Loaded event procedure
  Dim emp = New Employee()
  emp.FirstName = "Johnny"
  emp.LastName = "Appleseed"
  emp.Salary = 15000D
    
  ' sets the Datacontext for the Page
  Me.DataContext = emp

The data context is set in code. The last line in the snippet sets the data context for the entire page. When the binding object can't find a data context on the TextBlock, it walks the logical tree looking for a data context on a parent element. If there is none to be found, the default error handling occurs.

The next snippet shows how to apply different data contexts to elements on a page.

In C#:

// setting different data contexts
   var emp1 = new Employee();
   emp1.LastName = "Appleseed";
   
   stackPanel1.DataContext = emp1;
    
   var emp2 = new Employee();
   emp2.LastName = "Washington";
   dockPanel1.DataContext = emp2;

In Visual Basic:

' setting different data contexts
  Dim emp1 = New Employee()
  emp1.LastName = "Appleseed"
    
  stackPanel1.DataContext = emp1
    
  Dim emp2 = New Employee()
  emp2.LastName = "Washington"
  dockPanel1.DataContext = emp2

The Binding class has a constructor that takes a Path string. This means you can leave off the Path property entirely and use the shorter syntax shown here:

<TextBlock Text='{Binding Path=Salary}' />
<! -This binding works without the
   explicit Path property-->
<TextBlock Text='{Binding Salary}' />
    

Binding Extension

The Binding class is the main actor in the data binding story. It has a simple and easy to understand API. Here are some of the common binding properties:

  • ElementName: The data source is another element. The source element must have a name specified, usually with the x:Name attribute.
  • Source: Provide a reference to a valid object source. A binding configured with the Source property takes precedence over any applied data context.
  • RelativeSource: The source is a property on a related object.
  • Path: Provide navigation instructions for finding the data source property. The simplest path is merely the name of a property:
 <!-- Path to sub properties-->
 <TextBlock xx='{Binding Path=UserName.Length}' />
    
 <!-- Path to attached property -->
 <TextBlock xx='{Binding Path=(Canvas.Top)}' />
    
 <!-- Path to Indexer property-->
 <TextBlock xx='{Binding Path='{Brushes[2]}' />

  • XPath: Provide XPath navigation instructions for finding the XML source node.

What Can Be a Data Source?

You can use any type as a data source as long as it has a public parameterless constructor and at least one public property. Here's a sample of binding to System.String. In the example below, both TextBlock elements have a name, which makes them accessible in the *.cs/vb file. You set the textBox2 binding in the XAML file and the data context in the code behind:

  <StackPanel Margin='20'>
    <Label>Via Code:</Label>
    <TextBlock x:Name='tb1'
               Margin='20'
               Background='LightGray'
               Text="" />
<Label>Via Binding:</Label>
    <TextBlock x:Name='tb2'
               Margin='20'
               Background='LightGray'
               Text="{Binding}" />
    
    </StackPanel>

In the C# code-behind file:

string sample;
public BindingToString()
{
  InitializeComponent();
  sample = "ABC DEF GHI JKL MNO PQR";
    
  // assign directly to the Text property
  tb1.Text = sample;
    
  // register with the binding system
  tb2.DataContext = sample;
  // there must also be a binding in the XAML
  // or here in code
    
}

In the Visual Basic code-behind file:

Private sample As String
Public Sub New()
  InitializeComponent()
  sample = "ABC DEF GHI JKL MNO PQR"
    
  ' assign directly to the Text property
  textBox1.Text = sample
    
  ' register with the binding system
  textBox2.DataContext = sample
  ' there must also be a binding in the XAML
  ' or here in code
    
End Sub

Storing Items in Resources

In a few minutes I'm going to show you how to establish a binding without writing any code. Yes, I'm talking about a XAML-only binding. However, before tackling that subject I want to take a few minutes to discuss XAML resources. The resource framework exists in order to provide reusable items within your XAML. I’ll start by discussing the XAML parser.

When the XAML parser encounters a WPF element in a XAML file, it creates an instance of the underlying type. This is possible because there is a one-to-one mapping between every element in the http://schemas.microsoft.com/winfx/2006/xaml/presentation namespace and an existing WPF class in a .NET assembly. Thus the parser knows how to turn the <Button> element into an instance of the System.Windows.Controls.Button class. This is largely hidden if you use the Visual Studio XAML editor to write XAML. The IntelliSense shows you the allowed elements and the compiler flags any elements that it doesn't recognize.

When writing code you often create variables to hold class instances so that you can refer to them elsewhere in your code. The WPF architects believed that it was important to implement reusable items in XAML too. So the resources framework was born. To create a XAML variable you add it to a ResourceDictionary. To reference the stored item use the StaticResource or DynamicResource markup extension. Now you just need to know how to create a resource dictionary in your XAML.

A quick inspection of the WPF API shows that every FrameworkElement has a resource dictionary available in its Resources property.. Take any framework element in a XAML file, add an item to its Resources property, and your item is accessible in that element and any of its children. Since the ResourceDictionary stores the items in a simple hashtable, all you need to add an item is a key and the object instance.

Before looking at the XAML way, I'll show you the equivalent as written in code. The following example demonstrates how to add a style to several text boxes in the code-behind file.

In C#:

// target type for style
// is the TextBox
var s = new Style(typeof(TextBox));
var backSet = new Setter();
 
backSet.Property = BackgroundProperty;
backSet.Value =
   new SolidColorBrush(Colors.SteelBlue);
    
   s.Setters.Add(backSet);
    
// apply the style to
// the TextBox
textBox1.Style = s;
textBox2.Style = s;

In Visual Basic:

' target type for style
' is the TextBox
Dim s = New Style(GetType(TextBox))
Dim backSet = New Setter()
    
backSet.Property = BackgroundProperty
backSet.Value = New SolidColorBrush(Colors.SteelBlue)
    
   s.Setters.Add(backSet)
    
' apply the style to
' the TextBox
textBox1.Style = s
textBox2.Style = s

In the example above, the first step was to create the style variable, and then add some property setters. Once you added the style setters to the Setters collection, the style was applied to the individual text boxes.

To accomplish the same thing in XAML, you need to create the item (variable) in a Resources section. Then you use the StaticResource markup extension to assign the resource to the text boxes.

In XAML:

<! -- You must provide each element in a
     Resources section with a key.
     The key - element pair are added
     to the ResourceDictionary's hashtable
     -->
<Page.Resources>
  
  <Style x:Key='demoStyle'
         TargetType='TextBox'>
    <Setter Property='Background'
            Value='SteelBlue' />
  </Style>
</Page.Resources>
<StackPanel>
  <!-- reference the resource with the
       StaticResource markup extension -->
  <TextBox Style='{StaticResource demoStyle}'
           Text='Setting Style from a Page Resource' />
  <TextBox Style='{StaticResource demoStyle}'
           Text='Setting Style from a Page Resource' />
</StackPanel>

Styles are not the only element that you can store in a resource dictionary. It's common to store Brushes and Templates there as well. In fact, as you'll see in the next section, you can instantiate and store nearly any .NET type within a resource dictionary. So far you have seen how to do binding with code.... in the next issue of CoDe Magazine I'll take a look at XAML binding.