Silverlight Templates

.Silverlight Photo List Viewer


Screen Capture of Data Template inside ListBox

.Silverlight Templates

Silverlight supports control and data templates. A control template can be used to completely change the way a control looks, but retain all the controls behaviors. Data Templates can be used to define how raw data is presented to the user."

Silverlight uses default styles and templates for its controls. You can copy these styles and templates into your project and modify them in order to customize control behavior and appearance. The Control Styles and Templates are located on MSDN. You can also find information on Customizing the Appearance of an Existing Control by Using a ControlTemplate and How to: Customize Data Display with Data Templates on the MSDN website.


Data Templates

Data templates are used to define how raw data is presented to the user. Typically a data template is identified with a name (e.g. x:Key). However, Silverlight 5 introduced implicit data templates associated with object types.

  • The most important aspect of using a data template is binding. There is no way to show any data without binding.
  • When creating a data template, usually the DataContext is set on the root element to provide a source for all the bindings.
  • When displaying a collection of items using a control based on ItemsControl (ListBox, ComboBox), the data is rendered using a data template. This is accomplished by setting the ItemTemplate property to the name of the data template.

Below is a Silverlight application that uses a data template to render the ListBox data (MainPage.xaml) and global styles (App.xaml).

Get Microsoft Silverlight


Listbox Photo Viewer using a Data Template (Select a Pet from the List on the Left)


Code for the Listbox Photo Viewer using a Data Template


ListBox Photo Viewer - App.xaml

<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             x:Class="ListBoxBinding2.App"
             >
    <Application.Resources>
        <Style x:Key="BaseWhiteStyle"
               TargetType="TextBlock">
            <Setter Property="Foreground"
                    Value="White" />
        </Style>

        <Style x:Key="TitleStyle"
               TargetType="TextBlock"
               BasedOn="{StaticResource BaseWhiteStyle}">
            <Setter Property="HorizontalAlignment"
                    Value="Center" />
            <Setter Property="FontSize"
                    Value="18" />
            <Setter Property="FontWeight"
                    Value="Bold" />
        </Style>
    </Application.Resources>
</Application>


ListBox Photo Viewer - MainPage.xaml

<UserControl x:Class="ListBoxBinding2.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"
    mc:Ignorable="d"
    d:DesignHeight="400" d:DesignWidth="675">

    <Grid x:Name="LayoutRoot">
        <Grid.RowDefinitions>
            <RowDefinition Height="32" />
            <RowDefinition Height="360" />
        </Grid.RowDefinitions>
        <Grid.Background>
            <ImageBrush ImageSource="Images/board.jpg">               
            </ImageBrush>
        </Grid.Background>
       
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="185" />
            <ColumnDefinition Width="480" />
        </Grid.ColumnDefinitions>
               
        <StackPanel Margin="5,0,0,0"
                    Grid.Row="1">
            <ListBox x:Name="PetsListBox"
                     Height="360"
                     Width="185"
                     Margin="5, 0, 0, 0"
                     SelectionChanged="PetsListBox_SelectionChanged">
               <ListBox.ItemTemplate>
                  <DataTemplate>
                     <StackPanel>
                         <Image Source="{Binding ImagePath}" Height="20" Width="20" Margin="0,6,0,3"/>
                         <TextBlock Text="{Binding Name, StringFormat=Name: \{0\} }" Margin="25,0,0,0" />
                         <TextBlock Text="{Binding Bdate, StringFormat=Birthdate: \{0:00-00-0000\} }" Margin="25,0,0,0" />                        
                     </StackPanel>                           
                  </DataTemplate>
               </ListBox.ItemTemplate>
            </ListBox>
        </StackPanel>

        <Image Margin="5,0,12,0"
               x:Name="fullImage"
               Width="480"
               Height="360"
               Stretch="UniformToFill"
               Grid.Column="1"
               Grid.Row="1" />
        <TextBlock Text="Pets"
                   Style="{StaticResource TitleStyle}"
                   HorizontalAlignment="Center"
                   Grid.Column="1"
                   Margin="6,0,164,0"
                   Grid.RowSpan="2">           
        </TextBlock>
    </Grid>
</UserControl>


ListBox Photo Viewer - MainPage.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using ListBoxBinding2.Classes;
using System.Collections.ObjectModel;
using System.Windows.Media.Imaging;

namespace ListBoxBinding2
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(MainPage_Loaded);
        }

        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            ObservableCollection<PetEntity> pets = new ObservableCollection<PetEntity>();
            pets.Add(new PetEntity() { Name = "Holly", Bdate = 05012001, ImagePath = "Images/holly.png" });
            pets.Add(new PetEntity() { Name = "Shadow", Bdate = 11012000, ImagePath = "Images/shadow.png" });
            pets.Add(new PetEntity() { Name = "Tessa", Bdate = 02012007, ImagePath = "Images/tessa.png" });
            pets.Add(new PetEntity() { Name = "Tucker", Bdate = 11012000, ImagePath = "Images/tucker.png" });
            PetsListBox.ItemsSource = pets;
            PetsListBox.SelectedIndex = 0;
        }

        private void PetsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            PetEntity pickedPet = new PetEntity();
            pickedPet  = (PetEntity)this.PetsListBox.SelectedItem;

            if (pickedPet == null)
                return;

            string imagePath = "L" + pickedPet.ImagePath;

            fullImage.Source = new BitmapImage(new Uri(imagePath, UriKind.Relative));
        }

    }
}


.Listbox using Data Templates


Solution Explorer for Listbox Photo Viewer Project

DataForm Control and Templates

The DataForm control allows you to edit and update data by using a different data template for each operation.

  • The DataForm control is in the Silverlight Toolkit which must be installed on development computer.

  • The steps for creating a DataForm Silverlight Application are:
    1. Create a new Silverlight solution. Add a reference to System.Windows.Controls.Data.DataForm.Toolkit.
    2. In MainPage.xaml add the following namespace import statement for the DataForm control:

      xmlns:df="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit"

    3. Add the DataForm control to MainPage.xaml:

          <Grid x:Name="LayoutRoot" Background="White">

              <df:DataForm x:Name="myDataForm"
                           AutoEdit="False"
                           CommandButtonsVisibility="All"
                           Grid.Row="1"
                           Width="400"
                           Height="300"
                           Margin="20"
                           HorizontalAlignment="Left"
                           VerticalAlignment="Top">
              </df:DataForm>

          </Grid>

    4. Add a new data class (Pet.cs) to the project:

      using System;
      using System.Net;
      using System.Windows;
      using System.Windows.Controls;
      using System.Windows.Documents;
      using System.Windows.Ink;
      using System.Windows.Input;
      using System.Windows.Media;
      using System.Windows.Media.Animation;
      using System.Windows.Shapes;

      namespace DataForm1
      {
          public class Pet
          {
              public int ID { get; set; }
              public string Name { get; set; }
              public string ImagePath { get; set; }
              public DateTime BDate { get; set; }
          }
      }

    5. In MainPage.xaml.cs, create a property of the data class type and a method to create data:

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Net;
      using System.Windows;
      using System.Windows.Controls;
      using System.Windows.Documents;
      using System.Windows.Input;
      using System.Windows.Media;
      using System.Windows.Media.Animation;
      using System.Windows.Shapes;

      namespace DataForm1
      {
          public partial class MainPage : UserControl
          {

              public Pet pet { get; set; }

              public MainPage()
              {
                  InitializeComponent();
              }

              private void InitPet()
              {
                  pet = new Pet()
                  {
                      Id = 1,
                      Name = "Holly",
                      ImagePath = "Images/holly.png",
                      BDate = new DateTime(2001, 5, 1)
                  };                
              }

          }
      }

    6. In MainPage.xaml.cs, add a call to the method to create the data and set the CurrentItem property of the DataForm to the data:

              public MainPage()
              {
                  InitializeComponent();

                  InitPet();

                  PetDataForm.CurrentItem = pet;
              }

    7. Implment the IEditableObject interface on the data class. This exposes three methods: BeginEdit, CancelEdit, and EndEdit which are coded as:

          public class Pet : IEditableObject
          {
              public int Id { get; set; }
              public string Name { get; set; }
              public string ImagePath { get; set; }
              public DateTime BDate { get; set; }


              private Pet tmpPet;

              public void BeginEdit()
              {
                  // save current values
                  tmpPet = new Pet()
                  {
                      Id = this.Id,
                      Name = this.Name,
                      ImagePath = this.ImagePath,
                      BDate = this.BDate
                  };
              }

              public void CancelEdit()
              {
                  // reset values
                  Id = tmpPet.Id;
                  Name = tmpPet.Name;
                  ImagePath = tmpPet.ImagePath;
                  BDate = tmpPet.BDate;
              }

              public void EndEdit()
              {
              }

          }

    8. In MainPage.xaml.cs, define an ObservableCollection and assign it as the DataForm's ItemSource:

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Net;
      using System.Windows;
      using System.Windows.Controls;
      using System.Windows.Documents;
      using System.Windows.Input;
      using System.Windows.Media;
      using System.Windows.Media.Animation;
      using System.Windows.Shapes;
      using System.Collections.ObjectModel;

      namespace DataForm1
      {
          public partial class MainPage : UserControl
          {

              //public Pet pet { get; set; }

              public ObservableCollection<Pet> lstPet { get; set; }

              public MainPage()
              {
                  InitializeComponent();

                  InitPet();

                  //PetDataForm.CurrentItem = pet;
                  PetDataForm.ItemsSource = lstPet;
              }

              private void InitPet()
              {

                  lstPet = new ObservableCollection<Pet>()
                  {new Pet(){
                      Id = 1,
                      Name = "Holly",
                      ImagePath = "Images/holly.png",
                      BDate = new DateTime(2001, 5, 1) },
                   new Pet(){
                      Id = 2,
                      Name = "Shadow",
                      ImagePath = "Images/shadow.png",
                      BDate = new DateTime(2000, 11, 1) },
                   new Pet(){
                      Id = 3,
                      Name = "Tessa",
                      ImagePath = "Images/tessa.png",
                      BDate = new DateTime(2007, 2, 1) },               
                   new Pet(){
                      Id = 4,
                      Name = "Tucker",
                      ImagePath = "Images/tucker.png",
                      BDate = new DateTime(2000, 11, 1) }   
                  };

              }

          }
      }

The DataForm is now able to page through the data and make updates to the data.

.DataForm with Template


DataForm with Template

.DataForm with Edit Capabilities


DataForm with Edit Capabilities

Control Templates

A control template can be used to completely change the way a control looks, but retain all the controls behaviors.

  • Control templates can be created at the element, page, and app levels.

  • The ControlPresenter element is required before the specified content= will be displayed in the control.

  • The ItemPresenter element is required to place the items in controls based on the ItemsControl class.

Below is an example of a Button control that has a template at the element level to change its appearance to a bulls-eye. The modified control still retains its button behaviors (e.g. Click).

.Button Template


Button Control Appearance Modified with a Control Template

Template Binding

Template binding can be used to tell a control to use the property value specified in a parent element. Template binding is part of the data binding family and can only be used within the ControlTemplate element.

Below is an example of a button using template binding to obtain the value of the width and height properties from the parent (Button) element.

.Template Binding for Button Properties


Template Binding of Width and Height Properties to its Parent Control





Reference Articles


Top