Silverlight DataGrid Tutorial - Using a DataGridTemplateColumn

Skill

Silverlight DataGrid Tutorial - Using a DataGridTemplateColumn

Posted in:

Whenever you pit designers against developers, it always seems to be the developer that loses. It's very rare that controls like the Silverlight DataGrid are left alone - designers want little tweaks and polish to increase the user experience. This tutorial is going to illustrate how to use one of the most flexible solutions to theming a DataGrid - the DataGridTemplateColumn.

We'll be touching very little on the basics of how to use the Silverlight DataGrid. If you're new to the control, I'd recommend reading our Silverlight DataGrid Basics tutorial.

The first thing we're going to do is build a default DataGrid without any styling. I created a class to hold some information about the SOTC authors and bound a collection of those to my DataGrid.



using System.Collections.Generic;
using System.Windows.Controls;

namespace DataGridStyling
{
  public partial class Page : UserControl
  {
    public Page()
    {
      InitializeComponent();

      // Create some authors.
      List<Author> authors = new List<Author>()
      {
        new Author()
        {
          Name = "Brandon",
          Username = "The Reddest",
          Language = "C#"
        },
        new Author()
        {
          Name = "Charlie",
          Username = "The Fattest",
          Language = "ActionScript"
        },
        new Author()
        {
          Name = "Richard",
          Username = "The Hairiest",
          Language = "PHP"
        },
        new Author()
        {
          Name = "Mike",
          Username = "The Tallest",
          Language = "JavaScript"
        }
      };

      // Set the items source on the DataGrid to the
      // collection of authors.
      _dataGrid.ItemsSource = authors;
    }
  }

  /// <summary>
  /// Class to hold some information about an
  /// SOTC author.
  /// </summary>
  public class Author
  {
    public string Name { get; set; }
    public string Username { get; set; }
    public string Language { get; set; }
  }
}

<UserControl x:Class="DataGridStyling.Page"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:dg="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
   Width="400" Height="300">
  <Grid x:Name="LayoutRoot" Background="White">
    <dg:DataGrid x:Name="_dataGrid"
                AutoGenerateColumns="False">
      <dg:DataGrid.Columns>
        <dg:DataGridTextColumn
         Binding="{Binding Name}"
         Header="Name"
         Width="100" />
        <dg:DataGridTextColumn
         Binding="{Binding Username}"
         Header="Username"
         Width="100" />
        <dg:DataGridTextColumn
         Binding="{Binding Language}"
         Header="Language"
         Width="100" />
      </dg:DataGrid.Columns>
    </dg:DataGrid>
  </Grid>
</UserControl>

All right, now let's starting using the DataGridTemplateColumn. This column type gives us the ability to set the template for normal cells and cells that are in edit mode. Here's the same example as above except that uses this column type on the Name column.



<dg:DataGrid x:Name="_dataGrid"
            AutoGenerateColumns="False">
  <dg:DataGrid.Columns>
    <dg:DataGridTemplateColumn
     Header="Name"
     Width="100">
      <dg:DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
          <TextBlock Text="{Binding Name}"
                  Foreground="Green"
                  FontWeight="Bold"
                  VerticalAlignment="Center"/>
        </DataTemplate>
      </dg:DataGridTemplateColumn.CellTemplate>
      <dg:DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
          <TextBox Text="{Binding Name, Mode=TwoWay}" />
        </DataTemplate>
      </dg:DataGridTemplateColumn.CellEditingTemplate>
    </dg:DataGridTemplateColumn>
    <dg:DataGridTextColumn
     Binding="{Binding Username}"
     Header="Username"
     Width="100" />
    <dg:DataGridTextColumn
     Binding="{Binding Language}"
     Header="Language"
     Width="100" />
  </dg:DataGrid.Columns>
</dg:DataGrid>

So as you can see, we changed the cell to display bold green text when not in edit mode, and a simple TextBox when it is in edit mode. This is accomplished by using the CellTemplate and CellEditingTemplate properties on the DataGridTemplateColumn object. I had to explicitly set the BindingMode to TwoWay so text entered into the TextBox would be committed back to my Author object.

Here's a slightly more interesting example that builds on the previous one. Now, whenever edit mode is entered, a pencil icon will be displayed to the left of the edit field.



<dg:DataGrid x:Name="_dataGrid"
            AutoGenerateColumns="False">
  <dg:DataGrid.Columns>
    <dg:DataGridTemplateColumn
     Header="Name"
     Width="100">
      <dg:DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
          <TextBlock Text="{Binding Name}"
                  Foreground="Green"
                  FontWeight="Bold"
                  VerticalAlignment="Center"/>
        </DataTemplate>
      </dg:DataGridTemplateColumn.CellTemplate>
      <dg:DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
          <Grid>
            <Grid.ColumnDefinitions>
              <ColumnDefinition Width="Auto" />
              <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <Image Source="pencil_icon.png"
                  Grid.Column="0" />
            <TextBox Text="{Binding Name, Mode=TwoWay}"
                    Grid.Column="1" />
          </Grid>
        </DataTemplate>
      </dg:DataGridTemplateColumn.CellEditingTemplate>
    </dg:DataGridTemplateColumn>
    <dg:DataGridTextColumn
     Binding="{Binding Username}"
     Header="Username"
     Width="100" />
    <dg:DataGridTextColumn
     Binding="{Binding Language}"
     Header="Language"
     Width="100" />
  </dg:DataGrid.Columns>
</dg:DataGrid>

All I had to do in order to use the pencil icon was add it to my project like you would any other existing item. By default the Build Action property on the image will be set to Resource, which is what you want. Now, in XAML, you can simply reference the image by name.

There are basically no limits to how you can display information within cells using this column type. The powerful templating system behind Silverlight and WPF makes doing stuff like this trivial whereas before it may not have even been possible to accomplish the same task. On that note, that wraps up this introduction to the DataGridTemplateColumn.

Cain
07/29/2009 - 21:42

Thanks a bunch this was very helpful for me to figure how to get the Data Binding to work

reply

Add Comment

Put code snippets inside language tags:
[language] [/language]

Examples:
[javascript] [/javascript]
[actionscript] [/actionscript]
[csharp] [/csharp]

See here for supported languages.

Javascript must be enabled to submit anonymous comments - or you can login.

Sponsors