Databinding and Data Templates are perhaps the most powerful features of WPF. Whatever your experiences with databinding in previous technologies, MS or otherwise, I think you will be impressed with the new goods. To begin with, support for datadinding is built into WPF from its core. Almost every graphics/UI object that you will work with in WPF inherits from DependencyObject. The functionality supported by this base is what powers animation, styling and databinding. Without going into too much detail, objects that inherit from DependencyObject support a special type of property called a DependencyProperty. Most of the properties you will work with, such as Text, Content, Width, Height, etc, are DependencyProperties. Any dependency property can be animated, styled and databound. WPF support for databinding is so rich, that I will only be able to demonstrate the most basic of examples in this post. The best resource for digging deeper is Beatriz Costa’s blog. I recommend that you start from the very first post and read everything up to the present. This may seem like quite a task, but the time you will save by gaining a thorough understanding of databinding is worth it.
The first example I would like to show is a very common scenario. You have some object representing a person, customer, employee, etc and you want to display their information in the UI for editing purposes. Here’s some markup:
The screenshot is not very impressive, but you get the idea. I have created a Person object with first and last name public properties. There is also a public property called Address of type Address which has street, city and state properties. I have assigned an instance of the Person object to the DataContext property of the window in the code beside. Every FrameworkElement has this property. When binding WPF searches from the current element up the tree until it finds a DataContext property it can bind to. Notice that the markup syntax is enclosed in curly braces and begins with the word ‘Binding.’ You will see other markup extensions like this, but ‘Binding’ is the most common. Notice the ‘Path’ expression and the difference between how I have defined the binding to FirstName and LastName. These statements are equivalent; LastName demonstrates the abbreviated version. Also, notice how I have accessed the Address object. If you were to run this program, you would notice that all changes to the UI were propagated to the Person object, but changes to the Person object are not propagated back to the UI. For this to work you must implement the INotifyPropertyChanged interface, a trivial task.
Besides editing the person object, let’s say that we want to display the information elsewhere in our application, in a ‘contact card’ fashion. Let’s also say that we want to display this information in a consistent way in several different places. Using previous technologies we would likely create a custom control or user control to meet this need (or custom rendering logic for an existing control). In WPF we have both of these options, but additionally we can create a DataTemplate:
I got a little more advanced with this sample. I wanted to do something that looked decent at least once during this series. To the explanation:
A DataTemplate is a visualization of something nonvisual. In this case we have a Person class, but what does that look like? Here, I’ve created a DataTemplate and set its DataType to person. Now WPF knows how to render this type of class when databinding occurs. You can also assign a key to a template and reference the template by this rather than having it automatically applied. This is the same idea as using css to apply a style to all div elements verses applying the style based on class name. The difference is that here we are defining how .NET classes should be rendered. DataTemplates can also be scoped at any level of the application. Notice that the template is defined inside of a Grid.Resources tag. Every FrameworkElement has a resource collection. This means that you can store DataTemplate at virtually any level of the UI hierarchy. So I could define what Person looks like at the application, window, panel or control level. Here, I have defined the appearance of person and scoped it to all controls within the grid. The listbox contained within the grid picks up the template automatically when I set its ItemsSource to a collection of Person objects in the code beside. DataTemplates are also aware of .NET inheritance. So if I have employee and manager classes that both derive from person, they will be rendered with this template as well. But, if I define a DataTemplate specifically for the manager class, WPF will use the more specific template. Ah yes . . . consider the possibilities . . .
There is so much more to databinding and DataTemplates than I have said here. I am quite embarrassed at the lack of coverage I have been able to give. But I have to move on. As food for thought, here are some other things supported out of the box with WPF databinding: You can have conditional binding based on business rule validation, conditional template selection based on business rules, converters that shape data when binding to and from the UI, DataTriggers that change the appearance of the template based on values in the data, binding between different UI elements based on name or relative position in the UI hierarchy, a choice of four different binding modes and a choice of what type of event triggers the binding, and bindings to data sources that pass in other bindings as parameters, etc. The list goes on and on. Again, let me mention Beatriz Costa’s blog as a great source of info. Once you have learned the basics, go there and read everything.
I have attached the solution files for the final example.
NEXT POST: WPF Styles and Control Template
11-10-2006 10:56 AM