y article WPF Wonders: Building Control Templates
explains how to use templates to tell a control what components it should use to do its work. For example, you can use a template to make a Button use a polygon for its surface instead of the usual rectangle. The template can also determine how the Button reacts to state-changing events such as being under the mouse, being defaulted, being pressed, and so forth. This kind of template can change a control's fundamental structure and behavior.
This article describes another kind of template: a DataTemplate. A DataTemplate tells controls that display a series of items (such as ListBox, ComboBox, and TreeView) how to display their data items. Just as a control template tells a control what pieces to use to display itself, a DataTemplate tells a control what pieces to use to display each of its data items.
Suppose you work in a pet store's IT department and your mission, should you decide you want to keep your job, is to build a program that lets customers sign up for classes. Step one is listing the classes.
Figure 1 shows a simple ListBox for this "CoursesList" example program. The ListBox displays a list of classes. It's functional and not completely ugly but still rather boring.
|Figure 1. Lifeless ListBox: This ListBox displays a list of classes in a functional but static way.|
A big advantage of this kind of list is that it is very easy to use. The following XAML code fragment shows how the CoursesList program builds this list. (You can download this and all of the other example programs described in this article in C# and Visual Basic versions in the source code download.)
<ListBox Margin="10" Background="LightGreen">
<ListBoxItem Content="Dog Training, 1: Mondays, 90.00"/>
<ListBoxItem Content="Dog Training, 2: Tuesdays, 90.00"/>
<ListBoxItem Content="Cat Training: Tuesdays, 80.00"/>
This is simple but not very flexible. If the list of classes changes (and it certainly will), you'll need to update the XAML code.
A better strategy would be to bind the ListBox to a data source that can be loaded at run time. (This article is about data templates, so I don't want to go into data binding in great depth. Fortunately in this case, the solution is practically trivial.)
A second version of the CoursesList program creates its ListBox with the following code. (Different versions of this program are stored in the download in directories named CoursesList, CoursesList2, CoursesList3, and so forth.) The keys to this code are that it gives the control a name for the code-behind to use and it does not put any items in the list.
<ListBox Name="lstCourses" Margin="10" Background="LightGreen"/>
The program's new Course class has properties such as Name, Picture, DayOfWeek, Location, and Fee that define a course offering. The program creates a bunch of Course objects to define the course offerings and stores them in an array named all_courses. It then uses the following statement to tell the ListBox to get its items from the array.
lstCourses.ItemsSource = all_courses;
At this point, you might think you're home free. If you run the program, however, you'll see a list that contains dozens of items labeled "CoursesList.Course."
If you've used ListBoxes much (either the WPF or Windows Forms kind), then you probably know what's happening here. The ListBox is trying to display Course objects. It doesn't really know how to do that so it calls each object's ToString method to generate something that it understands. By default, ToString returns the name of the class, which is somewhat less than useful, so you get a list that will confuse and terrify the user.
One easy solution is to override the Course class's ToString method to make it return something more useful, as in the following code.
public override string ToString()
return Name + ": " + DayOfWeek + ", " + Fee;
With this change, the program once again produces the result shown in Figure 1. You've done a bunch of extra work (defined a class, overridden ToString, made a bunch of instances, and attached them to the ListBox) to get back to the result you had originally produced with a few simple lines of XAML.
The difference is that now the ListBox is bound to data defined in the code-behind. This example hard codes its list of offerings, but it could have loaded the data from a database instead. Later, when the course offerings change, the code-behind just needs to pick up the new changes and the ListBox will display them.
The result still isn't very pretty, however. The rest of this article is dedicated to remedying that.