Search code examples
silverlight-4.0datagridmergecell

Merge Header Row in Silverlight DataGrid


I'm trying to obtain a table with the following format:

Header 1    |  Header 2

Col1 | Col2 | Col3 Col4

while using Silverlight. I have searched, without success.

Any ideas?

[EDIT]

I have found this blog post, but the data and the column header doesn't get align. Merging Silverlight DataGrid Headers


Solution

  • I had some luck with the block entry mentioned at the edited question. Indeed header and data cells aren't aligned. You need to manually adjust the sizes of these to match. In cases, where the data fields are expected to be of a common specified width, this will work fine. For reference, I am copying this solution here:

    <Style x:Key="DataGridBaseHeaderStyle" TargetType="dataprimitives:DataGridColumnHeader">
        <Setter Property="FontWeight" Value="Bold" />
    </Style>
    
    <Style x:Key="TimeSheetTotalsHeaderStyle" TargetType="dataprimitives:DataGridColumnHeader"
           BasedOn="{StaticResource TimeSheetDayHeaderStyle}">
        <Setter Property="Foreground" Value="#FFFF0000"/>
    </Style>
    
    <Style x:Key="TimeSheetDayHeaderStyle" TargetType="dataprimitives:DataGridColumnHeader" 
           BasedOn="{StaticResource DataGridBaseHeaderStyle}">
        <Setter Property="Foreground" Value="#FF000000"/>
        <Setter Property="HorizontalContentAlignment" Value="Left"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="IsTabStop" Value="False"/>
        <Setter Property="SeparatorBrush" Value="#FFC9CACA"/>
        <Setter Property="Padding" Value="8"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate>
                    <Grid x:Name="Root">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition Width="Auto"/>
                        </Grid.ColumnDefinitions>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal"/>
                                <VisualState x:Name="MouseOver">
                                    <Storyboard>
                                        <ColorAnimation Duration="0" 
                                                        Storyboard.TargetName="BackgroundRectangle" 
                                                        Storyboard.TargetProperty="(Fill).Color" To="#FF448DCA"/>
                                        <ColorAnimation Duration="0" 
                                                        Storyboard.TargetName="BackgroundGradient" 
                                                        Storyboard.TargetProperty="(Fill).(GradientStops)[3].Color" To="#7FFFFFFF"/>
                                        <ColorAnimation Duration="0" 
                                                        Storyboard.TargetName="BackgroundGradient" 
                                                        Storyboard.TargetProperty="(Fill).(GradientStops)[2].Color" To="#CCFFFFFF"/>
                                        <ColorAnimation Duration="0" 
                                                        Storyboard.TargetName="BackgroundGradient" 
                                                        Storyboard.TargetProperty="(Fill).(GradientStops)[1].Color" To="#F2FFFFFF"/>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Pressed">
                                    <Storyboard>
                                        <ColorAnimation Duration="0" 
                                                        Storyboard.TargetName="BackgroundRectangle" 
                                                        Storyboard.TargetProperty="(Fill).Color" To="#FF448DCA"/>
                                        <ColorAnimation Duration="0" 
                                                        Storyboard.TargetName="BackgroundGradient" 
                                                        Storyboard.TargetProperty="(Fill).(GradientStops)[0].Color" To="#D8FFFFFF"/>
                                        <ColorAnimation Duration="0" 
                                                        Storyboard.TargetName="BackgroundGradient" 
                                                        Storyboard.TargetProperty="(Fill).(GradientStops)[1].Color" To="#C6FFFFFF"/>
                                        <ColorAnimation Duration="0" 
                                                        Storyboard.TargetName="BackgroundGradient" 
                                                        Storyboard.TargetProperty="(Fill).(GradientStops)[2].Color" To="#8CFFFFFF"/>
                                        <ColorAnimation Duration="0" 
                                                        Storyboard.TargetName="BackgroundGradient" 
                                                        Storyboard.TargetProperty="(Fill).(GradientStops)[3].Color" To="#3FFFFFFF"/>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="SortStates">
                                <VisualState x:Name="Unsorted"/>
                                <VisualState x:Name="SortAscending" />
                                <VisualState x:Name="SortDescending" />
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <Rectangle x:Name="BackgroundRectangle" Fill="#FF1F3B53" Stretch="Fill" Grid.ColumnSpan="2"/>
                        <Rectangle x:Name="BackgroundGradient" Stretch="Fill" Grid.ColumnSpan="2">
                            <Rectangle.Fill>
                                <LinearGradientBrush EndPoint=".7,1" StartPoint=".7,0">
                                    <GradientStop Color="#FCFFFFFF" Offset="0.015"/>
                                    <GradientStop Color="#F7FFFFFF" Offset="0.375"/>
                                    <GradientStop Color="#E5FFFFFF" Offset="0.6"/>
                                    <GradientStop Color="#D1FFFFFF" Offset="1"/>
                                </LinearGradientBrush>
                            </Rectangle.Fill>
                        </Rectangle>
                        <Grid HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="20" />
                                <RowDefinition Height="1" />
                                <RowDefinition Height="20" />
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="50"/>
                                <ColumnDefinition Width="1" /> 
                                <ColumnDefinition Width="50"/>
                            </Grid.ColumnDefinitions>
                            <!-- Row 0 -->
                            <!-- This was edited in order to work in Silvelight 4 -->
                            <ContentPresenter Content="Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}" 
                                              VerticalAlignment="Center" HorizontalAlignment="Center" 
                                              Grid.ColumnSpan="3" />
    
                            <!-- Row 1 -->
                            <Rectangle Fill="#FFC9CACA" VerticalAlignment="Stretch" Height="1" 
                                       Visibility="Visible" Grid.Row="1" Grid.ColumnSpan="3" />
                            <!-- Row 2 -->
                            <ContentPresenter Content="Qty" Grid.Row="2" VerticalAlignment="Center" 
                                              HorizontalAlignment="Center" />
                            <Rectangle Fill="#FFC9CACA" VerticalAlignment="Stretch" Width="1"  
                                       Visibility="Visible" Grid.Row="2" Grid.Column="1" />
                            <ContentPresenter Content="Hours" Grid.Row="2" Grid.Column="2" 
                                              VerticalAlignment="Center" HorizontalAlignment="Center" />
                        </Grid>
                        <Rectangle x:Name="VerticalSeparator" Fill="#FFC9CACA" 
                                   VerticalAlignment="Stretch" Width="1" Visibility="Visible" 
                                   Grid.Row="1" Grid.Column="1"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    

    The original Style was slightly edited in order to work with Silverlight 4 (more details here).

    You also need to define a TextBox style with a fixed width that matches the width of the header:

    <Style x:Key="TimeSheetTextBoxStyle" TargetType="TextBox">
        <Setter Property="Width" Value="50"></Setter>
        <Setter Property="Background" Value="Transparent"></Setter>
        <Setter Property="BorderThickness" Value="0"></Setter>
    </Style>
    

    Use of the styles in the DataGrid:

    <data:DataGridTemplateColumn Header="Tue" HeaderStyle="{StaticResource TimeSheetDayHeaderStyle}">
        <data:DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBox Text="{Binding TuesdayQuantity}" Style="{StaticResource TimeSheetTextBoxStyle}"/>
                    <Rectangle Fill="#FFC9CACA" VerticalAlignment="Stretch" Width="1" />
                    <TextBox Text="{Binding TuesdayHours}" Margin="2,0,0,0" Style="{StaticResource TimeSheetTextBoxStyle}"/>
                </StackPanel>
            </DataTemplate>
        </data:DataGridTemplateColumn.CellTemplate>
    </data:DataGridTemplateColumn>