wez
wez

Reputation: 21

WPF 4.0 - Datagrid column widths & margins with grouping

I've come across a problem related to grouping in the WPF Data Grid where the right hand side margin does not match the left hand side when using an expander control. This issue is more obvious when adding extra margin to the expander.

My intention is to have each group as an expander but with a margin either side, so as more groups are added, the grid columns become "squeezed" more into the centre. This appears to happen on the left hand side, but not the right hand side.

All of my columns are "auto" apart from one which is set to * so that the grid column always stretches to fit the window. In doing this, the grid seems to have trouble creating the extra space required on the right hand side to fit the entire column set. The left hand side seems fine as it appears to expand the row selector every time a new group is created, pushing the grid columns further to the right.

This is how it currently looks: http://oi58.tinypic.com/117cojb.jpg

This is how i want it to look when adding a new group each time: http://oi62.tinypic.com/2rcn20w.jpg

In the second picture, I had to manually drag the column widths to get the expander to fit "on screen". Ideally i want this to be handled automatically for each new group which is added.


The Window Xaml...

<Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        Width="1000"
        Height="600">

    <Window.Resources>

        <!--  Data Grid  -->
        <Style TargetType="{x:Type DataGrid}">
            <Setter Property="BorderThickness" Value="0" />
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="RowBackground" Value="Transparent" />
            <Setter Property="AlternationCount" Value="2" />
            <Setter Property="GridLinesVisibility" Value="None" />
            <Setter Property="SelectionMode" Value="Extended" />
            <Setter Property="SelectionUnit" Value="FullRow" />
            <Setter Property="CanUserAddRows" Value="False" />
            <Setter Property="IsReadOnly" Value="True" />
            <Setter Property="AutoGenerateColumns" Value="False" />
            <Setter Property="IsSynchronizedWithCurrentItem" Value="False" />
            <Setter Property="RowHeaderWidth" Value="0" />
        </Style>

        <!--  Group Style  -->
        <Style x:Key="DefaultGroupStyle" TargetType="{x:Type GroupItem}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type GroupItem}">
                        <Expander Header="{Binding Name}" 
         Margin="10"
                                  IsExpanded="True"
                                  >
                            <ItemsPresenter />
                        </Expander>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <!-- Expander -->
        <Style TargetType="{x:Type Expander}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Expander}">
                        <Grid>

                            <Border Background="LightCoral"  CornerRadius="3" Opacity="0.5" />

                            <DockPanel>

                                <StackPanel 
                                        DockPanel.Dock="Top"
                                        Orientation="Horizontal">

                                    <ToggleButton Width="20" Content=">" Margin="5" VerticalAlignment="Center" 
                                              IsChecked="{Binding Path=IsExpanded,
                                                                  RelativeSource={RelativeSource TemplatedParent}}"
                                               />

                                    <ContentPresenter  VerticalAlignment="Center" 
                                                  Content="{TemplateBinding Header}"
                                                  ContentTemplate="{TemplateBinding HeaderTemplate}"
                                                  ContentTemplateSelector="{TemplateBinding HeaderTemplateSelector}"
                                                  DockPanel.Dock="Top"
                                                  Focusable="false" />

                                </StackPanel>

                                <ContentPresenter x:Name="ExpanderContent"

                                              DockPanel.Dock="Bottom"
                                              Visibility="Collapsed" />
                            </DockPanel>

                        </Grid>

                        <ControlTemplate.Triggers>
                            <Trigger Property="IsExpanded" Value="True">
                                <Setter TargetName="ExpanderContent" Property="Visibility" Value="Visible" />
                            </Trigger>
                        </ControlTemplate.Triggers>

                    </ControlTemplate>
                </Setter.Value>
            </Setter>

        </Style>

    </Window.Resources>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <DataGrid x:Name="IssuesGrid"
                  Margin="20"
                  ItemsSource="{Binding}">
            <DataGrid.Columns>

                <DataGridTextColumn Width="Auto"
                                    Binding="{Binding ID}"
                                    CanUserSort="False"
                                    Header="ID" />
                <DataGridTextColumn Width="Auto"
                                    Binding="{Binding Customer}"
                                    CanUserSort="False"
                                    Header="Customer" />
                <DataGridTextColumn Width="*"
                                    Binding="{Binding Title}"
                                    CanUserSort="False"
                                    Header="Title" />
                <DataGridTextColumn Width="Auto"
                                    Binding="{Binding AssignedTo}"
                                    CanUserSort="False"
                                    Header="Assigned To" />
            </DataGrid.Columns>

            <DataGrid.GroupStyle>
                <GroupStyle ContainerStyle="{StaticResource DefaultGroupStyle}">
                    <GroupStyle.Panel>
                        <ItemsPanelTemplate>
                            <DataGridRowsPresenter />
                        </ItemsPanelTemplate>
                    </GroupStyle.Panel>
                </GroupStyle>
            </DataGrid.GroupStyle>

        </DataGrid>

        <StackPanel Grid.Row="1"
                    HorizontalAlignment="Center"
                    Orientation="Horizontal">
            <Button x:Name="btnGroup1"
                    Width="Auto"
                    Margin="5"
                    Content="Add  Group" />

        </StackPanel>

    </Grid>
</Window>

The Code Behind...

Imports System.ComponentModel
Imports System.Collections.ObjectModel

Public Class MainWindow

    Public Items As New IssueCollection

    Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded

        Items.Add(New Issue With {.ID = "1234", .AssignedTo = "John Doe", .Customer = "Customer A", .Title = "A long title to take up a good amount of space"})
        Items.Add(New Issue With {.ID = "1234", .AssignedTo = "John Doe", .Customer = "Customer A", .Title = "A long title to take up a good amount of space"})
        Items.Add(New Issue With {.ID = "1234", .AssignedTo = "John Doe", .Customer = "Customer B", .Title = "A long title to take up a good amount of space"})
        Items.Add(New Issue With {.ID = "1234", .AssignedTo = "John Doe", .Customer = "Customer B", .Title = "A long title to take up a good amount of space"})
        Items.Add(New Issue With {.ID = "1234", .AssignedTo = "John Doe", .Customer = "Customer B", .Title = "A long title to take up a good amount of space"})

        IssuesGrid.ItemsSource = CollectionViewSource.GetDefaultView(Items)

    End Sub

    Private Sub btnGroup1_Click(sender As Object, e As RoutedEventArgs) Handles btnGroup1.Click
        CType(IssuesGrid.ItemsSource, ICollectionView).GroupDescriptions.Add(New PropertyGroupDescription("Customer"))
    End Sub

End Class

Public Class Issue
    Public Property ID As String
    Public Property AssignedTo As String
    Public Property Customer As String
    Public Property Title As String

End Class

Public Class IssueCollection
    Inherits ObservableCollection(Of Issue)
    Implements INotifyPropertyChanged

    Public Sub New()
    End Sub

End Class

Any ideas on how i can get around this problem?- I've tried altering the margin and padding on all levels (i.e. columns, row presenter and expander) with no luck.

Thank you.

Upvotes: 2

Views: 2574

Answers (1)

pushpraj
pushpraj

Reputation: 13679

I made little adjustment to group style

    <!--  Group Style  -->
    <Style x:Key="DefaultGroupStyle" TargetType="{x:Type GroupItem}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type GroupItem}">
                    <Grid Width="{Binding ActualWidth,RelativeSource={RelativeSource TemplatedParent}}">
                        <Expander Header="{Binding Name}" Margin="10" IsExpanded="True">
                            <ItemsPresenter />
                        </Expander>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

I enclosed the expander in a grid and binded it's width to the container's width, which will eventually restrict the child to grow larger

however this approach has a limitation i.e. this will not re-position the grid columns so may have some artifects, I think that can be handled separately

result

result

Upvotes: 1

Related Questions