For almost any developer who has worked in GUIs the concept of data binding should be at least familiar. If you have an Article and want to show its code and price, you just place two textboxes bound to those properties and place some invisible magical control who ensures that the controls and the data objects are kept synchronized. As long as you didn't push it too far, it worked just fine, and allowed you to forget about some tedious GUI programming.
Silverlight, of course, has its own flavor of data binding, partially inherited from its big brother. This time, however, things have been made much easier.
Any Silverlight page or control has a visual tree, defined in XAML, which specifies a root container, its controls, their controls, and so on. Any Silverlight control has, as well, a property of type Object named DataContext. This property, when set to a control, is inherited by all of its children. Therefore, if you have a control C inside B inside A, and you set:
A.DataContext = myArticle;
C.DataContext = myName;
Then A and B will share myArticle
as their DataContext, and C will have myName since it was manually set. To make C inherit its parent DataContext later, just set its property to null. Note that if you want to clear an object's DataContext, then you can't set it to null, you should set it to an empty object that has all the properties that the control expects.
What are these properties expected by the control? Silverlight has a special syntax to specify that a control's property binds to one of it's DataContext's properties. Nothing better to begin with than the classic TextBox
example:
<TextBlock Text="Name" />
<TextBlock Text="{Binding Name}" />
The first textblock will always display the text "Name", whereas the second one will search for a property named "Name" in its DataContext and display its value. You can even set it to bind two-ways, as an easy way to allow user input:
<TextBlock Text="{Binding Name, Mode=TwoWay}" />
Note that if the property does not exist then the binding will fail silently (warning you by a small notice in the output console if you happen to be debugging). Nevertheless, Beta 2 introduced an event to which you can attach and get these kind of errors.
Because it fails silently, it is not mandatory that a control's DataContext
always provides all of the binded properties, so an easy and dirty way of clearing a data context is setting it to String.Empty
.
Silverlight 2 in fact allows some interesting property paths, that allows you to bind to a property of a property of a property ... of the data bound object, traverse through a collection's hierarchy or refer to attached properties.
When you look for how to ensure that the GUI stays tuned with the data bound object's properties whenever they change, you find an old interface from 2.0 filling the gap: INotifyPropertyChanged. If you are wondering if its cousin, INotifyCollectionChanged, has a role to play here, just consider the following scenario:
<TextBlock Text="{Binding CourseName}" />
<ListBox ItemsSource="{Binding Students}"/>
Consider this class model, with the class Course
set as the visual tree's datacontext:
class Course
{
public ObservableCollectionStudents { get; set; }
public String CourseName { get; set; }
} class Student
{
public String Name { get; set; }
public int RegistrationNumber { get; set; }
public int CourseYear { get; set; }
public override string ToString() { return Name; }
}
What you will get is a TextBox displaying the course name, and a ListBox with the list of students in the course. Since the type of the Students collection is ObservableCollection, the most common INotifyCollectionChanged implementor, whenever you add a student to the course, the listbox is automatically updated.
If you want the same thing to happen with the name of the course, then you will have to manually implement INotifyPropertyChanged.
Note that you have a more complex property path for your bindings, suppose {Binding Course.Teacher.Address.Street}, then all objects in the path must implement INotifyPropertyChanged for it to refresh properly.
Going back to the example, you will notice that what is displayed as items in the ListBox are the ToString executions of all the Students contained in the items source collection. Though it is the easiest representation, it will hardly ever be the representation you want to show to the end user.
To solve this issue, Silverlight has included the concept of DataTemplates, which allow you to customize the way an object is rendered when contained in a presenter (such as a ListBoxItem).
But that is more than enough to fill a new post, which will be coming real soon.