views:

4988

answers:

7

NB this was for the silverlight 3 beta, RTM seems to handle grouping entirely differently.

I've a grid that is working fine, which I'm using the GroupDescriptions property like so:

<data:DataGrid.GroupDescriptions>
    <cm:PropertyGroupDescription PropertyName="ClientName" />
</data:DataGrid.GroupDescriptions>

This works brilliantly, it's only when the datagrid is rendered, it shows the grouping by "ClientName". Obviously I'd like that to be "Client Name". I cannot for the life of me see a property that would allow me to set this?

+7  A: 

FWIW this has changed in SL3 RTM:

Silverlight 3 Beta

[Xaml]

<dataGrid.GroupDescriptions>

      <windata:PropertyGroupDescription PropertyName=”State” />

</dataGrid.GroupDescriptions>

Silverlight 3 RTM

[c#]

pagedCollectionView.GroupDescriptions.Add(new PropertyGroupDescription(“State”));

You need to use the PagedCollectionView class to accomplish this, it can't be done in Xaml anymore. See http://msdn.microsoft.com/en-us/library/dd833072(VS.95).aspx

And from that link, here's how to change the text in the group header:

When items are grouped in the DataGrid, each group has a header. You can change the appearance of the DataGridRowGroupHeader by defining a custom Style and adding it to the RowGroupHeaderStyles collection. If you have multiple levels of grouping, you can apply different styles to each group level. Styles are applied in the order in which they are defined. For example, if you define two styles, the first will be applied to top level row groups. The second style will be applied to all row groups at the second level and lower. The DataContext of the DataGridRowGroupHeader is the CollectionViewGroup that the header represents.

So a quick and dirty example would be:

<dataControls:DataGrid x:Name="Grid">
    <dataControls:DataGrid.RowGroupHeaderStyles>
        <Style TargetType="dataControls:DataGridRowGroupHeader">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <TextBlock Text="My text."/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
   </dataControls:DataGrid.RowGroupHeaderStyles>
</dataControls:DataGrid>

In practice you probably want to include the other control parts that are specified for DataGridRowGroupHeader so that you can expand and collapse them. As with everything WPF, instead of just setting a "GroupText" property you have to go whole 9 yards!

James Cadd
what is the paged collection view? I tried using the CollectionViewSource and the GroupDescriptions property is not implemented.
DaRKoN_
Sorry for the incomplete answer - updated the post.
James Cadd
A: 

Having the same problem as DaRKoN_ and having read James Cadd insightful answer I solved my own problem. By using Blend I have extracted the template for the DataGridRowGroupHeader. You can use the code below to customize it:

<data:DataGrid>
  <data:DataGrid.RowGroupHeaderStyles>
    <Style TargetType="data:DataGridRowGroupHeader">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="data:DataGridRowGroupHeader">
            <dataPrimitives:DataGridFrozenGrid x:Name="Root" Background="{TemplateBinding Background}">
              <dataPrimitives:DataGridFrozenGrid.Resources>
                <ControlTemplate x:Key="ToggleButtonTemplate" TargetType="ToggleButton">
                  <Grid Background="Transparent">
                    <VisualStateManager.VisualStateGroups>
                      <VisualStateGroup x:Name="CommonStates">
                        <VisualState x:Name="Normal"/>
                        <VisualState x:Name="MouseOver">
                          <Storyboard>
                            <ColorAnimation Duration="0" Storyboard.TargetName="CollapsedArrow" Storyboard.TargetProperty="(Stroke).Color" To="#FF6DBDD1"/>
                            <ColorAnimation Duration="0" Storyboard.TargetName="ExpandedArrow" Storyboard.TargetProperty="(Fill).Color" To="#FF6DBDD1"/>
                          </Storyboard>
                        </VisualState>
                        <VisualState x:Name="Pressed">
                          <Storyboard>
                            <ColorAnimation Duration="0" Storyboard.TargetName="CollapsedArrow" Storyboard.TargetProperty="(Stroke).Color" To="#FF6DBDD1"/>
                            <ColorAnimation Duration="0" Storyboard.TargetName="ExpandedArrow" Storyboard.TargetProperty="(Fill).Color" To="#FF6DBDD1"/>
                          </Storyboard>
                        </VisualState>
                        <VisualState x:Name="Disabled">
                          <Storyboard>
                            <DoubleAnimation Duration="0" Storyboard.TargetName="CollapsedArrow" Storyboard.TargetProperty="Opacity" To=".5"/>
                            <DoubleAnimation Duration="0" Storyboard.TargetName="ExpandedArrow" Storyboard.TargetProperty="Opacity" To=".5"/>
                          </Storyboard>
                        </VisualState>
                      </VisualStateGroup>
                      <VisualStateGroup x:Name="CheckStates">
                        <VisualState x:Name="Checked"/>
                        <VisualState x:Name="Unchecked">
                          <Storyboard>
                            <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetName="CollapsedArrow" Storyboard.TargetProperty="Visibility">
                              <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
                            </ObjectAnimationUsingKeyFrames>
                            <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetName="ExpandedArrow" Storyboard.TargetProperty="Visibility">
                              <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                            </ObjectAnimationUsingKeyFrames>
                          </Storyboard>
                        </VisualState>
                      </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Path x:Name="CollapsedArrow" Stretch="Uniform" Stroke="#FF414345" HorizontalAlignment="Center" VerticalAlignment="Center" Width="5" Visibility="Collapsed" Data="F1 M 0,0 L 0,1 L .6,.5 L 0,0 Z"/>
                    <Path x:Name="ExpandedArrow" Fill="#FF414345" Stretch="Uniform" HorizontalAlignment="Center" VerticalAlignment="Center" Width="6" Data="F1 M 0,1 L 1,1 L 1,0 L 0,1 Z"/>
                  </Grid>
                </ControlTemplate>
              </dataPrimitives:DataGridFrozenGrid.Resources>
              <dataPrimitives:DataGridFrozenGrid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition/>
              </dataPrimitives:DataGridFrozenGrid.ColumnDefinitions>
              <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="CurrentStates">
                  <VisualState x:Name="Regular"/>
                  <VisualState x:Name="Current">
                    <Storyboard>
                      <DoubleAnimation Duration="0" Storyboard.TargetName="FocusVisual" Storyboard.TargetProperty="Opacity" To="1"/>
                    </Storyboard>
                  </VisualState>
                </VisualStateGroup>
              </VisualStateManager.VisualStateGroups>
              <dataPrimitives:DataGridFrozenGrid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition/>
                <RowDefinition Height="Auto"/>
              </dataPrimitives:DataGridFrozenGrid.RowDefinitions>
              <Rectangle Fill="#FFFFFFFF" Height="1" Grid.Column="1" Grid.ColumnSpan="5"/>
              <Rectangle x:Name="IndentSpacer" Grid.Column="1" Grid.Row="1"/>
              <ToggleButton x:Name="ExpanderButton" Height="15" Margin="2,0,0,0" Width="15" Template="{StaticResource ToggleButtonTemplate}" Grid.Column="2" Grid.Row="1"/>
              <StackPanel Margin="0,1,0,1" VerticalAlignment="Center" Grid.Column="3" Grid.Row="1" Orientation="Horizontal">

                <TextBlock x:Name="PropertyNameElement" Margin="4,0,0,0" Visibility="{TemplateBinding PropertyNameVisibility}"/>

                <TextBlock Margin="4,0,0,0" Text="{Binding Name}"/>
                <TextBlock x:Name="ItemCountElement" Margin="4,0,0,0" Visibility="{TemplateBinding ItemCountVisibility}"/>
              </StackPanel>
              <Rectangle Fill="#FFD3D3D3" Height="1" Grid.Column="1" Grid.ColumnSpan="5" Grid.Row="2"/>
              <Rectangle x:Name="FocusVisual" Stroke="#FF6DBDD1" StrokeThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" IsHitTestVisible="false" Opacity="0" Grid.Column="1" Grid.ColumnSpan="4" Grid.RowSpan="3"/>
              <dataPrimitives:DataGridRowHeader x:Name="RowHeader" Grid.RowSpan="3" dataPrimitives:DataGridFrozenGrid.IsFrozen="True"/>
            </dataPrimitives:DataGridFrozenGrid>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>
  </data:DataGrid.RowGroupHeaderStyles>
</data:DataGrid>

I have added blank lines before and after the TextBlock that contains the offending text. You can completely turn it off by using the following XAML:

<data:DataGrid>
   <data:DataGrid.RowGroupHeaderStyles>
     <Style TargetType="data:DataGridRowGroupHeader">
       <Setter Property="PropertyNameVisibility" Value="Collapsed"/>
     </Style>
  <data:DataGrid.RowGroupHeaderStyles>
</data:DataGrid>

If you want to modify the text you will have both remove the name of the TextBlock and add a Text attribute:

<TextBlock Margin="4,0,0,0" Visibility="{TemplateBinding PropertyNameVisibility}" Text="Client Name:"/>

The DataGridRowGroupHeader will look for a TextBlock named PropertyNameElement and set the text from code, and to avoid that happening you will have to remove the name from the template.

Martin Liversage
A: 

Martin, can you post code which assign value to PropertyNameElement TextBlock from code? I would like to display custom information (including grouped item value) in each group header.

Thx

Fel4334
A: 

How to extract DataGridRowGroupHeader template using Blend? I don't see it there.

tomasK
A: 

Hi

How to resuse the DataGridRowGroupHeader template across multiple grids.

Thanks, Sreekanth Boya

sreekanth
A: 

I have implemented the template graciously provided by Martin Liversage (thanks!) but I can't seem to control the height of the group data row. Adjusting the size of the rectangles etc just takes up more room in the row, hiding other parts. It seems the row height is being controlled by the container for the row, outside the influence of the template. TIA Toby

Found the answer!
Refer to http://msdn.microsoft.com/en-us/library/cc278075%28VS.95%29.aspx
This defines all the control styles and templates and zooming into the DataGrid and viewing the Default Template you will find:

<data:DataGrid.RowGroupHeaderStyles>
<Style TargetType="local:DataGridRowGroupHeader">
<Setter Property="Cursor" Value="Arrow" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Background" Value="#FFE4E8EA" />
<Setter Property="Height" Value="20"/>
<Setter Property="Template">
    <Setter.Value>
     <ControlTemplate TargetType="local:DataGridRowGroupHeader">
     ...snip...
     </ControlTemplate>
    </Setter.Value>
</Setter>
</Style>
</data:DataGrid.RowGroupHeaderStyles>

Setting the Height property does the job.

I still want to know how to extract the template using Blend...
I spent about 5 minutes trying to figure out how to get the default template using Blend, then I just opened Reflector and extracted generic.xaml from the assembly's resources. Microsoft really has to come up with a better solution for this, bunch of daft pri...
Rory
A: 

@Toby - RightClick the grid in Blend and choose 'Edit Additional Templates'

Greg