asp:Feature
LANGUAGES: C#
ASP.NET VERSIONS: 3.5
Columns & Rows: Part II
Silverlight 2.0 DataGrid Columns
By Bilal Haidar
Having a Silverlight DataGrid control displayingits columns in an auto-generated fashion does not satisfy most developers.Rather, it is usually the case that developers require in-depth control overthe DataGrid columns to decide what to show, what to hide, and even tocustomize the appearance of the columns.
The Silverlight DataGrid gives developers theopportunity to manipulate and configure its columns in an easy and flexibleway. Several built-in columns ship with Silverlight out of the box and withinthe DataGrid control to help in the customization process.
You were introduced to the DataGrid s majorproperties in the firstinstallment of this series properties you can use to configure theappearance and behavior of the DataGrid (see the June issue of asp.netPRO). In this article, you ll beintroduced to using the DataGrid with column auto-generation, learning how toadd a DataGrid control to a User Control page with columns beingauto-generated. You ll be introduced to the built-in columns available for youto use out of the box . You ll also learn how to define DataGrid columns inXAML. And, finally, you ll learn how to add at runtime a DataGrid control,together with its columns.
References to Silverlight 2.0
This article assumes you have a fair knowledge ofusing Silverlight 2.0, especially data-binding features, and is not intended toexplain how to use Silverlight 2.0. If you feel you need more information onSilverlight 2.0, it is recommended you check the official website ofSilverlight at www.silverlight.net(it contains dozens of articles and videos). Another major resource to learnSilverlight 2.0 is www.silverlightshow.net.This website focuses on delivering rich and comprehensive tutorials coveringSilverlight. In addition, you can download from www.microsoft.com/Downloads/details.aspx?familyid=BCE7684A-507B-4FC6-BC99-6933CD690CAB&displaylang=enthe Microsoft Silverlight 2 SDK Documentation that covers all the features ofSilverlight.
Simple DataGrid
This article follows a step by step approach topresent the DataGrid control and its defined columns. To start, we ll add asimple DataGrid control and bind it to some data. Figure 1 shows the XAML usedto add a DataGrid control.
The XAML in Figure 1 shows the custom namespacedefined at the User Control header definition. As mentioned in Part I, theDataGrid control is part of the Silverlight 2.0 Software Development Kit (SDK),and must be imported to this User Control. The data namespace alias is usedwhenever you add a DataGrid control to the page, as a way to note to the XAMLcompiler that the DataGrid control is defined within a different namespace thanthat of the current User Control.
<UserControlxmlns:data="clr-namespace:System.Windows.Controls;
assembly=System.Windows.Controls.Data"
<!-- Simple DataGrid-->
<data:DataGridx:Name="dgEmployees"
AutoGenerateColumns="True"
IsReadOnly="True"
HeadersVisibility="Column"
RowBackground="Beige"
AlternatingRowBackground="AliceBlue"
SelectionMode="Single"
GridLinesVisibility="Horizontal"
ColumnWidth="SizeToHeader"
ItemsSource="{Binding}">
</data:DataGrid>
Figure 1: Simple DataGrid control
Defining a DataGrid control instance is as simple asdefining the control with the x:Nameonly. However, the DataGrid in Figure 1 configures a few major properties,like:
IsReadOnly:When set to false, the user can double-click any cell and edit its value;however, having its value set to true makes the entire DataGrid read-only,without allowing any cell editing.
AutoGenerateColumns:This property tells the DataGrid whether to auto-generate the columns based onthe data source being bound to it when this property is set to true, or whetherthe DataGrid control should expect column definitions when the value of thisproperty is set to false.
The rest of the properties were discussed in Part Iof this series. Running the Silverlight application displays the diagram shown inFigure 2.

Figure 2: DataGrid with auto generatedcolumns
The DataGrid control shown in Figure 1 is bound tothe data source in the code-behind as follows:
this.dgEmployees.DataContext =
EmployeeManager.GetEmployeeList();
The EmployeeManager.GetEmployeeList method is asimple method that returns a collection of Employee objects to be displayed inthe DataGrid. To bind the DataGrid control to a data source, use either ofthese properties:
ItemsSource:You set the ItemsSource property to an IEnumerable implementation. Examples areList<T>, ObservableCollection<T>, and other collections. In thecode-behind you bind to the ItemsSource property.
DataContext:You set the ItemsSource property to the Binding extension markup {Binding} value. In the code-behind you simply bind on the DataContext property and notthe ItemsSource property.
Once you bind the DataGrid control to a datasource, each object in the bound collection will be represented by one row, andevery property on the bound object will be represented by a column, as in thecase of AutoGeneratedColumns=true .
DataGrid Built-in Columns
The DataGrid control ships with three built-incolumns that help the developer customize the data displayed by the DataGrid.The built-in columns are:
DataGridTextColumn:The DataGridTextColumn is the default, and simplest column type. By default,when the AutoGeneratedColumns property of the DataGrid is set to true, theDataGrid control uses the DataGridTextColumn to represent all the data boundobject s properties (except those of Boolean values). In the read-only mode,the DataGridTextColumn uses a TextBlock control to represent the underlyingdata source object s property value. While in edit mode, a TextBox control isused to display the data, allowing the use of inline editing. For more detailedinformation, visit msdn.microsoft.com/en-us/library/system.windows.controls.datagridtextcolumn(VS.95).aspx.
DataGridCheckBoxColumn:The DataGridCheckBoxColumn is used by the DataGrid control to represent Booleanvalues, in the underlying data source, as a CheckBox control. This means thatif you have a property in the object that is of type Boolean, that propertywill be displayed inside the DataGrid control as a CheckBox control. For moredetailed information, visit msdn.microsoft.com/en-us/library/system.windows.controls.datagridcheckboxcolumn(VS.95).aspx.
DataGridTemplateColumn:The DataGridTemplateColumn is the most flexible and popular DataGrid column. Insome cases you might feel unsatisfied with the other two built-in columns, andthus feel the need for a flexible way to define new column types. For suchcases, the DataGridTemplateColumn is used. For the read-only state, set theCellTemplate property to any UI with which you want to display the underlyingdata. In the case of editing state, set the CellEditingTemplate property to theUI to show when the DataGrid s row is in edit mode. For more detailedinformation, visit msdn.microsoft.com/en-us/library/system.windows.controls.datagridtemplatecolumn(VS.95).aspx.
Now that you know the different column typesavailable, let s have a look at some of the major properties each column holds.
Common Properties
Some properties are shared among all the columns previouslycited:
CanUserReorder:Allows/Prevents user from reordering the column. The value set at the columnlevel overrides the one set at the DataGrid level.
CanUserResize:Allows/Prevents user from resizing the column. The value set at the columnlevel overrides the one set at the DataGrid level.
CanUserSort:Allows/Prevents user from clicking on the column to sort the data accordingly.The value set at the column level overrides the one set at the DataGrid level.
Header:Allows setting a header text for the column.
IsFrozen:If this is true , the specified column will be frozen and outside the range ofthe horizontal scrollbar.
IsReadOnly:When set to true , the column is always displayed as read-only.Double-clicking the column in this case will not enter the row into the editingmode. When this property is set both at the DataGrid level and column level,the true value always wins.
MaxWidth:This property specifies the maximum width a column can reach.
MinWidth:This property specifies the minimum width a column can reach.
SortMemberPath:By default in the DataGridTextColumn and DataGridCheckBoxColumn, this propertyis set to the bounding property on the column. In the case ofDataGridTemplateColumn, this property must be set to enable sorting on thetemplate column.
Visibility:This property controls the visibility of the column.
Width:This property sets the width of the column. This property is of typeGridLength, which helps in auto-sizing the column. It can be any of thefollowing values:
o SizeToHeader: This value auto-sizes thewidth of the cell to that of the header column cell.
o SizeToCells: This value auto-sizes thewidth of the cell to the largest cell showing in the same column, ignoring theheader column cell width.
o Numeric: This value specifies the exactwidth as a double value.
o Auto: This is a combination of theSizeToHeader and SizeToCells values. With this value, the cell s width wouldauto-size to the header column cell width, or to the largest cell width.
DataGridTextColumn.The DataGridTextColumn has a few properties of its own:
FontFamily:Allows you to set the font family of the cell s content.
FontSize:Allows you to set the font size of the cell s content.
FontStyle:Allows you to set the font style of the cell s content.
FontWeight:Allows you to set the font weight of the cell s content.
Foreground:Allows you to set the foreground color of the cell s content.
DataGridCheckBoxColumn.The DataGridCheckBoxColumn has a single, specific property:
IsThreeState:This property decides whether the underlying CheckBox control allows three ortwo states. In addition to Checked and Unchecked, the CheckBox can have a nullstate, which happens when you bind the CheckBox control to a null value whenits IsThreeState property is enabled.
DataGridTemplateColumn.The DataGridTemplateColumn has two main specific properties:
CellTemplate:You set this property to a DataTemplate to control how to display the data inthis custom cell when the row is in read-only mode.
CellEditingTemplate:You set this property to a DataTemplate to control how to display the data inthis custom cell when the row is in edit mode.
In the coming sections you ll see how to use theabove columns to customize the display of data using the DataGrid control.
DataGrid XAML-defined Columns
In this section of the article, we ll look at howto add a DataGrid control to a User Control and define its columns explicitly. Figure3 shows a DataGrid control definition.
<data:DataGrid Grid x:Name="dgEmployees" >
<data:DataGrid.Columns>
<!-- FirstNamecolumn -->
<data:DataGridTextColumn
Binding="{Binding Path=FirstName}"
CanUserReorder="False" CanUserResize="True"
CanUserSort="True" IsReadOnly="True"
Width="100" Header="First Name">
<data:DataGridTextColumn.ElementStyle>
<StyleTargetType="TextBlock">
<Setter Property="Foreground" Value="Blue"/>
</Style>
</data:DataGridTextColumn.ElementStyle>
</data:DataGridTextColumn>
<!-- LastNamecolumn -->
<data:DataGridTextColumn
Binding="{Binding Path=LastName}"
Width="100" Visibility="Collapsed"
Header="Last Name">
</data:DataGridTextColumn>
<!-- IsMarriedcolumn -->
<data:DataGridCheckBoxColumn
Binding="{BindingPath=IsMarried}" Header="Is Married?"
Visibility="Visible" IsThreeState="True" />
<!-- MemberOfColumn -->
<data:DataGridTemplateColumn Header="Member Of">
<data:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ListBox Width="Auto" Height="Auto"
ItemsSource="{Binding Path=MemberOf, Mode=OneTime}"
BorderThickness="0" Background="Transparent" />
</DataTemplate>
</data:DataGridTemplateColumn.CellTemplate>
</data:DataGridTemplateColumn>
</data:DataGrid.Columns>
</data:DataGrid>
</Grid>
Figure 3: DataGrid with XAML-defined columns
To define DataGrid columns, simply use the Columnsproperty on the DataGrid by using the property element syntax. The Columnsproperty holds a collection of columns.
The first column is defined as a DataGridTextColumnas follows:
<!-- FirstName column -->
<data:DataGridTextColumn
Binding="{BindingPath=FirstName}"
CanUserReorder="False" CanUserResize="True"
CanUserSort="True" IsReadOnly="True"
Width="100"Header="First Name">
<data:DataGridTextColumn.ElementStyle>
<StyleTargetType="TextBlock">
<SetterProperty="Foreground" Value="Blue"/>
</Style>
</data:DataGridTextColumn.ElementStyle>
</data:DataGridTextColumn>
The Binding property is set to the bound object sproperty; in this case, FirstName . Other common properties are set, like theCanUserReorder, CanUserResize, CanUserSort, IsReadOnly, Width, and Header.
The above column makes use of the ElementStyleproperty, which can be used to edit the Style of the cell displayed.
The second column defined also is a DataGridTextColumn,and is similar to the above column; however, its Visibility property is set to Collapsed , which means the column will be hidden.
The third column is defined as aDataGridCheckBoxColumn:
<!-- IsMarried column -->
<data:DataGridCheckBoxColumn Binding="{
BindingPath=IsMarried}" Header="Is Married?"
IsThreeState="True" />
Defining a DataGridCheckBoxColumn is as simple asadding the column definition and configuring a few properties on thecorresponding column (as shown above).
Notice in Figure 2 the MemberOf column. This columncorresponds to a property on the data source object that is of typeList<String>. When the columns are auto-generated, this column is boundautomatically to the ToString method on the List<String> instance. Hence,you see the 'System.Collections.Generic.List'1[[System.String] value in thecell, instead of the real items of the MemberOf collection.
A DataGridTemplateColumn is needed to solve thisproblem, as shown in the MemberOf column here:
<!-- MemberOf Column -->
<data:DataGridTemplateColumnHeader="Member Of">
<data:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ListBoxWidth="Auto" Height="Auto"
ItemsSource="{Binding Path=MemberOf, Mode=OneTime}"
BorderThickness="0" Background="Transparent" />
</DataTemplate>
</data:DataGridTemplateColumn.CellTemplate>
</data:DataGridTemplateColumn>
</data:DataGrid.Columns>
</data:DataGrid>
When you add a DataGridTemplateColumn, theimportant thing to define is the CellTemplate. The CellTemplate is set to aDataTemplate that defines the UI of the cell. In this case, the DataTemplatedefines a ListBox control to list all the entries of the bounding property, theMemberOf collection.
DataGrid Columns at Runtime
Now that you ve seen how to define columns insideXAML, it s time to see how we can accomplish the same thing at runtime orthrough code.
The following code shows how to define the DataGridcontrol and specify its columns using code-behind. Start by creating a newinstance of the DataGrid control:
DataGrid gdEmployees = new DataGrid();
Configure some properties and the data source:
gdEmployees.AutoGenerateColumns = false;
gdEmployees.ItemsSource =
EmployeeManager.GetEmployeeList();
gdEmployees.IsReadOnly = false;
Add the DataGrid instance to the User Control; inthis case, the DataGrid is added as a child control into the User Control sGrid layout panel:
this.LayoutRoot.Children.Add(gdEmployees);
Start adding a few columns and adding some majorproperties to them:
DataGridTextColumn jobTitle =
new DataGridTextColumn();
jobTitle.Header = "Job Title";
jobTitle.Binding = new Binding("JobTitle");
jobTitle.IsReadOnly = true;
Add into the DataGrid s Column collection thecolumn created:
gdEmployees.Columns.Add(jobTitle);
Another column is added of typeDataGridCheckBoxColumn:
DataGridCheckBoxColumn isMarried =
newDataGridCheckBoxColumn();
isMarried.Binding = new Binding("IsMarried");
isMarried.Header = "Is Married?";
isMarried.IsThreeState = true;
gdEmployees.Columns.Add(isMarried);
As you can see, creating a DataGrid at runtime anddefining its columns is as simple as creating it through XAML-defined columns.
There are additional major properties that can bemanipulated on the DataGrid control. The code download accompanying thisarticle explores additional important properties; take some time to explore howthey are implemented. I also suggest you visit bhaidar.net/SilverlightDataGrid/GridColumns.aspxto browse a live sample and play around with all the major DataGrid properties.
In addition, you can download the accompanyingsolution code for this article and open it in Visual Studio 2008. This willhelp you browse all the DataGrid properties that were not tackled in thisarticle, yet are covered in the accompanying code. If Visual Studio gives thefollowing error upon opening the code solution:
The projecttype is not supported by this installation.
all you need to do is reinstall on your machine theVisual Web Developer of the current installation of Visual Studio 2008.
Conclusion
This article provides an overview to the built-inDataGrid columns that ship with Silverlight 2.0. It goes deeper byexperimenting with defining DataGrid columns at the XAML level and at runtimethrough code.
Source code accompanying this article is available for download.
Bilal Haidar (bhaidar@gmail.com) is a Microsoft MVP inASP.NET. He is an MCP, MCTS, MCPD, MCT, and Telerik MVP. He is a lead softwaredeveloper at CCC, a multinational construction company based in Athens, Greece.