Note – these posts are put together after a short time with Silverlight 4 as a way of providing pointers to some of the new features that Silverlight 4 has to offer. I’m posting these from the PDC as Silverlight 4 is announced for the first time so please bear that in mind when working through these posts.
In Silverlight today Selector controls like the ComboBox and ListBox are lacking a couple of crucial properties from the WPF world – the SelectedValue and SelectedValuePath properties.
This is a little painful – you can see examples of people working around it here and I’ve hacked around with that approach myself in the past.
So, it’s great to see these show up in Silverlight 4. As a quick illustration, imagine I’ve got this Person class;
public class Person { public string FirstName { get; set; } public string LastName { get; set; } public int CountryId { get; set; } }
and that CountryId is really a foreign key into a lookup table of countries represented for me here by these classes;
public class Country { public int Id { get; set; } public string CountryName { get; set; } } public class CountryLookup { public CountryLookup() { this.Countries = new List<Country>() { new Country() { Id = 0, CountryName = "England" }, new Country() { Id = 1, CountryName = "Scotland" }, new Country() { Id = 2, CountryName = "Wales" }, new Country() { Id = 3, CountryName = "Northern Ireland" } }; } public List<Country> Countries { get; private set; } }
Now, if I want to display a list of Person objects with something like a ComboBox which displays the country choices “England”/”Scotland”/”Wales”/”Northern Ireland” then I need a ComboBox which;
- Binds to the list of Countries from an instance of my CountryLookup type – easy enough
- Knows that it needs to display the CountryName property for each item in the ComboBox – that means setting the DisplayMemberPath.
- Binds itself to the CountryId property on the underlying Person object that it will be bound to – that means using the SelectedValue.
- Knows that this value corresponds to the Id value on the Country instance – that means using the SelectedValuePath
Putting that together into some UI;
<UserControl x:Class="SilverlightApplication29.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" xmlns:local="clr-namespace:SilverlightApplication29" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <UserControl.Resources> <local:CountryLookup x:Key="countryLookup" /> </UserControl.Resources> <Grid x:Name="LayoutRoot" Background="White"> <ListBox> <ListBox.Items> <local:Person FirstName="Fred" LastName="Smith" CountryId="0" /> <local:Person FirstName="Bob" LastName="Smith" CountryId="1" /> <local:Person FirstName="Eric" LastName="Smith" CountryId="2" /> <local:Person FirstName="Jack" LastName="Smith" CountryId="3" /> </ListBox.Items> <ListBox.ItemTemplate> <DataTemplate> <StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Margin="5" Text="{Binding FirstName}" /> <TextBlock Margin="5" Text="{Binding LastName}" /> </StackPanel> <ComboBox Margin="5" ItemsSource="{Binding Source={StaticResource countryLookup},Path=Countries}" DisplayMemberPath="CountryName" SelectedValuePath="Id" SelectedValue="{Binding CountryId, Mode=TwoWay}"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> </UserControl>
So, hopefully you can see that my ComboBox binds to a CountryLookup which is defined as a resource and then it uses DisplayMemberPath, SelectedValuePath and SelectedValue to achieve what I want;
Cool 🙂