Flexible and Powerful Data Binding with WPF 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. |