Most UI objects in WPF have a DataContext property. Using this property, you can have that control, or other controls data bind to the object stored in the DataContext property. By default, this DataContext property is passed down the control hierarchy by default. This becomes very useful when nesting controls.
However, there is only one DataContext property on any given control. Sometimes, you may be creating a UserControl and you need to have 2 or more data bound properties. One way to do this is to encapsulate all your data inside a single class and have an instance of that class be stored in the DataContext. This may not be convenient though.
It’s possible to add additional property members to your UserControls that can then be data bound. For example, we have a data class that we are going to use.
public class Data
{
public string Name { get; set; }
public int Age { get; set; }
}
We need to add a property member to our UserControl to store the data.
public partial class DataControl : UserControl
{
// ...
public Data User
{
get { return (Data)GetValue(UserProperty); }
set { SetValue(UserProperty, value); }
}
public static readonly DependencyProperty UserProperty =
DependencyProperty.Register("User", typeof(Data),
typeof(DataControl), new UIPropertyMetadata());
}
Now the UserControl has a member called ‘User’ which can be referenced via data binding. In the Xaml for the UserControl, we can do this:
<UserControl
x:Name="Main">
<!-- ... -->
<TextBlock Text="{Binding User.Name, ElementName=Main}" />
<!-- ... -->
</UserControl>
What the above does is tells the TextBlock, that the data for the Text is in an element called “Main”, which we’ve labelled our UserControl via the x:Name property, and in that element, get the data from “User.Name”. “User” is the property on the control, “Name” is the member of the Data class that contains the user’s name which we want to put in this text box.
Had the dependency property been something like a simple string, we could have just done {Binding User, ElementName=Main}
In our main window, we’d populate the control with the data by doing the following:
<Window.Resources>
<local:Data x:Key="User" Name="Matt" Age="33" />
</Window.Resources>
<Grid>
<local:DataControl
User="{Binding Source={StaticResource User}}" />
</Grid>
Once that’s done, you can repeat as necessary to add more data members to your controls as required. There is only one DataContext member, but you can add as many other members as you need. It also helps towards type-safety.
My sample project can be downloaded here: DataBindingEx.zip (9.25kb)