Writing applications for the phone will
likely involve data of some sort. Silverlight’s support for data binding
helps you build your applications in a much more powerful way, but what
is data binding exactly? Data binding is simply a way
to take data from a source (e.g., the value of a property on an object)
and show it in a XAML element. If that XAML element is a control, it
also supports pushing changes back to the source of the data. While that
is a pretty basic explanation, the explanation is correct. Data binding
is profoundly simple, and because it is simple, it is powerful.
1. Simple Data Binding
At the most basic level, a binding is a connector to pull data from a data source and put it in an element’s property. As you can see in Figure 1, a binding is in the middle of the data and the element (Control
).
Figure 1. Simple data binding
Bindings are defined as a markup extension. For example, here is a TextBox
bound to the Name
property:
<TextBox Text="{Binding Name, Source={StaticResource myData}}" />
The Binding
markup extension first takes a path to the
property to be bound to and then a number of optional elements. As you
can see in this example, the binding is pulling from a resource object
called myData
. When the data binding happens, it takes the source of the data binding and uses the property path (the Name
in this case) to navigate to the data it needs to put in the TextBox
’s Text
.
The path to the property must be a public property as it uses
reflection to call the getter of the public property to access the data
from the source.
Having to specify the source for bindings is relatively rare, though,
because when the source of an object changes you would have to change
it in a number of places. For example, this XAML would show a simple
editor for some data:
<StackPanel>
<TextBlock>Name</TextBlock>
<TextBox Text="{Binding Name, Source={StaticResource myData}}" />
<TextBlock>Phone Number</TextBlock>
<TextBox Text="{Binding Phone, Source={StaticResource myData}}" />
<TextBlock>BirthDate</TextBlock>
<TextBox Text="{Binding BirthDay, Source={StaticResource myData}}" />
</StackPanel>
Imagine that if the source changed, all of the TextBox
es would need to be rebound. Instead, data binding uses a property called DataContext
, which simply allows for the source of the data binding to exist along the hierarchy of the XAML. For example, if the DataContext
were set at the StackPanel
, all the controls that attempt data binding inside the StackPanel
would get their data from the DataContext
instead of needing specific sources:
<StackPanel DataContext="{StaticResource myData}">
<TextBlock>Name</TextBlock>
<TextBox Text="{Binding Name}" />
<TextBlock>Phone Number</TextBlock>
<TextBox Text="{Binding Phone}" />
<TextBlock>BirthDate</TextBlock>
<TextBox Text="{Binding BirthDay}" />
</StackPanel>
When the bindings pull their data they will look for a source, and
when they don’t have one they’ll search for the first non-null data
source in the hierarchy. In this case they will find it at the StackPanel
level and use that and the source for the data binding. The search for a DataContext
will continue up the hierarchy until a valid DataContext
is found. This walking of the XAML tree is not limited to the current
XAML document. If the data binding is happening inside a control that is
used on another XAML document, it will continue up through all the
parents until it exhausts the entire object tree.
Data binding supports three modes, as described in Table 1.
Table 1. Data Binding Modes
The pushing and pulling of changes is performed via reflection so
that all binding modes work with any .NET class. There are no
requirements for that class to work with data binding. The one exception
to that is if you want changes to the source object itself to be
reflected in the controls via data binding. For that to work, your
source classes must support a simple interface called INotifyPropertyChanged
.
When the source data changes, it notifies the binding that the data has
changes that will cause the binding to reread the data and change the
data in the control, as shown in Figure 2.
Figure 2. Changes in the source
2. Using a DataTemplate
List controls can show any list that supports IList
or IEnumerable
, but that’s only part of the story. List controls also support the ability to use DataTemplate
s to customize the look of individual items in the list. You can use a DataTemplate
to specify the ItemTemplate
to use arbitrary XAML to define what is contained in a ListBox
. For example:
<ListBox ItemsSource="{StaticResource theData}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Name}" />
<Image Source="{Binding ImageUrl}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
As this ListBox
creates its individual items, it will use the DataTemplate
as a factory to create the XAML that is contained inside. The DataContext
for the created XAML becomes the individual item to be shown in the ListBox
so that the data binding inside the DataTemplate
just works.