开发者

WPF Grouping a DataGrid nested in databound tabs

开发者 https://www.devze.com 2023-01-21 18:13 出处:网络
I need to apply grouping to rows in a DataGrid that is nested in a TabControl. Both the DataGrid and the TabControl are databound.The outermost control is bound to a ViewModel that exposes a collectio

I need to apply grouping to rows in a DataGrid that is nested in a TabControl. Both the DataGrid and the TabControl are databound. The outermost control is bound to a ViewModel that exposes a collection of pages that is bound to the TabControl. Each page exposes a collection of lines that is bound to the Grid.

I am tried to follow patterns like this one from SO and this one from C-SharpCorner. I'm not married to these, so if there is a better pattern (as this post seems to indicate), I'm willing to go in another direction.

For now, I am not sure where to inject the definition of the PropertyGroupDescription and bind it to my desired PropertyName. I've tried doing it as a resource and directly as a CollectionViewSource on the DataGrid. But neither produced reasonable results.

This is what I have so far:

<UserControl x:Class="View.ViewInvoiceUserControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" >
<Grid Name="_grid" MinHeight="100">

snipped for clarity...

<TabControl 
    ItemsSource="{Binding Path=CurrentInvoice.InvoicePages}" 
    Grid.Column="0" 
    Grid.ColumnSpan="4" 
    Grid.Row="5" 
    HorizontalAlignment="Left" 
    Margin="0,4,0,0" 
    Name="_invoicePageTabControl" 
    VerticalAlignment="Top">
    <TabControl.ItemContainerStyle />
        <TabControl.ContentTemplate>
            <DataTemplate>
                <DataGrid 
                    Name="_invoiceLineGrid" 
                    AutoGenerateColumns="False" 
                    CanUserSortColumns="True"
                    ColumnHeaderStyle="{StaticResource columnHeaderStyle}"
                    HorizontalAlignment="Left" 
                    ItemsSource="{Binding InvoiceLines}" 
                    IsReadOnly="True"
                    RowDetailsVisibilityMode="VisibleWhenSelected"
                    RowStyle="{StaticResource DataGridRowStyle}"
                    SelectionUnit="FullRow"
                    VerticalAlignment="Top"
                    Visibility="{Binding Path=InvoiceLineGridVisibility}"
                    Initialized="_invoiceLineGrid_Initialized">
                    <DataGrid.Columns>
                        <DataGridTextColumn Header="Line Number" MinWidth="50"  Binding="{Binding InvoiceLineNumber}" />
                        <DataGridTextColumn Header="Description" MinWidth="50" Width="*" Binding="{Binding Description}" />
                        <DataGridTextColumn Header="Quantity" MinWidth="50" Binding="{Binding Quantity}" />
                        <DataGridTextColumn Header="Extended Cost" MinWidth="50" Width="*" Binding="{Binding ExtendedCost}" />
                    </DataGrid.Columns>
                    <DataGrid.GroupStyle>
                        <GroupStyle>
                            <GroupStyle.ContainerStyle>
                                <Style TargetType="{x:Type GroupItem}">
                                    <Setter Property="Template">
                                        <Setter.Value>
                                            <ControlTemplate TargetType="{x:Type GroupItem}">
                                                <Expander>
                                                    <Expander.Header>
                                                        <StackPanel>
                                                            <TextBlock Text="{Binding Name}" />
                                                        </StackPanel>
                                                    </Expander.Header>
                                                    <ItemsPresenter />
                                                </Expander>
                                            </ControlTemplate>
                                        </Setter.Value>
                                    </Setter>
                                </Style>
                            </GroupStyle.ContainerStyle>
             开发者_运维知识库           </GroupStyle>
                    </DataGrid.GroupStyle>
                </DataGrid>
            </DataTemplate>
        </TabControl.ContentTemplate>
    </TabControl>
</Grid>
</UserControl>

I think I need to add something like:

<CollectionViewSource>
    <CollectionViewSource.GroupDescriptions>
        <PropertyGroupDescription PropertyName="DepartmentBillingCode" />
    </CollectionViewSource.GroupDescriptions>
</CollectionViewSource>

If I add the CollectionViewSource as a resource and change the DataGrid binding, there are no rows in the grid. If I add the CollectionViewSource to the DataGrid, I get an exception: Operation is not valid while ItemsSource is in use. Access and modify elements with ItemsControl.ItemsSource instead. nested in Add value to collection of type 'System.Windows.Controls.ItemCollection' threw an exception. But I don't see a GroupDescription or PropertyGroupDescription on DataGrid.ItemSource

So, I'm feeling lost now. Any suggestions are appreciated.

Thanks


So I found a possible answer. I'm open to other people's interpretation. Is this a good solution?

Applying an SO post regarding what part of MVVM pattern is resonsible for grouping of DataGrid, I went in search of a solution to generate a grouping in the ViewModel. I found a simple example on WpfTutorial.com

In my InvoicePageViewModel, I created a new property that creates a ListViewCollection from my List. ListViewCollection allows me to add my own GroupDescription as follows:

    public ListCollectionView GroupedInvoiceLines
    {
        get
        {
            ListCollectionView groupedLines = new ListCollectionView(InvoiceLines); // TODO should this be cached?

            groupedLines.GroupDescriptions.Add(new PropertyGroupDescription("DepartmentBillingCode"));

            return groupedLines;
        }
    }

Then it was trivial to change the data binding on the DataGrid from InvoiceLines to GroupedInvoiceLines.

Comments? Questions?

0

精彩评论

暂无评论...
验证码 换一张
取 消