Published articles on other web sites*

Published articles on other web sites*

Silverlight 5 Beta Rough Notes–Implicit Data Templates


Note: these are early notes based on some initial experiments with the Silverlight 5 beta, apply a pinch of salt to what you read.
One of the powerful new features around templating in the Silverlight 5 beta is the ability to produce a DataTemplate that will be implicitly associated with a particular data type.
For example, if I have these 2 simple types Person and Vehicle;

  1. public class Person  
  2. {  
  3.   public string FirstName { getset; }  
  4.   public string LastName { getset; }  
  5.   public int Age { getset; }  
  6. }  
  7. public class Vehicle  
  8. {  
  9.   public string Type { getset; }  
  10.   public int Wheels { getset; }  
  11. }  
then I can define implicit templates for them by writing templates such as
these;

  1. <UserControl.Resources>  
  2.     <DataTemplate  
  3.       DataType="local:Person">  
  4.       <StackPanel>  
  5.         <TextBlock  
  6.           Text="{Binding FirstName}" />  
  7.         <TextBlock  
  8.           Text="{Binding LastName}" />  
  9.         <TextBlock  
  10.           Text="{Binding Age}" />  
  11.       </StackPanel>  
  12.     </DataTemplate>  
  13.     <DataTemplate  
  14.       DataType="local:Vehicle">  
  15.       <StackPanel>  
  16.         <TextBlock  
  17.           Text="{Binding Type}" />  
  18.         <TextBlock  
  19.           Text="{Binding Wheels}" />  
  20.       </StackPanel>  
  21.     </DataTemplate>  
  22.   </UserControl.Resources>  
where I have not specified a Key for these resources but have, instead, specified a DataType and that’s enough for Silverlight to figure it out.
If I have a scenario like this one where I have a ListBox bound to a set of Items;
  1. <Grid>  
  2.   <Grid.RowDefinitions>  
  3.     <RowDefinition />  
  4.     <RowDefinition  
  5.       Height="Auto" />  
  6.     <RowDefinition  
  7.       Height="Auto" />  
  8.   </Grid.RowDefinitions>  
  9.   <ListBox  
  10.     ItemsSource="{Binding Items}">  
  11.   </ListBox>  
  12.   <Button  
  13.     Command="{Binding AddPerson}"  
  14.     Content="Add Person"  
  15.     Grid.Row="1" />  
  16.   <Button  
  17.     Command="{Binding AddVehicle}"  
  18.     Content="Add Vehicle"  
  19.     Grid.Row="2" />  
  20. </Grid>  
with a DataContext providing a view model like this one;
  1. public class ViewModel  
  2. {  
  3.   public ViewModel()  
  4.   {  
  5.     this.Items = new ObservableCollection<object>();  
  6.     this.AddPerson = new SimpleCommand(() =>  
  7.       {  
  8.         this.Items.Add(  
  9.           new Person()  
  10.           {  
  11.             FirstName = "TestFirst",  
  12.             LastName = "TestLast",  
  13.             Age = 22  
  14.           });  
  15.       });  
  16.     this.AddVehicle = new SimpleCommand(() =>  
  17.       {  
  18.         this.Items.Add(  
  19.           new Vehicle()  
  20.           {  
  21.             Type = "Car",  
  22.             Wheels = 4  
  23.           });  
  24.       });  
  25.   }  
  26.   public ObservableCollection<object> Items { getset; }  
  27.   public ICommand AddPerson { getset; }  
  28.   public ICommand AddVehicle { getset; }  
  29. }  
then whenever I add a Person to the ListBox the runtime will find the right implicit template to display the Person and if I add a Vehicle to the ListBox then the runtime will do the right thing there too;
image
and, if for example I was to make my ViewModel implement property change notification and then bind up a new property called SelectedItem to my ListBox then I can bring in a ContentPresenter and it will also make use of the implicit template as in;

  1. <UserControl.Resources>  
  2.   <DataTemplate  
  3.     DataType="local:Person">  
  4.     <StackPanel>  
  5.       <TextBlock  
  6.         Text="{Binding FirstName}" />  
  7.       <TextBlock  
  8.         Text="{Binding LastName}" />  
  9.       <TextBlock  
  10.         Text="{Binding Age}" />  
  11.     </StackPanel>  
  12.   </DataTemplate>  
  13.   <DataTemplate  
  14.     DataType="local:Vehicle">  
  15.     <StackPanel>  
  16.       <TextBlock  
  17.         Text="{Binding Type}" />  
  18.       <TextBlock  
  19.         Text="{Binding Wheels}" />  
  20.     </StackPanel>  
  21.   </DataTemplate>  
  22. </UserControl.Resources>  
  23. <UserControl.DataContext>  
  24.   <local:ViewModel />  
  25. </UserControl.DataContext>  
  26. <Grid>  
  27.   <Grid.ColumnDefinitions>  
  28.     <ColumnDefinition />  
  29.     <ColumnDefinition />  
  30.   </Grid.ColumnDefinitions>  
  31.   <Grid.RowDefinitions>  
  32.     <RowDefinition />  
  33.     <RowDefinition  
  34.       Height="Auto" />  
  35.     <RowDefinition  
  36.       Height="Auto" />  
  37.   </Grid.RowDefinitions>  
  38.   <ListBox  
  39.     ItemsSource="{Binding Items}"  
  40.     SelectedValue="{Binding SelectedItem,Mode=TwoWay}" />  
  41.   <Button  
  42.     Command="{Binding AddPerson}"  
  43.     Content="Add Person"  
  44.     Grid.Row="1" />  
  45.   <Button  
  46.     Command="{Binding AddVehicle}"  
  47.     Content="Add Vehicle"  
  48.     Grid.Row="2" />  
  49.   <ContentPresenter  
  50.     Grid.Column="1"  
  51.     Content="{Binding SelectedItem}" />  
  52. </Grid>  
and so then both the ListBox on the left and the ContentPresenter on the right are using implicit templates to display content;
image
(as an aside, I also tried this with a ContentPresenter inside a Tooltip and it didn’t work for me so far in the beta).
Naturally, you can override these implicit templates so if I want a different template for my ContentPresenter I can simply add an implicit template that is nearer to the ContentPresenter in the hierarchy of resource resolution as in;
  1. <UserControl.Resources>  
  2.   <DataTemplate  
  3.     DataType="local:Person">  
  4.     <StackPanel>  
  5.       <TextBlock  
  6.         Text="{Binding FirstName}" />  
  7.       <TextBlock  
  8.         Text="{Binding LastName}" />  
  9.       <TextBlock  
  10.         Text="{Binding Age}" />  
  11.     </StackPanel>  
  12.   </DataTemplate>  
  13.   <DataTemplate  
  14.     DataType="local:Vehicle">  
  15.     <StackPanel>  
  16.       <TextBlock  
  17.         Text="{Binding Type}" />  
  18.       <TextBlock  
  19.         Text="{Binding Wheels}" />  
  20.     </StackPanel>  
  21.   </DataTemplate>  
  22. </UserControl.Resources>  
  23. <UserControl.DataContext>  
  24.   <local:ViewModel />  
  25. </UserControl.DataContext>  
  26. <Grid>  
  27.   <Grid.ColumnDefinitions>  
  28.     <ColumnDefinition />  
  29.     <ColumnDefinition />  
  30.   </Grid.ColumnDefinitions>  
  31.   <Grid.RowDefinitions>  
  32.     <RowDefinition />  
  33.     <RowDefinition  
  34.       Height="Auto" />  
  35.     <RowDefinition  
  36.       Height="Auto" />  
  37.   </Grid.RowDefinitions>  
  38.   <ListBox  
  39.     ItemsSource="{Binding Items}"  
  40.     SelectedValue="{Binding SelectedItem,Mode=TwoWay}" />  
  41.   <Button  
  42.     Command="{Binding AddPerson}"  
  43.     Content="Add Person"  
  44.     Grid.Row="1" />  
  45.   <Button  
  46.     Command="{Binding AddVehicle}"  
  47.     Content="Add Vehicle"  
  48.     Grid.Row="2" />  
  49.   <Grid  
  50.     Grid.Column="1">  
  51.     <Grid.Resources>  
  52.       <DataTemplate  
  53.         DataType="local:Vehicle">  
  54.         <StackPanel  
  55.           Orientation="Horizontal">  
  56.           <TextBlock  
  57.             Text="{Binding Type}" />  
  58.           <TextBlock  
  59.             Text="{Binding Wheels}" />  
  60.         </StackPanel>  
  61.       </DataTemplate>  
  62.     </Grid.Resources>  
  63.     <ContentPresenter  
  64.         Grid.Column="1"  
  65.         Content="{Binding SelectedItem}"/>  
  66.   </Grid>  
  67. </Grid>  
and, naturally, you can also mix/match this implicit approach with the explicit approach that you’d use in Silverlight 4 today.
I think this is a pretty powerful addition to the Silverlight 5 binding/templating abilities and it’ll be interesting to see what other folks and frameworks do with it.
As a final note, I’m not sure at the time of writing whether there’s anything in Visual Studio 2010 Sp1 or in the Blend Preview for Silverlight 5 that deals with implicit templates – I’ve not seen anything just yet.

No comments:

Post a Comment

Related Posts Plugin for WordPress, Blogger...