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.
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.
[silverlight width="400" height="300" src="BasicDataGrid.xap"]
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.
[silverlight width="400" height="300" src="TemplateColumn.xap"]
<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.
[silverlight width="400" height="300" src="Pencil.xap"]
<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.
Comments
Post a Comment