Free Trial

Safari Books Online is a digital library providing on-demand subscription access to thousands of learning resources.

  • Create BookmarkCreate Bookmark
  • Create Note or TagCreate Note or Tag
  • PrintPrint
Share this Page URL
Help

4. The Data Grid > Using custom columns in the DataGrid

Using custom columns in the DataGrid

Using custom columns in the DataGrid Applies to Silverlight 3, 4 and 5 By default, the DataGrid will generate columns for us based on the type of objects that we pass to the control. We looked at this in Displaying the data in a customized DataGrid. However, we'll want more control over what is being displayed most of the time. We'll want to make decisions such as which columns should be shown, in what order and so on. In addition to that, we may want to allow the user to select a value from a ComboBox for a particular column or entirely reformat a value. In this recipe, we'll take full control over what will be displayed by the DataGrid by creating a number of columns ourselves. Getting ready To follow along with this recipe, you can continue using the code that was created in the previous recipes of this chapter. You can also use the start solution located in the Chapter04/Datagrid_Custom_Columns_Starter folder in the code bundle that is available on the Packt website. The completed solution for this recipe can be found in the Chapter04/Datagrid_Custom_Columns_Completed folder. How to do it... There are three types of columns from which we can choose—the DataGridTextColumn, the DataGridCheckBoxColumn, and the DataGridTemplateColumn. We can either declare columns from XAML by adding them to the Columns collection of the DataGrid or add them from the code-behind. We'll again work with the Book class. We'll create an ObservableCollection<Book> in the code-behind and bind this to the DataGrid. We'll create a few custom columns in the following list of steps: The AutoGenerateColumns property defaults to True. Therefore, in the declaration of the DataGrid, we set the property to False. The custom-created columns will be added to the Columns collection. This is shown in the following code: <sdk:DataGrid x:Name="BookDataGrid" AutoGenerateColumns="False"> <sdk:DataGrid.Columns> </sdk:DataGrid.Columns> </sdk:DataGrid> In order to display plain textual values such as the Title, the Author, and the Publisher, we can use the DataGridTextColumn as shown in the following code. We need to specify the Binding for each column. Note that we now need to set the Mode property to TwoWay. If we omit this, the value will not be pushed back to the underlying collection. <sdk:DataGridTextColumn x:Name="TitleColumn" Binding="{Binding Title}" Header="Title"> </sdk:DataGridTextColumn> <sdk:DataGridTextColumn x:Name="AuthorColumn" Binding="{Binding Author}" Header="Author"> </sdk:DataGridTextColumn> <sdk:DataGridTextColumn x:Name="PublisherColumn" Binding="{Binding Publisher, Mode=TwoWay}" Header="Publisher"> </sdk:DataGridTextColumn> The AlreadyRead property of our Book class is of the bool type. We can bind such a value to a DataGridCheckBoxColumn as shown in the following code: <sdk:DataGridCheckBoxColumn x:Name="AlreadyReadColumn" Binding="{Binding AlreadyRead, Mode=TwoWay}" Header="Already read"> </sdk:DataGridCheckBoxColumn> The DataGridTemplateColumn is the most powerful column type. Using this type, we can specify the template for the column manually. The following is the code for the ImageName property. We specify a converter, which is used to convert the ImageName property of type string into a BitmapImage. This BitmapImage can then be used for setting the Source property of the Image control. The code for the converter can be found in the code bundle that is available on the Packt website. <sdk:DataGridTemplateColumn x:Name="ImageColumn"> <sdk:DataGridTemplateColumn.CellTemplate> <DataTemplate> <Image Source="{Binding ImageName, Converter={StaticResource localImageConverter}}" Margin="2"> </Image> </DataTemplate> </sdk:DataGridTemplateColumn.CellTemplate> </sdk:DataGridTemplateColumn> A CellTemplate was defined in the previous template. However, we can also define a CellEditingTemplate. The cell will switch to the editing template when the user starts editing inside the cell. For the Language property in edit mode, we want to offer the user a ComboBox containing the available languages. First, we need to make it possible to retrieve the different languages. We can do so by creating a helper class called LanguageHelper, which defines a property. The return value of this property is a list of Language instances. This is shown in the following code: public class LanguageHelper { public List<string> LanguageList { get { List<string> languages = new List<string>(); Type languageType = typeof(Languages); var fields = from c in languageType.GetFields() where c.IsLiteral select c; foreach (var f in fields) { var value = f.GetValue(languageType); languages.Add(value.ToString()); } return languages; } } } We can instantiate this class in MainPage.xaml as shown in the following code: <UserControl.Resources> <local:LanguageHelper x:Key="localLanguageHelper"> </local:LanguageHelper> </UserControl.Resources> We can now use this instance to fill the ComboBox. The following is the code for the Language column. The normal, non-editing template shows a TextBlock and the editing template shows a ComboBox. The ItemsSource property defines the data binding between the ComboBox and the LanguageList property on the instance of the LanguageHelper class: <sdk:DataGridTemplateColumn x:Name="LanguageColumn" Header="Language"> <sdk:DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding Language}" VerticalAlignment="Center"> </TextBlock> </DataTemplate> </sdk:DataGridTemplateColumn.CellTemplate> <sdk:DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <ComboBox VerticalAlignment="Center" SelectedItem="{Binding Language, Converter={StaticResource localEnumConverter}, Mode=TwoWay}" ItemsSource="{Binding LanguageList, Source={StaticResource localLanguageHelper}}" > </ComboBox> </DataTemplate> </sdk:DataGridTemplateColumn.CellEditingTemplate> </sdk:DataGridTemplateColumn> Not all columns are shown here, but they are all similar to the previous samples. The completed sample code contains the remaining ones. All the columns have been added to the DataGrid as shown in the following image: How it works... In most cases, we will not use the auto-generate function of the DataGrid. We can specify the columns ourselves by adding them to the Columns collection. Three types are available, of which the DataGridTemplateColumn is the most powerful. If we need to display plain text, then we can use the DataGridTextColumn. However, we only have limited control over the formatting of the text. For example, we can change the ForeGround, the FontSize, and the FontWeight properties. However, if we want the text to wrap, we need to use the ElementStyle property as shown in the following code: <sdk:DataGridTextColumn x:Name="PublisherColumn" Binding="{Binding Publisher, Mode=TwoWay}" Header="Publisher"> <sdk:DataGridTextColumn.ElementStyle> <Style TargetType="TextBlock"> <Setter Property="TextWrapping" Value="Wrap"> </Setter> </Style> </sdk:DataGridTextColumn.ElementStyle> </sdk:DataGridTextColumn> While displaying a boolean property, we can use a DataGridCheckboxColumn, which will render a checkbox per item. As mentioned before, the real power lies in the DataGridTemplateColumn because we can specify how a column will render its contents. We specify a DataTemplate containing the data binding statements for the CellTemplate property. In this template, we can use whichever control we want (for example, a DateTimePicker, an Image, or a ComboBox). Each column can have a CellTemplate as well as a CellEditingTemplate. When both are specified, the column renders the editing template when the user starts editing its content. In this editing template, we can offer the user a way to make a selection from several options. We have allowed this using a ComboBox. However, we need some way to bind the list of possible options to this ComboBox. To do so, we can create a helper class that exposes a property that returns a List<T>. We can then instantiate this helper class in XAML and perform a data binding with this instance as the source. There's more... Starting with Silverlight 4, more sizing options were added for the columns of a DataGrid. Silverlight 2 and Silverlight 3 offered us two options. Under these options, we either needed to specify a width for a column, or else had to leave this task for Silverlight. In the latter case, Silverlight would basically do an auto-sizing (sizing a column according to its contents). With Silverlight 4, three new options were added, bringing the total to five options to size the columns. No changes were made in this area with the release of Silverlight 5. The following table shows an overview of these size options:


The most interesting option is the star option, which works similarly to the star in a regular Grid. Using this option, we can now, for example, specify a cell to either take all of the remaining space or become twice as wide as another cell. The following image shows how the TitleColumn is set to take all the remaining space, the PurchaseDateColumn and the ImageColumn are set to a size according to their cells, and the AlreadyReadColumn is set to a size according to its header. The following code shows how the cells are sized using these sizing options (only the relevant part of the code is posted here): <sdk:DataGrid> <sdk:DataGrid.Columns> <sdk:DataGridTextColumn x:Name="TitleColumn" Width="*"> </sdk:DataGridTextColumn> <sdk:DataGridTextColumn x:Name="AuthorColumn" Width="100"> </sdk:DataGridTextColumn> <sdk:DataGridTextColumn x:Name="PublisherColumn" Width="150"> </sdk:DataGridTextColumn> <sdk:DataGridTemplateColumn x:Name="LanguageColumn" Width="100"> </sdk:DataGridTemplateColumn> <sdk:DataGridTemplateColumn x:Name="CategoryColumn" Width="100"> </sdk:DataGridTemplateColumn> <sdk:DataGridCheckBoxColumn x:Name="AlreadyReadColumn" Width="SizeToHeader> </sdk:DataGridTemplateColumn> <sdk:DataGridCheckBoxColumn x:Name="PurchaseDateColumn" Width="SizeToCells> </sdk:DataGridTemplateColumn> <sdk:DataGridTemplateColumn x:Name="ImageColumn" Width="SizeToCells"> </sdk:DataGridTemplateColumn> </sdk:DataGrid.Columns> </sdk:DataGrid>

  

You are currently reading a PREVIEW of this book.

                                                                                                                    

Get instant access to over $1 million worth of books and videos.

  

Start a Free Trial


  
  • Safari Books Online
  • Create BookmarkCreate Bookmark
  • Create Note or TagCreate Note or Tag
  • PrintPrint