如何处理小组小计WPF DataGrid中的目标行? [英] how to handle group subtotal and e.g. target rows in WPF DataGrid?

查看:134
本文介绍了如何处理小组小计WPF DataGrid中的目标行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实现包含许多关键数字的项目的WPF DataGrid。项目按项目类别分组。



对于每个类别,应该有:


  1. 关键图列列的所有行的总和。

  2. 不是绑定到数据源网格的一部分的目标行。目标行告诉每一列每年的目标是什么(例如花费多少钱)。

这些行应该总是在每个组的顶部(排序过滤)。



我的第一个解决方案是在组头中拥有这些数据。这不是一个很好的解决方案,因为组头不支持列。即,它应该通过获取列宽度来构造。



可以这样做,但是当用户想要重新排序和隐藏列时,它会变得复杂。



DataGrid正在使用CollectionViewSource,因此它没有填充C#代码。基本上我正在扩展这个例子: http://msdn.microsoft.com/en -us / library / ff407126.aspx



谢谢&最好的问候 - matti

解决方案

我在我的一个项目中有一个黑客的DataGrid与组小计行。我们不担心您提出的一些问题,例如隐藏和排序列,所以我不知道是否可以扩展。我也意识到可能会出现性能问题,这可能是大集合的问题(我的窗口运行32个单独的DataGrids - ouch)。但是与其他解决方案不同,所以我以为我会把它扔在这里,看看它是否可以帮助你。



我的解决方案包括2个主要组件:

1.小计行不是主DataGrid中的行,而是单独的DataGrids。实际上每个组中有两个额外的网格:标题中只有一个组合被折叠时显示,另外一个在ItemsPresenter下方。 DataGrids小计的ItemsSource来自一个转换器,它接收组中的项目并返回聚合视图模型。小计网格的列与主网格完全相同(填写在DataGrid_Loaded中,尽管我确信它可以在xaml中完成)。

 < GroupStyle> 
< GroupStyle.ContainerStyle>
< Style TargetType ={x:Type GroupItem}>
< Setter Property =Template>
< Setter.Value>
< ControlTemplate TargetType ={x:Type GroupItem}>
< Expander Background =GrayHorizo​​ntalAlignment =LeftIsExpanded =True
ScrollViewer.CanContentScroll =True>
< Expander.Header>
< DataGrid Name =HeaderGridItemsSource ={Binding Path =。,Converter = {StaticResource SumConverter}}
Loaded =DataGrid_LoadedHeadersVisibility =Row
Margin = 25 0 0 0PreviewMouseDown =HeaderGrid_PreviewMouseDown>
< DataGrid.Style>
< Style TargetType =DataGrid>
< Style.Triggers>
< DataTrigger Binding ={Binding RelativeSource = {RelativeSource AncestorType = Expander},Path = IsExpanded}
Value =True>
< Setter Property =VisibilityValue =Collapsed/>
< / DataTrigger>
< /Style.Triggers>
< / Style>
< /DataGrid.Style>
< / DataGrid>
< /Expander.Header>
< StackPanel>
< ItemsPresenter />
< DataGrid Name =FooterGridItemsSource ={Binding ElementName = HeaderGrid,Path = ItemsSource,Mode = OneWay}
Loaded =DataGrid_LoadedHeadersVisibility =Row
Margin = 50 0 0 0>
< DataGrid.Style>
< Style TargetType =DataGrid>
< Style.Triggers>
< DataTrigger Binding ={Binding RelativeSource = {RelativeSource AncestorType = Expander},Path = IsExpanded}
Value =False>
< Setter Property =VisibilityValue =Collapsed/>
< / DataTrigger>
< /Style.Triggers>
< / Style>
< / DataGrid>
< / StackPanel>
< / Expander>
< / ControlTemplate>
< /Setter.Value>
< / Setter>
< / Style>
< /GroupStyle.ContainerStyle>
< / GroupStyle>



2.然后问题是如何让所有DataGrids的行为如果他们是一个单一的网格。我已经通过子类化 DataGridTextColumn (我们在这种情况下只有文本,但其他列类型也应该工作)在一个名为的类中DataGridSharedSizeTextColumn ,它模拟了Grid类的SharedSizeGroup行为。它具有一个具有组名称的字符串依赖属性,并跟踪同一组中的所有列。当一列中 Width.DesiredValue 更改时,我会更新所有其他列中的MinWidth,并强制使用 DataGridOwner.UpdateLayout()。此类也覆盖列重新排序,并在DisplayIndex更改时进行组范围更新。我会认为这种方法也可以与任何其他列属性一起使用,只要它有一个设置器。



还有其他烦人的事情要选择,复制等但是,通过使用MouseEntered和MouseLeave事件以及使用自定义的Copy命令,可以很容易地处理。


I'm implementing a WPF DataGrid that contains projects with many key figures. Projects are grouped by project categories.

For each category there should be:

  1. a row that shows in each key figure column sum of all rows for the column.
  2. a target row that is not part of the datasource grid in binded to. target row tells for every column what is target for the year (e.g. how much money there's to spend).

These rows should be always on top in each group (sorting filtering).

My 1st solution was to have this data in group header. This is not a good solution because group header does not support columns. i.e. it should be constructed by getting column widths.

That could be done but it gets complicated when users want to reorder and hide columns.

DataGrid is using CollectionViewSource so it's not populated with C# code. Basically i'm extending this example: http://msdn.microsoft.com/en-us/library/ff407126.aspx

Thanks & Best Regards - matti

解决方案

I have a hacked-together DataGrid with group subtotal rows in one of my projects. We weren't concerned about some of the issues you bring up, such as hiding and sorting columns so I don't know for sure if it can be extended for that. I also realize there could be performance issues that may be a problem with large sets (my window is operating 32 separate DataGrids - ouch). But it's a different direction from other solutions I've seen, so I thought I'd throw it up here and see if it helps you out.

My solution consists of 2 major components:
1. The subtotal rows aren't rows in the main DataGrid, but are separate DataGrids. I have 2 extra grids in each group actually: 1 in the header that is only displayed when the group is collapsed, and one beneath the ItemsPresenter. The ItemsSource for the subtotal DataGrids comes from a Converter that takes the items in the group and returns an aggregate view model. The columns of the subtotal grids are exactly the same as the main grid (filled out in DataGrid_Loaded, though I'm sure it could be done in xaml too).

            <GroupStyle>
                <GroupStyle.ContainerStyle>
                    <Style TargetType="{x:Type GroupItem}">
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="{x:Type GroupItem}">
                                    <Expander Background="Gray" HorizontalAlignment="Left" IsExpanded="True"
                                              ScrollViewer.CanContentScroll="True">
                                        <Expander.Header>
                                            <DataGrid Name="HeaderGrid" ItemsSource="{Binding Path=., Converter={StaticResource SumConverter}}"
                                                        Loaded="DataGrid_Loaded" HeadersVisibility="Row"
                                                        Margin="25 0 0 0" PreviewMouseDown="HeaderGrid_PreviewMouseDown">
                                                <DataGrid.Style>
                                                    <Style TargetType="DataGrid">
                                                        <Style.Triggers>
                                                            <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=Expander}, Path=IsExpanded}"
                                                                            Value="True">
                                                                <Setter Property="Visibility" Value="Collapsed"/>
                                                            </DataTrigger>
                                                        </Style.Triggers>
                                                    </Style>
                                                </DataGrid.Style>
                                            </DataGrid>
                                        </Expander.Header>
                                        <StackPanel>
                                            <ItemsPresenter/>
                                            <DataGrid Name="FooterGrid" ItemsSource="{Binding ElementName=HeaderGrid, Path=ItemsSource, Mode=OneWay}"
                                                            Loaded="DataGrid_Loaded" HeadersVisibility="Row"
                                                            Margin="50 0 0 0">
                                                <DataGrid.Style>
                                                    <Style TargetType="DataGrid">
                                                        <Style.Triggers>
                                                            <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=Expander}, Path=IsExpanded}"
                                                                         Value="False">
                                                                <Setter Property="Visibility" Value="Collapsed"/>
                                                            </DataTrigger>
                                                        </Style.Triggers>
                                                    </Style>
                                            </DataGrid>
                                        </StackPanel>
                                    </Expander>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </GroupStyle.ContainerStyle>
            </GroupStyle>


2. Then the issue is how to get all DataGrids to behave as if they were a single grid. I've handled that by subclassing DataGridTextColumn (we only have text in this case, but other column types should work too) in a class called DataGridSharedSizeTextColumn that mimics the SharedSizeGroup behavior of the Grid class. It has a string dependency property with a group name and keeps track of all columns in the same group. When Width.DesiredValue changes in one column, I update the MinWidth in all the other columns and force an update with DataGridOwner.UpdateLayout(). This class is also covering column reordering and does a group-wide update whenever DisplayIndex changes. I would think this method would also work with any other column property as long as it has a setter.

There were other annoying things to work out with selection, copying, etc. But it turned out to be pretty easy to handle with MouseEntered and MouseLeave events and by using a custom Copy command.

这篇关于如何处理小组小计WPF DataGrid中的目标行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆