Suitable Data Sources
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 an example of binding to a System.String type. In the example below, both TextBlock elements have a
Name, which makes them accessible in the
*.cs or
*.vb code-behind file. You set the TextBox (
tb2) binding in the XAML file, and set 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
}
The equivalent code in a Visual Basic code-behind file is:
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
You can create bindings completely declaratively— a XAML-only binding; you'll see shortly how to establish such bindings without writing any program code. However, to tackle that subject I first need to discuss XAML resources. The resource framework exists to provide easy access to 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 process is largely hidden if you use the Visual Studio XAML editor to write XAML. The IntelliSense window 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 from that element and any of its children. Because a ResourceDictionary stores 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 code. The following example demonstrates how to add a style to several text boxes in the code-behind file.
// 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;
' 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
The preceding example first creates the style variable, and then adds some property setters. After adding the style setters to the
Setters collection, the style gets 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 is 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 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 article, 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 deeper look at XAML-based binding.
You'll find all the code for this article in the
downloadable DataBindingExample project. The project includes additional binding examples for you to study.
There is a still place for traditional binding—a business class value bound to a control property. But you'll find that there are dozens of dependency properties on a TextBlock, any of which can be a suitable binding target, and might simplify your development tasks. For examples, look at the control and data templates in WPF; they make extensive use of binding.