Powered by

US - English
NEW! Silverlight 5 is available Learn More

Data Binding to Controls

By Microsoft Silverlight Team|March 5, 2009|Level 300 : Intermediate

Summary

Most Silverlight-based applications display data in controls. In many cases, the data is a business object or a collection of business objects, such as stock quotes, headlines, or images. In addition, you often want to enable the user to select an item from a list and then display details about that item in another control, such as a text box.

This QuickStart shows you how to bind a control to a single item or bind a list control to a collection of items. In addition, this QuickStart shows you how to customize the display of control items, implement a details view based on a selection, and convert data for display.

This QuickStart contains the following sections:

Binding a Control to a Single Item

A data binding consists of a target and a source. The target of a binding typically is a control property. The target must be a DependencyProperty.

The following shows an example of binding a control to a single item. The target is the Text property of a text box control. The source is a simple music Recording class.

XAML

<Grid x:Name="LayoutRoot" Background="White" HorizontalAlignment="Center" >
    <TextBox VerticalAlignment="Top" IsReadOnly="True" Margin="5" 
       TextWrapping="Wrap" Height="50" Width="200" 
       Text="{Binding}" x:Name="textBox1"/>
</Grid>

C#

// A simple business object
public class Recording
{
    public Recording() { }

    public Recording(string artistName, string cdName, DateTime release)
    {
        Artist = artistName;
        Name = cdName;
        ReleaseDate = release;
    }

    public string Artist { get; set; }
    public string Name { get; set; }
    public DateTime ReleaseDate { get; set; }

    // Override the ToString method.
    public override string ToString()
    {            
        return Name + " by " + Artist + ", Released: " + ReleaseDate.ToShortDateString();
    }
    
}

...

// Set the data context to a new Recording.
textBox1.DataContext = new Recording("Chris Sells", "Chris Sells Live",
    new DateTime(2008, 2, 5));

Visual Basic

Public Class Recording

    Public Sub New()
    End Sub

    Public Sub New(ByVal artistName As String, ByVal cdName As String, _
        ByVal release As DateTime)
        
        Artist = artistName 
        Name = cdName 
        ReleaseDate = release
    End Sub
    
    Public Property Artist As String
    Public Property Name As String
    Public Property ReleaseDate As DateTime 
 
    ' Override ToString.
    Public Overloads Overrides Function ToString() As String 
        Return Name + " by " + Artist + ", Released: " + releaseDate.ToShortDateString()
    End Function
End Class

    ...

' Set the data context to a new recording.
textBox1.DataContext = New Recording("Chris Sells", "Chris Sells Live", _
    New DateTime(2008, 2, 5))

To display a music recording in a text box, the control's Text property is set to a Binding by using a markup extension. In this example, the binding mode is BindingMode.OneWay by default, which means that data is retrieved from the source, but changes are not propagated back to the source. For more information about markup extensions and the syntax, see Binding Markup Extension in the Silverlight documentation on MSDN.

The Recording class has three public properties and a ToString method override. The properties are Artist, Name, and ReleaseDate. The ToString method is significant, because if no formatting is specified, the ToString method is called on a bound object for display purposes. The Binding.Source property for the binding is not set directly; instead, the FrameworkElement.DataContext property for the TextBox control is set to a new Recording object.

Binding a Control to a Collection of Objects

The previous example demonstrates the syntax you use to bind data to controls, but it is not very realistic. A more common scenario is to bind to a collection of business objects. The generic ObservableCollection class is a good collection choice for data binding, because it implements the INotifyPropertyChanged and INotifyCollectionChanged interfaces. These interfaces provide change notification to bound controls when an item in the list changes or a property of the list itself changes. If you want your bound controls to update with changes to properties of objects in the collection, the business object should also implement INotifyPropertyChanged.

The following example binds a collection of music Recording objects to a ComboBox. To try this example, click the down arrow in the combo box to see the list of bound recordings.

XAML

<StackPanel x:Name="LayoutRoot" Background="White">
    <ComboBox x:Name="ComboBox1" Margin="5" Height="40" Width="300"
        ItemsSource="{Binding}" /> 
</StackPanel>
 

C#

public ObservableCollection<Recording> MyMusic = new ObservableCollection<Recording>();

public Page()
{
    InitializeComponent();

    // Add items to the collection.
    MyMusic.Add(new Recording("Chris Sells", "Chris Sells Live",
        new DateTime(2008, 2, 5)));
    MyMusic.Add(new Recording("Luka Abrus",
        "The Road to Redmond", new DateTime(2007, 4, 3)));
    MyMusic.Add(new Recording("Jim Hance",
        "The Best of Jim Hance", new DateTime(2007, 2, 6)));

    // Set the data context for the combo box.
    ComboBox1.DataContext = MyMusic;
}

Visual Basic

Public MyMusic As New ObservableCollection(Of Recording)()
 
Public Sub New()
    InitializeComponent()
    ' Add items to the collection.
    MyMusic.Add(New Recording("Chris Sells", "Chris Sells Live", _
        New DateTime(2008, 2, 5)))
    MyMusic.Add(New Recording("Luka Abrus", "The Road to Redmond", _
        New DateTime(2007, 4, 3)))
    MyMusic.Add(New Recording("Jim Hance", "The Best of Jim Hance", _
        New DateTime(2007, 2, 6)))

    ' Set the data context for the combo box.
    ComboBox1.DataContext = MyMusic
End Sub

To display the music recordings in the ComboBox, the control's ItemsControl.ItemsSource property is set to a Binding, and the FrameworkElement.DataContext property for the ComboBox control is set to the collection of Recording objects, which provides the source for the binding. A ComboBoxItem is created for each item in the collection. ToString is automatically called on each Recording object to display it in the combo box item.

Displaying Items in a Control by using a Data Template

You can display items in a list by using the item's ToString method. However, a more common scenario is to provide a customized display of data bound items by using a DataTemplate. A DataTemplate enables you to customize how list items are displayed in a control. Typically, you set the data template by using the ContentControl.ContentTemplate property of a content control or the ItemsControl.ItemTemplate property of an items control.

The following example shows the same list of recordings bound to a combo box by using a data template. A combo box is an ItemsControl, which means that you establish a data template for each item by setting its ItemTemplate property to a data template. To try this example, click the down arrow to see the list of recordings. Notice how the recordings look different from the previous example. The artist and CD name are displayed in a custom format.

XAML

<ComboBox x:Name="ComboWithTemplate" Margin="5" 
    Width="400" HorizontalAlignment="Left"
    ItemsSource="{Binding}" >
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal" Margin="2">
                <TextBlock Text="Artist:" Margin="2" />
                <TextBlock Text="{Binding Artist}" Margin="2" />
                <TextBlock Text="CD Name:" Margin="10,2,0,2" />
                <TextBlock Text="{Binding Name}" Margin="2" />
            </StackPanel>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

In the XAML, you can see the data template definition. The data template contains a StackPanel with four TextBlock controls. The stack panel has a horizontal orientation so that the four text block controls appear side by side. Two of the TextBlock controls are bound to the Artist and Name properties of a Recording object. The other two TextBlock controls display static text. For each bound item, the binding provides the path to the property on the Recording object. As in the previous example, this binding relies on the data context to be set to the list of recordings.

This XAML uses the property element syntax. For more information about XAML syntax, see XAML Overview in the Silverlight documentation on MSDN. For more information about control layout, see Object Positioning and Layout in the Silverlight documentation on MSDN.

Adding a Details View

To display the details of an item when it is selected from a collection, you have to create the appropriate UI and bind the UI to the data that you want it to display. Additionally, you must use a CollectionViewSource as the data context to enable the details view to bind to the current item.

The following example shows the same list of recordings, but this time the list is the data source of a CollectionViewSource instance. The data context of the layout root is set to the collection view source, and the combo box and details view inherit the data context from the layout root. This enables the combo box to display the same list of items while the details view shows information about the current item.

To try this example, click the down arrow and select different recordings. Notice that the artist, CD name, and release date appear in a details view below the combo box.

XAML

<!--The UI for the details view-->
<StackPanel x:Name="RecordingDetails">
    <TextBlock FontWeight="Bold" Text="{Binding Artist}" Margin="5,0,0,0"/>
    <TextBlock FontStyle="Italic" Text="{Binding Name}" Margin="5,0,0,0"/>
    <TextBlock Text="{Binding ReleaseDate}" Margin="5,0,0,0" />
</StackPanel>

C#

//ComboWithTemplate.DataContext = MyMusic;
LayoutRoot.DataContext = new CollectionViewSource { Source = MyMusic };

Visual Basic

'ComboWithTemplate.DataContext = MyMusic
LayoutRoot.DataContext = New CollectionViewSource With {.Source = MyMusic}

In this example, a StackPanel is added to the user control that contains the existing combo box. A Rectangle serves as a dividing line under the ComboBox. Next is a stack panel that contains four text blocks to display the recording details. The TextBlock.Text property of each text block is bound to a property on the Recording object.

Converting Data for Display in Controls

If you want to format and display a non-string type in a control, such as a TextBox, you can use a converter. For example, you could display a label and a formatted date instead of displaying just the date. (Note that you can use the BindingBase.StringFormat property if you just want to format the date by itself.)

The following example shows a converter implementation for the release date in the list of recordings. To try this example, click the down arrow and select different recordings. Notice that the release date in the drop-down list and details view is displayed in a custom format.

XAML

<UserControl x:Class="DataBindingControlsQuickStart4.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:DataBindingControlsQuickStart4"
    Width="300" Height="200">
    <UserControl.Resources>
        <local:StringFormatter x:Key="StringConverter"/>
    <UserControl.Resources />
    <!--The UI for the details view-->
    <StackPanel x:Name="RecordingDetails">
        <TextBlock Text="{Binding Artist}" />
        <TextBlock Text="{Binding Name}" />
        <TextBlock Text="{Binding ReleaseDate, 
            Converter={StaticResource StringConverter}, 
            ConverterParameter=Released: \{0:d\}}" />
    </StackPanel>

C#

public class StringFormatter : IValueConverter
{
    // This converts the value object to the string to display.
    // This will work with most simple types.
    public object Convert(object value, Type targetType, 
        object parameter, System.Globalization.CultureInfo culture)
    {
        // Retrieve the format string and use it to format the value.
        string formatString = parameter as string;
        if (!string.IsNullOrEmpty(formatString))
        {
            return string.Format(culture, formatString, value);
        }

        // If the format string is null or empty, simply 
        // call ToString() on the value.
        return value.ToString();
    }

    // No need to implement converting back on a one-way binding
    public object ConvertBack(object value, Type targetType,
        object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Visual Basic

Public Class StringFormatter
    Implements IValueConverter
    
    ' This converts the DateTime object to the string to display.
    Public Function Convert(ByVal value As Object, ByVal targetType As Type, _
        ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) _ 
        As Object Implements IValueConverter.Convert
        
        ' Retrieve the format string and use it to format the value.
        Dim formatString As String = TryCast(parameter, String)        
        If Not String.IsNullOrEmpty(formatString) Then
            Return String.Format(culture, formatString, value)
        End If
        
        ' If the format string is null or empty, simply call ToString() 
        ' on the value.
        Return value.ToString()       
    End Function

    ' No need to implement converting back on a one-way binding
    Public Function ConvertBack(ByVal value As Object, ByVal targetType As Type, _
        ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) _ 
        As Object Implements IValueConverter.ConvertBack
        Throw New NotImplementedException()
    End Function
End Class

A converter is a class that derives from the IValueConverter interface. IValueConverter has two methods; Convert and ConvertBack. For a one-way binding from the data source to the binding target, you only have to implement the Convert method. The converter in this example is fairly generic. You can pass the desired string format as a parameter, and the converter uses the Format method to perform the conversion. If no format string is passed, the converter returns the result of calling ToString on the object.

Once you implement the converter, you create an instance of the converter class and tell the bindings to use this instance. In this example, this is performed in XAML. An instance of the converter is created as a static resource and assigned a key. The key is used when the converter property is set on the binding.

For more information about how to convert data for display in controls, see IValueConverter in the Silverlight documentation on MSDN.

See Also

Microsoft Silverlight Team

By Microsoft Silverlight Team, Silverlight is a powerful development platform for creating engaging, interactive user experiences for Web, desktop, and mobile applications when online or offline.

Comments (0)