DATABASE

Binding Application Data to the UI objects in Silverlight

9/14/2010 4:10:38 PM

1. Problem

You need to bind various properties on UI objects in Silverlight to application data available in managed code.

2. Solution

Use the Binding markup extension to specify the appropriate data bindings in XAML or use the FrameworkElement.SetBinding() method to do the same in the codebehind.

3. How It Works

The Binding markup extension or the FrameworkElement.SetBinding() method can be used to bind properties on instances of application data types to dependency properties defined on any type inheriting from FrameworkElement. The application data type properties are called the source properties for the binding, and the dependency properties are called the target properties.

3.1. Binding Expression

XAML exposes several markup extensions, one of which is Binding. A markup extension provides an extension to the default XAML namespaces and is used as a keyword within a set of curly braces in your XAML document. The syntax for using the Binding extension to bind some data to a property is as follows:

  "{Binding sourcePropertyPath, oneOrMoreBindingProperties}" .../>

The entire Binding statement within the curly braces, including all the property settings, is collectively called a binding expression.

The targetPropertyName points to a dependency property on the XAML element. The sourcePropertyPath is the complete, qualified path to a property in the data source object hierarchy. The dot notation can be used to indicate properties belonging to type instances that are nested within other instances. The Binding extension also exposes several properties that can be set to impact various behaviors of the binding, such as the direction of the data flow, input validation behavior, or conversion of values. We will discuss most of the properties in subsequent recipes.

3.2. Dependency Properties

Dependency properties are unique to the Silverlight runtime and have some differences compared with standard .NET properties. One of the major differences is that a target property needs to be a dependency property to allow data binding. You can read about dependency properties in the Silverlight SDK documentation.

3.3. Associating the Data Source

The data source is a CLR object, and the source properties are public properties with at least public get accessors defined. The data source can be set as the DataContext on the element at the level where the binding is being set or on a containing element, thus making it automatically available as the DataContext to all children elements. The following is an example of using the DataContext, where a CLR type declared as a resource named CLRDS_Company is being used as the data source on the Grid and the Text property on a contained TextBlock is being bound to the Street property on the data source object:


DataContext="{StaticResource CLRDS_Company}">


The data source can also be set as the Source property on the binding itself. This may be necessary if the data for the elements in your UI came from different data sources and just providing a higher-level DataContext was not enough. A sample of the syntax for that would look like the following, where the Source can be set to a different data source than the one defined in the data context:


In either case, you can define the data source by referencing a CLR type as a resource in your XAML, as shown here:




The local: prefix is a custom namespace defined to bring in the Company type. Both custom namespace mapping and the StaticResource extension used to reference such resources in XAML.

4. The Code

The CLR object model shown in Listing 1 is being used as the application data source for this sample.

Listing 1. Application Data Classes
using System.Collections.Generic;

namespace Recipe4_1
{
public class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public long PhoneNum { get; set; }
}
public class Company
{
public string Name { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public int ZipCode { get; set; }
public List Employees { get; set; }

public Company()
{
this.Name = "Woodgrove Bank";
this.Street = "555 Wall Street";
this.City = "New York";
this.State = "NY";
this.ZipCode = 10005;
this.Employees = new List();

this.Employees.Add(
new Employee
{
FirstName = "Joe",
LastName = "Duffin",
PhoneNum = 2125551212
});
this.Employees.Add(
new Employee


{
FirstName = "Alex",
LastName = "Bleeker",
PhoneNum = 7185551212
});

//rest of the initialization code omitted for brevity
this.Employees.Add(new Employee
{
FirstName = "Nelly",
LastName = "Myers",
PhoneNum = 7325551212
});
this.Employees.Add(new Employee
{
FirstName = "Marcus",
LastName = "Bernard",
PhoneNum = 7325551414
});
this.Employees.Add(new Employee
{
FirstName = "Juliette",
LastName = "Bernard",
PhoneNum = 7325551414
});
this.Employees.Add(new Employee
{
FirstName = "Cory",
LastName = "Winston",
PhoneNum = 9085551414
});
this.Employees.Add(new Employee
{
FirstName = "Randall",
LastName = "Valetta",
PhoneNum = 2015551414
});

this.Employees.Add(new Employee
{
FirstName = "Maurice",
LastName = "Dutronc",
PhoneNum = 3635551414
});
this.Employees.Add(new Employee
{

FirstName = "Nathan",
LastName = "Adams",
PhoneNum = 3635551414
});
this.Employees.Add(new Employee
{
FirstName = "Harold",
LastName = "Anthony",
PhoneNum = 3745551414
});
this.Employees.Add(new Employee
{
FirstName = "Paul",
LastName = "Gomez",
PhoneNum = 3415551414
});

this.Employees.Add(new Employee
{
FirstName = "Martha",
LastName = "Willard",
PhoneNum = 4795551414
});
this.Employees.Add(new Employee
{
FirstName = "Barry",
LastName = "Driver",
PhoneNum = 4165551414
});
this.Employees.Add(new Employee
{
FirstName = "Peter",
LastName = "Martinson",
PhoneNum = 4165551414
});
this.Employees.Add(new Employee
{
FirstName = "Mike",
LastName = "Dempsey",
PhoneNum = 4165551656
});
}
}
}


The XAML page shown in Listing 2 declares an instance of the Company class to use as a data source.

Listing 2. XAML for the Page
<UserControl x:Class="Recipe4_1.MainPage"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:local="clr-namespace:Recipe4_1"
Width="400" Height="300" >

<UserControl.Resources>
<local:Company x:Key="CLRDS_Company" />
</UserControl.Resources>

<Grid x:Name="LayoutRoot" Background="White"
DataContext="{StaticResource CLRDS_Company}" Margin="8,8,8,8">

<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.38*"/>
<ColumnDefinition Width="0.032*"/>
<ColumnDefinition Width="0.238*"/>
<ColumnDefinition Width="0.028*"/>
<ColumnDefinition Width="0.322*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="0.103*"/>
<RowDefinition Height="0.114*"/>
<RowDefinition Height="0.783*"/>
</Grid.RowDefinitions>
<TextBlock Grid.ColumnSpan="5" x:Name="tbxCompanyName"/>
<TextBlock Text="{Binding Street}" Grid.ColumnSpan="1" Grid.Row="1" />
<TextBlock Text="," Grid.Column="1" Grid.Row="1" />
<TextBlock Text="{Binding City}" Grid.Column="2"
Grid.ColumnSpan="1" Grid.Row="1" />
<TextBlock Text="," Grid.Column="3" Grid.ColumnSpan="1"
Grid.Row="1" Grid.RowSpan="1"/>
<StackPanel Margin="0,0,0,8" Orientation="Horizontal"
Grid.Column="4" Grid.ColumnSpan="1"
Grid.Row="1" Grid.RowSpan="1">
<TextBlock Margin="0,0,5,0" Text="{Binding State}" />
<TextBlock Text="{Binding Zip}"/>
</StackPanel>

<ListBox x:Name="lbxEmployees" Grid.RowSpan="1" Grid.Row="2"
             Grid.ColumnSpan="5" ItemsSource="{Binding Employees}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding FirstName}"
Margin="0,0,5,0" />
<TextBlock Grid.Column="1" Text="{Binding LastName}"
Margin="0,0,5,0"/>
<TextBlock Grid.Column="2" Text="{Binding PhoneNum}"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>

</UserControl>
To bind the data to the UI, you set the DataContext property on the top-level grid named LayoutRoot. As discussed earlier, the DataContext is made available to all contained controls inside the grid so that any binding expression automatically uses it as the binding source, thus negating the need to specify the source explicitly in the binding statement. So for each of the binding expressions in the UI for the controls contained immediately within the grid, you simply specify the name of the property in the Company type to which you want to bind the control's property.

You use a ListBox to display the Employees collection in the Company instance. You set the ItemTemplate for the ListBox to a DataTemplate that defines how each item in the ListBox is displayed. The DataTemplate is discussed in greater detail later in this chapter, but for now, think of it as a way to package the UI representation of a specific data type. By binding the ItemsSource property of the ListBox to the Employees property on the Company instance, you effectively provide an instance of the Employee class as the data source for each item in the ListBox. In the DataTemplate, you can then bind properties of individual elements to properties on the Employee class to display employee data. The page output for the application is shown in Figure 1.

Figure 1. The data-bound page

Note that the Company type being referenced as the CLRDS_Company resource will also need to have a default constructor defined to be referenced in XAML this way. If you do not have a default constructor, you can instantiate the type and set the DataContext in code like so:

LayoutRoot.DataContext = new Company(SomeParameter);

You can also create and set bindings in code if you need to. To do so, create and initialize an instance of the Binding type, and then use the SetBinding() method on the FrameworkElement type to associate it with a specific DependencyProperty, as shown in Listing 3.

Listing 3. Creating a Binding in Code
using System.Windows.Controls;
using System.Windows.Data;

namespace Recipe4_1
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
//In case you want to set the datacontext in code...
//LayoutRoot.DataContext = new Company();
//create a new Binding
Binding CompanyNameBinding = new Binding("Name");
//set properties on the Binding as needed
CompanyNameBinding.Mode = BindingMode.OneWay;
//apply the Binding to the DependencyProperty of
//choice on the appropriate object
tbxCompanyName.SetBinding(TextBlock.TextProperty,
CompanyNameBinding);

}
}
}

Before you apply the Binding, you can also set various properties on the Binding to control its behavior. The BindingMode setting in Listing 3 is one such property. BindingMode controls the direction of data flow in the Binding, and the OneWay setting stipulates that data only flow from the source to the target in this case.

To utilize the code in Listing 3, you will need to name the element that is targeted by the binding in XAML appropriately so that it becomes accessible to you in code. In the following snippet, you see how to name the TextBlock tbxCompanyName in Listing 2 so that you can refer to it in code.


DataContext="{StaticResource CLRDS_Company}">


Other  
 
Video
Top 10
SG50 Ferrari F12berlinetta : Prancing Horse for Lion City's 50th
The latest Audi TT : New angles for TT
Era of million-dollar luxury cars
Game Review : Hearthstone - Blackrock Mountain
Game Review : Battlefield Hardline
Google Chromecast
Keyboards for Apple iPad Air 2 (part 3) - Logitech Ultrathin Keyboard Cover for iPad Air 2
Keyboards for Apple iPad Air 2 (part 2) - Zagg Slim Book for iPad Air 2
Keyboards for Apple iPad Air 2 (part 1) - Belkin Qode Ultimate Pro Keyboard Case for iPad Air 2
Michael Kors Designs Stylish Tech Products for Women
REVIEW
- First look: Apple Watch

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
Popular Tags
Video Tutorail Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Exchange Server Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe Photoshop CorelDRAW X5 CorelDraw 10 windows Phone 7 windows Phone 8 Iphone