Friday, July 17, 2009

DomainUpDown Controls with Silverlight 3

The DomainUpDown control allows the user to spin through a collection of data objects, focusing on one at a time. DomainUpDown is one of the new controls available in the Silverlight 3 Toolkit.

DomainUpDown

To begin this tutorial, set up a new navigation application project as per my last post. This tutorial is informed by Jesse Liberty's video, which I recommend you watch on: silverlight.net

Data Classes

First, we need to create two classes to store the data. We use a Book class to represent each book, storing the Name and Author.

public class Book
{
public string Name { get; set; }
public string Author { get; set; }

public Book(string name, string author)
{
Name = name;
Author = author;
}
}

The BookCollection object contains all of the books used in the tutorial:

public class BookCollection
{
public static ObjectCollection Books
{
get
{
ObjectCollection books = new ObjectCollection();

books.Add(new Book("Possession", "A.S. Byatt"));
books.Add(new Book("Lord of the Rings", "J.R.R Tolkein"));
books.Add(new Book("The Long Dark Tea-Time of the Soul", "Douglas Adams"));
books.Add(new Book("The Sandman", "Neil Gaiman"));

return books;
}
}
}

Add references

Turning to the Silverlight project in the Solution Explorer, add references to the following two DLLs, which can be found in your Silverlight toolkit installation:

System.Windows.Controls.Toolkit
System.Windows.Controls.Input.Toolkit


Add a Namespace

Add the following namespace to the top of your page:

xmlns:in="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Input.Toolkit"

Add the DomainUpDown Control

Add the following code to the Grid in your xaml file:

<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*"/>
<ColumnDefinition Width="0.5*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="0.2*"/>
<RowDefinition Height="0.8*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0" VerticalAlignment="Bottom" Style="{StaticResource ContentPanelStyle}" >
<ContentControl Content="Domain Up Down" VerticalAlignment="Top" HorizontalAlignment="Left"/>
<in:DomainUpDown x:Name="DomainUD" ItemsSource="{Binding}" Height="90" FontSize="32" IsEditable="False">
<in:DomainUpDown.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Name}" FontSize="32" Foreground="#66000000" Height="50"/>
<TextBlock Text="{Binding Author}" FontSize="24" Foreground="#33000000" Height="40" />
</StackPanel>
</DataTemplate>
</in:DomainUpDown.ItemTemplate>
</in:DomainUpDown>
</StackPanel>

Add the DataContext

Add the following line to your code-behind (.cs) page, just after the InitializeComponent() line:

DomainUD.DataContext = BookCollection.Books;

This will tell the binding engine to use our books collection. Once this step is done, we can press F5 and see our DomainUpDown control in action!


Editing the DomainUpDown

You'll notice in the code above that the DomainUpDown has its IsEditable attribute set to "False". If you set it to "True", you will need to add the following code to the Book object:

public override string ToString()
{
return Name + " : " + Author;
}

The reason is that when the user clicks on the content of the DomainUpDown, a call is made to the Book's ToString() method (which by default will return what type of object it is). The code above overrides this default behaviour and returns a nicely formatted string containing the Name and Author fields.

Cycling

Another feature of the DomainUpDown is that you can set its IsCyclic attribute to "True" (it is False by default, restricting the user from browsing to a data object before the first, and after the last in the collection). Setting IsCyclic to "True" allows the user to cycle somewhat more seemlessly through the set of data.

Conclusion

Well that concludes this tutorial. I hope you have enjoyed learning how to create a DomainUpDown control, populate it with data, and how to tweak the control's attributes to change its behaviour.