Welcome to the Xceed Community | Help
Community Search  
More Search Options

DON'T PANIC!

Getting Started with Xceed DataGrid for Silverlight: Part 2, Making it Pretty

In my first post in this series, Binding to a Data Source, I explained how to connect Xceed DataGrid for Silverlight to an OData data source. This post will explain how to configure the datagrid to get the most out of it and your data.

As I said in the first post, loading data from a data source is quite easy; however, the initial result is probably not what most people would like since the data is displayed in its "raw" form. For example, if we take the data returned by the Netflix catalog, you would probably want to limit the number of decimals places for double-typed columns and display an actual image rather than its URL. You may also want to limit the number of columns that are displayed to only those that contain the pertinent information. And so on.

So, first things first, let's reduce the number of columns that are displayed to only those that contain the information we want. There are 2 ways that this can be accomplished: the first being to set the Visible property to false for the columns that are not to be displayed, the second is to set the grid's AutoCreateColumns property to false and manually define the desired columns. The first option would be acceptable if only a couple of columns from a large list are to be hidden; however, the second option is preferrable if more columns are to be hidden than displayed. This is the option that we will use in this sample since we only want to display 6 of the columns.

<sldg:DataGridControl x:Name="netflixGrid"
                      
ItemsSource="{Binding Path=NetflixTitles}"
                     
AutoCreateColumns="False">

   <!-- Because the AutoCreateColumns property was set to false, it is necessary to
        define the columns that will be displayed in the grid. If a custom content
        template is to be used, it is defined through a column's
        CellContentTemplate property. -->
   
<sldg:DataGridControl.Columns>
     
<sldg:Column FieldName="BoxArt"
                   
Title=""
                  
Width="100"/>
     
<sldg:Column FieldName="ShortName"
                  
Title="Title"
                  
Width="200"/>
     
<sldg:Column FieldName="Synopsis"
                  
Width="600"/>
     
<sldg:Column FieldName="ReleaseYear"
                  
Title="Released"
                   
Width="75"/>
      
<sldg:Column FieldName="Rating"
                  
Width="75"/>
     
<sldg:Column FieldName="AverageRating"
                  
Title="Average Rating"
                  
Width="100"/>
  
</sldg:DataGridControl.Columns>
</sldg:DataGridControl>

Now that we have limited the number of columns to only those we want, the next step is to decide how the content in those columns is displayed. In the columns that we decided to keep, there are 3 that could use a facelift. These are the BoxArt column, in which we could display an image rather than a URL; the Synopsis column, in which we could format the text to support the various HTML tags such has bold, italic, and hyperlinks (i.e., href); and the AverageRating column, in which we could display a "star-rating" rather than simply displaying a numeric value.

Up first, the BoxArt column. But before we start, let's make a grocery list of what we will need.

In order to change how the content of each cell in a column is displayed, you need to provide a DataTemplate to the column's CellContentTemplate property. Easy enough. So what will we need to change a URL into an actual image? For starters, we will need to create a new DataTemplate that uses an Image and whose Source property is bound to the LargeUrl field, which provides the URL. In some cases a title will not have a URL. When this happens, we want to display an image that indicates that no image is available for the title. In order to do this, we will create an IValueConverter that will return the "no image" image when one is not provided for the title, and use this converter in the binding that is applied to the Source property.

<!-- The BoxArtImageSourceConverter is an IValueConverter that is used to
     display a custom image when one is not provided by the Netflix data. -->
<local:BoxArtImageSourceConverter x:Key="boxArtImageSourceConverter" />

<!-- The DataTemplate that will be used to display the box art. -->
<DataTemplate x:Key="boxArtCellContentTemplate">
  
<Image Source="{Binding Path=LargeUrl, Converter={StaticResource boxArtImageSourceConverter}}"
         
Height="100"
         
VerticalAlignment="Center"
         
HorizontalAlignment="Center"/>
</DataTemplate>

The next DataTemplate we will create is one that will be used by the AverageRating column to display a star-rating rather than a value. Like the BoxArt column, we will need to create an IValueConverter that will take the value and return a star-rating instead. To keep things clean, the various data templates that can be returned by the RatingConverter are defined in the ImageResourceDictionary.xaml resource dictionary.

<!-- The RatingConverter is an IValueConverter that is used to convert a value 
     into an image. In this case, it will display a numeric value as a star-rating system.

     The DataTemplates that are used are retrieved from the ImageResourceDictionary.xaml
     resource dictionary, which is included as a merged dictionary in the resources
     of the UserControl. -->
<local:RatingConverter x:Key="ratingConverter"
                      
FullTemplate="{StaticResource fullStarDataTemplate}"
                      
HalfTemplate="{StaticResource halfStarDataTemplate}"
                       
EmptyTemplate="{StaticResource noStarDataTemplate}"/>

<!-- The DataTemplate that will be used to display the star ratings. -->
<DataTemplate x:Key="ratingCellContentTemplate">
  
<ItemsControl ItemsSource="{Binding Converter={StaticResource ratingConverter}}"
                
VerticalAlignment="Center"
                
HorizontalAlignment="Center"
                
ToolTipService.ToolTip="{Binding StringFormat=\{0:f1\}}">
     
<ItemsControl.ItemsPanel>
        
<ItemsPanelTemplate>
           
<StackPanel Orientation="Horizontal" />
        
</ItemsPanelTemplate>
     
</ItemsControl.ItemsPanel>
   </ItemsControl>
</DataTemplate>

The last DataTemplate will be used by the Synopsis column to properly format the text that it displays according to the various HTML tags found throughout the text. This template required a little more work since some things that were required (*cough* FlowDocument *cough*) are missing from the Silverlight framework and needed to be created. Like the other 2 columns, an IValueConverter was also needed, except this one converts plain text to a Paragraph that contains the appropriate text and inlines (e.g., Hyperlink).

<!-- The TextToParaConverter is an IValueConverter that is used to create
     a paragraph from plain text. It will also replace tags such as bold, italic,
     and href into the appropriate inline type (e.g., HyperLink)-->
<local:TextToParaConverter x:Key="textToParaConverter"/>

<!-- The DataTemplate that will be used to display the synopsis. The background
     has been set to Transparent to allow the default row highlighting to be apparent. -->
<DataTemplate x:Key="textWrappingContentTemplate">
  
<local:BindableRichTextBox BindableBlocks="{Binding Converter={StaticResource textToParaConverter}}"
                             
BorderThickness="0"
                             
Background="Transparent"/>
</DataTemplate>

Now that we have all these nifty data templates, simply assign them to CellContentTemplate property of the appropriate columns, and voilĂ ! All data is now displayed in a more user-friendly and appropriate manner. Sprinkle a little sorting and grouping, and you are ready to go!

<sldg:Column FieldName="BoxArt"
             
Title=""
             
Width="100"
            
CellContentTemplate="{StaticResource boxArtCellContentTemplate}"/>

<sldg:Column FieldName="Synopsis"
            
Width="600"
             
CellContentTemplate="{StaticResource textWrappingContentTemplate}"/>

<sldg:Column FieldName="AverageRating"
            
Title="Average Rating"
            
Width="100"
             
CellContentTemplate="{StaticResource ratingCellContentTemplate}"/>

 

If you would like to download the sample to play around with it and have access to the custom classes that were created for it, you can do so HERE!

Published August 26, 2010 2:34 PM by Jenny [Xceed]

Comments

 

Gautam said:

How can i sum of the column and show in a footer

June 2, 2011 3:29 AM
 

NALLASIVAM said:

how can we bind null date and text odata columns

November 14, 2011 11:22 PM
Anonymous comments are disabled
Contact | Site Map | Reviews | Legal Terms of Use | Trademarks | Privacy Statement Copyright 2011 Xceed Software Inc.