WEBINAR:
On-Demand
Building the Right Environment to Support AI, Machine Learning and Deep Learning

ll applications are dependent on data in some form and most developers find themselves writing reams of data access code. The
first article in this series discussed how to control the data binding mechanisms of WPF programmatically. Along with a programmatic interface, WPF also provides a
declarative data binding interface, which is the topic of this article.
XAML Binding
It's possible to set up a binding using only XAML. The XAML parser understands how to parse and instantiate many of the WPF framework classes, but doesn't know how to work with non-WPF classes unless they're registered with the parser. Therefore, the first step in using a custom data source is to associate an XML namespace with a CLR namespace. The following XAML snippet shows how to set up an
xmlns "sys" namespace for the System namespace in
mscorlib and a
"local" namespace for a custom assembly:
<Page
xmlns:sys='clr-namespace:System;assembly=mscorlib'
xmlns:local='clr-namespace:MyLib' />
Next, you need to create an instance of the type and store it in a discoverable location. In C#/Visual Basic, you would create a variable and instantiate the type. In XAML, you have to put the instance in a resources section. The XAML parser instantiates your tTeype and adds the instance to the resource dictionary. You provide a key for the resource so that you can retrieve the instance later:
<Page.Resources>
<!-- Instantiate a string
and load into resource dictionary -->
<sys:String x:Key='sample'>ABC 123 DEF 456
</sys:String>
<!-- Instantiate an employee
and load into resource dictionary -->
<local:Employee x:Key='emp'
FirstName='Jimmy'
LastName='Crickett'
Salary='2500'
/>
</Page.Resources>
Now you can set up the binding in the main part of the page and employ the
Source property for the configuration. Set the
Source property to refer to an instance of an object, in this case the sample string declared in the
Page.Resources section shown previously. Bind the first
TextBlock directly to the string and use a
Path for the second
TextBlock to show the second Char in the
String.Chars array:
<TextBlock
Text="{Binding Source=
{StaticResource sample}}" />
<TextBlock Text="{Binding Source=
{StaticResource sample},Path=[2]}" />
The next example shows comparable XAML that binds to the Employee object:
<TextBlock
Text="{Binding Source=
{StaticResource emp},Path=LastName}" />
Relative Source Binding
It's not necessary (or desirable) to name every element in a WPF logical tree, which can pose a problem when binding to other elements. Use the
ElementName property to specify a named element as the source. There are times when you won't know the element name but you'll want to bind to it anyway.
WPF is a complete rethinking of how to construct a UI development platform. Because Microsoft started with a blank slate, the WPF architects took the opportunity to engineer interesting ideas into their binding engine.
|
|
Sometimes you just want to say; "Bind to my parent StackPanel" or "Bind to the previous item in this list." Another example is when you want to bind to a different property of the same element. In other words, you need a way to configure the element binding without requiring an element name—and XAML provides one. Use the
RelativeSource property when you need an element binding, but can't use the
ElementName property.
There are four modes available for
RelativeSource bindings, but only two are relevant to this article:
- Self: Reference any property on the current object. The next example shows some XAML that binds the TextBox Background property to the Text property on the same TextBox. Note that the example nests one markup extension within another. Run the application and try typing "Red" or "#FF336688" in the text box to see the background color change:
<TextBox Text='#FF55FFCC'
Background='{Binding Text,
RelativeSource={RelativeSource Self }}'/>
- FindAncestor: This binding walks the tree of parent elements looking for a specific type of ancestor element. You must specify the AncestorType (a DockPanel in the following example), to create the binding successfully. Use the AncestorLevel to skip over parent levels. For example, setting AncestorLevel=2 will skip one generation. This example binds the TextBox Background attribute to its grandparent DockPanel (so it will be blue):
<DockPanel Background='Blue'>
<DockPanel Background='Green'>
<TextBox Margin='20'
DockPanel.Dock="Top"
Background='{Binding Background ,
RelativeSource={RelativeSource FindAncestor,
AncestorType=DockPanel ,
AncestorLevel=2}}' />
</DockPanel>
</DockPanel>
Editor's Note: This article was first published in the January/February 2009 issue of CoDe Magazine, and is reprinted here by permission. |