(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

Changing the style of the selected row of the DataGrid control

(5 votes)
Martin Mihaylov
>
Martin Mihaylov
Joined Oct 29, 2007
Articles:   50
Comments:   70
More Articles
16 comments   /   posted on Nov 17, 2008
Categories:   Controls , Design

This article is compatible with the latest version of Silverlight.

In the article about the basic customizations of the DataGrid control we showed how to change the color of the rows and of the alternating rows, how to modify the headers' and the gridlines' visibility. But we haven't mentioned anything about how to change the look of the row when the mouse is over it or when it's selected. Let's take a look how we can achieve that.

Before starting

I won't start directly with the explanation of each thing and step we have to do. Instead I’ll start with a few common things. First there is no specific property for the color of the selected row, as RowBackground and AlternatingRowBackground and the only property that comes in hand is the RowStyle. The Target property of the style must be set to DataGridRow and the thing we have to customize is the Template property. I've tried to do this using the Expression Blend, but I didn’t find a way to get to this Template, so I had to disassemble the System.Windows.Controls.Data.dll and get the template from there. After that I modified what I needed in the VisualStudio.

Getting the Template of the DataGridRow

The DataGrid control and its components are located in the System.Windows.Controls.Data.dll which usually can be found here - C:\Program Files\Microsoft SDKs\Silverlight\v2.0\Libraries\Client. To disassemble it we use the .Net Reflector (more about it here).

We add the desired assembly and expand it. The generic.xaml for the DataGrid can be found in the System.Windows.Controls.Data.g.resources file. We save it and open it in VisualStudio, where we can copy the default DataGridRow style and customize it in our project. The style we need is with TargetType set to local:DataGridRow. Before just copying the style, note the namespaces that are declared in the ResourceDictionary:

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
    xmlns:primitives="clr-namespace:System.Windows.Controls.Primitives;assembly=System.Windows"
    xmlns:localprimitives="clr-namespace:System.Windows.Controls.Primitives;assembly=System.Windows.Controls.Data"
    xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows">
    ...
</ResourceDictionary>

The "local" is the namespace where the DataGrid control is located and the "localprimitives" is the one in which some components of the DataGridRow template can be found. To modify the template of the row we have to add these namespaces to our UserControl or App.xaml (depends on where you define your style), so copy and paste them where needed. After that, copy and paste the style for the DataGridRow.

Taking a closer look at the template

Here is the whole style for those who can't obtain it through the Reflector:

<Style x:Key="MyCustomRow" TargetType="local:DataGridRow">
    <Setter Property="IsTabStop" Value="False" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:DataGridRow">
                <localprimitives:DataGridFrozenGrid Name="Root">
                    <vsm:VisualStateManager.VisualStateGroups>
                        <vsm:VisualStateGroup x:Name="CommonStates">
                            <vsm:VisualStateGroup.Transitions>
                                <vsm:VisualTransition GeneratedDuration="0" />
                            </vsm:VisualStateGroup.Transitions>
                            <vsm:VisualState x:Name="Normal" />
                            <vsm:VisualState x:Name="Normal AlternatingRow">
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="Opacity" Duration="0" To="0"/>
                                </Storyboard>
                            </vsm:VisualState>
                            <vsm:VisualState x:Name="MouseOver">
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="Opacity" Duration="0" To=".5"/>
                                </Storyboard>
                            </vsm:VisualState>
                            <vsm:VisualState x:Name="Normal Selected">
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="Opacity" Duration="0" To="1"/>
                                </Storyboard>
                            </vsm:VisualState>
                            <vsm:VisualState x:Name="MouseOver Selected">
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="Opacity" Duration="0" To="1"/>
                                </Storyboard>
                            </vsm:VisualState>
                            <vsm:VisualState x:Name="Unfocused Selected">
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="Opacity" Duration="0" To="1"/>
                                    <ColorAnimationUsingKeyFrames BeginTime="0" Duration="0" Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
                                        <SplineColorKeyFrame KeyTime="0" Value="#FFE1E7EC"/>
                                    </ColorAnimationUsingKeyFrames>
                                </Storyboard>
                            </vsm:VisualState>
                        </vsm:VisualStateGroup>
                    </vsm:VisualStateManager.VisualStateGroups>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="*"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
 
                    <Grid.Resources>
                        <Storyboard x:Key="DetailsVisibleTransition">
                            <DoubleAnimation Storyboard.TargetName="DetailsPresenter" Storyboard.TargetProperty="ContentHeight" Duration="00:00:0.1" />
                        </Storyboard>
                    </Grid.Resources>
 
                    <Rectangle x:Name="BackgroundRectangle" Grid.RowSpan="2" Grid.ColumnSpan="2" Opacity="0" Fill="#FFFFCC00"/>
 
                    <localprimitives:DataGridRowHeader Grid.RowSpan="3" Name="RowHeader" localprimitives:DataGridFrozenGrid.IsFrozen="True" />
                    <localprimitives:DataGridCellsPresenter Grid.Column="1" Name="CellsPresenter" localprimitives:DataGridFrozenGrid.IsFrozen="True" />
                    <localprimitives:DataGridDetailsPresenter Grid.Row="1" Grid.Column="1" Name="DetailsPresenter" />
                    <Rectangle Grid.Row="2" Grid.Column="1" Name="BottomGridLine" HorizontalAlignment="Stretch" Height="1" />
                </localprimitives:DataGridFrozenGrid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

The things, we'll focus on, are the Rectangle control called BackgroundRectangle and the ViewStates. To change the color of the selection, use the Fill property of this rectangle.

In fact that's all, but I want to add something else – a more advanced customization of the selection.

Take a look at the ViewStates - they use animations to change the opacity of the BackgroundRectangle depending on the state and there are also different states for the rows and the alternating rows. In this line of thoughts you can easily add animations to the storyboards of the states that change the color of the BackgroundRectangle, in order to set its fill to a different color when the row is selected or when the mouse is over it. Here is a simple example for the ViewStates: 

<vsm:VisualStateManager.VisualStateGroups>
    <vsm:VisualStateGroup x:Name="CommonStates">
        <vsm:VisualStateGroup.Transitions>
            <vsm:VisualTransition GeneratedDuration="0" />
        </vsm:VisualStateGroup.Transitions>
        <vsm:VisualState x:Name="Normal" />
        <vsm:VisualState x:Name="Normal AlternatingRow">
            <Storyboard>
                <DoubleAnimation Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="Opacity" Duration="0" To="0"/>
            </Storyboard>
        </vsm:VisualState>
        <vsm:VisualState x:Name="MouseOver">
            <Storyboard>
                <DoubleAnimation Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="Opacity" Duration="0" To=".5"/>
                <ColorAnimationUsingKeyFrames BeginTime="0" Duration="0" Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
                    <SplineColorKeyFrame KeyTime="0" Value="#d3eaf9"/>
                </ColorAnimationUsingKeyFrames>
            </Storyboard>
        </vsm:VisualState>
        <vsm:VisualState x:Name="Normal Selected">
            <Storyboard>
                <DoubleAnimation Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="Opacity" Duration="0" To="1"/>
                <ColorAnimationUsingKeyFrames BeginTime="0" Duration="0" Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
                    <SplineColorKeyFrame KeyTime="0" Value="#1ca0f2"/>
                </ColorAnimationUsingKeyFrames>
            </Storyboard>
        </vsm:VisualState>
        <vsm:VisualState x:Name="MouseOver Selected">
            <Storyboard>
                <DoubleAnimation Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="Opacity" Duration="0" To="1"/>
                <ColorAnimationUsingKeyFrames BeginTime="0" Duration="0" Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
                    <SplineColorKeyFrame KeyTime="0" Value="#ffcc00"/>
                </ColorAnimationUsingKeyFrames>
            </Storyboard>
        </vsm:VisualState>
        <vsm:VisualState x:Name="Unfocused Selected">
            <Storyboard>
                <DoubleAnimation Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="Opacity" Duration="0" To="1"/>
                <ColorAnimationUsingKeyFrames BeginTime="0" Duration="0" Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
                    <SplineColorKeyFrame KeyTime="0" Value="LightGray"/>
                </ColorAnimationUsingKeyFrames>
            </Storyboard>
        </vsm:VisualState>
    </vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>

I have set different colors for the MouseOver, MouseOver Selected, Normal Selected, Unfocus Selected states. Take a look at this live sample:

And here is the source code to the sample.

Conclusion

Now you know how to change the style of the row when it is selected and when the mouse is over it. The template and the VisualStates give us a lot of possibilities to experiment, so go on and try it out. You can even add something more creative to this template and configure the VisualStates to manipulate it.

Probably now you want to change the style of the row and the column headers too. For that purpose use the RowHeaderStyle and the ColumnHeaderStyle properties. The default styles for the RowHeader and the ColumnHeader can also be found in the generic.xaml. If you want to change the look of the cell when it is selected or mouseovered you can set the CellStyle property of the DataGrid to a valid style and the default style can be also found in the generic.xaml. Good luck!


Subscribe

Comments

  • -_-

    RE: Changing the style of the selected row of the DataGrid control


    posted by Vikram on Feb 04, 2009 10:44

    great help...thanx lot

     

  • -_-

    RE: Changing the style of the selected row of the DataGrid control


    posted by Jorley on Feb 12, 2009 09:18

    nice work

  • -_-

    RE: Changing the style of the selected row of the DataGrid control


    posted by GEB on May 28, 2009 15:34
    In your live example, the first row is initially selected (index = 0) , but it does not show the orange highlighted color when first displayed.  This does not seem to be the desired behavior.  Since this row is selected, shouldnyt it initially show in orange as well?
  • -_-

    RE: Changing the style of the selected row of the DataGrid control


    posted by gopinath vara on Aug 10, 2009 22:13

    Hi,

    Is it possible to switch the row color based on a (first column) checkbox? like if the checkbox selected, rowColor = blue

    and unselected then rowColor = Yellow....

    Thanks,

    Gopi

  • -_-

    RE: Changing the style of the selected row of the DataGrid control


    posted by gopinath vara on Aug 10, 2009 23:09

    Hi,

    Is it possible to switch the row color based on a (first column) checkbox? like if the checkbox selected, rowColor = blue

    and unselected then rowColor = Yellow....

    Thanks,

    Gopi

  • -_-

    RE: Changing the style of the selected row of the DataGrid control


    posted by Apogen on Sep 11, 2009 06:48
    Exelente aporte.. Gracias
  • -_-

    RE: Changing the style of the selected row of the DataGrid control


    posted by W. Leader on Sep 24, 2009 00:39
    I'm really kind of surprised that changing the visual style of such a useful control is such a difficult task. At least once the appropriate template was copied into my app.xml, I was able to edit things using Expression Blend. Hopefully this sort of thing will get sorted out in a later version of the tools.
  • -_-

    RE: Changing the style of the selected row of the DataGrid control


    posted by Alejandro on Oct 16, 2009 07:27

    In the case you want to change any font properties like foreground, you need to wrap the DataGridCellsPresenter into a content control, because the DataGridCellsPresenter doesnt have any of these properties it inherits them from the parent. Here is an example: http://alejandrobog.wordpress.com/2009/07/02/silverlight-datagrid-change-foreground-color-on-visualstatemanagermouseover-selected

     

  • -_-

    RE: Changing the style of the selected row of the DataGrid control


    posted by loryas on Nov 30, 2009 18:03
    thanks, helped me a lot.
  • -_-

    RE: Changing the style of the selected row of the DataGrid control


    posted by Richard on Dec 02, 2009 05:33
    Great! It's working in my project.
    I really appreciate you. Thanks.
  • -_-

    RE: Changing the style of the selected row of the DataGrid control


    posted by Michel on Mar 18, 2010 19:16

    Excellent article.
    It solve my problem.

    Many thanks!

  • -_-

    RE: Changing the style of the selected row of the DataGrid control


    posted by Jatin on Jul 20, 2010 11:12

    Great help

    Thanks

  • lnikolov

    RE: Changing the style of the selected row of the DataGrid control


    posted by lnikolov on Jan 21, 2011 10:57
    The article has been updated to the latest version of Silverlight and Visual Studio.
  • dong

    Re: Changing the style of the selected row of the DataGrid control


    posted by dong on Apr 09, 2012 06:33

    Thank you very much.

  • santoshf2

    Re: Changing the style of the selected row of the DataGrid control


    posted by santoshf2 on Apr 10, 2012 14:54

    great help thnx a bunch :)

  • holyballs

    Re: Changing the style of the selected row of the DataGrid control


    posted by holyballs on Aug 31, 2012 07:50

    Great .. Thank You very Much..!!

Add Comment

Login to comment:
  *      *