WPF DataGrid Virtualization with Grouping

前端 未结 4 600
臣服心动
臣服心动 2020-12-01 02:19

I\'m using the WPF DataGrid from CodePlex and I need to get Virtualization to work with grouping.

This question is on topic and points to an MSDN Example but it onl

相关标签:
4条回答
  • 2020-12-01 02:44

    I realize I'm late to the party here... but I ran into this problem recently (using the DataGrid built into .NET 4). Unfortunately, there still is no virtualization of the rows once Grouping is used on the DataGrid... but a I found a very slick performance enhancement trick that hopefully somebody else will find useful as well.

    Assuming you're using an ItemsPresenter within an expander of your GroupItem's template and by default your expander is not expanded, then try simply binding the visibility of your ItemsPresenter to the Expander's IsEnabled property with the default BooleanToVisibilityConverter:

    <BooleanToVisibilityConverter x:Key="bool2vis" />
    
    
    <DataGrid.GroupStyle>
        <GroupStyle>
            <GroupStyle.ContainerStyle>
                <Style TargetType="{x:Type GroupItem}">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type GroupItem}">
                                <Expander x:Name="exp">
                                    <ItemsPresenter Visibility="{Binding ElementName=exp, Path=IsExpanded, Converter={StaticResource bool2vis}}" />
                                </Expander>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </GroupStyle.ContainerStyle>
        </GroupStyle>
    </DataGrid.GroupStyle>
    

    If you're running into the problem where your DataGrid takes really long to load (because it's essentially drawing out every record in your datagrid even though it's in a collapsed expander)... then using the above code will cause the datagrid to not draw your records until you expand a group, and then, it will only draw out the records for that particular group.

    The down side is that this only helps if your expanders are collapsed by default, and still the rows do not get virtualized (if you have 100 items in an expanded group, but only 20 fit on the screen, all 100 will be drawn at the time you expanded the group).

    The upside is that you've essentially implemented lazy loading of your DataGrid records, so you're not performing the drawing work until you actually need to view the items (you choose to expand the group). For my product, my group header had buttons built in to perform operations on all items within its group, so more often the user never expanded a group unless they needed to perform an operation on an individual item within a group.

    *One thing to note if you use this trick is that you should probably set some explicit widths or minimum widths to your column headers (because the items are not being drawn when the DataGrid first loads, so the column headers cannot autosize to fit the largest item).

    Hopefully true virtualization gets implemented in a future service pack, but if not, I hope this will help somebody else!

    Update

    It appears this issue will be fixed in .NET 4.5 with a new attached property VirtualizingPanel.IsVirtualizingWhenGrouping.

    0 讨论(0)
  • 2020-12-01 02:48

    There is a new attached property in framework 4.5 VirtualizingPanel.IsVirtualizingWhenGrouping, which allows to switch on virtualization when grouping.

    <DataGrid EnableColumnVirtualization="True" EnableRowVirtualization="True"
       VirtualizingPanel.IsVirtualizingWhenGrouping="True">
    
    0 讨论(0)
  • 2020-12-01 02:53

    There is no built-in feature that allows you to enable UI Virtualization when grouping is enabled in a ListView or DataGrid, If you think about it for a second it also makes sense. How is the DataGrid to group items that do not exist. To apply grouping the control would need to load the whole collection wich would defeat the whole purpose of virtualization. The best you can probably do is to provide some sort of virtualization in your viewmodel (the object you bind agains) in that you provide only the data that is currently needed plus some sort of generic data about the amount of data that exists and then fake the view yourself.

    With grouping it could go something like this: When grouping is enabled initially all groups would be collapsed. So your viewmodel would only have to provide one item for each group that there is. Just to make sure that the view contains all exisiting groups. As soon as the user expands one group the ViewModel would dynamically refill the items for that group. This is a very simple and basic way of virtulization and not optimal but it might be a good starting point to. It is just to illistrate the approach.

    0 讨论(0)
  • 2020-12-01 03:04

    As you said, enabling Grouping will disable UI virtualization.

    I don't think you'll find an easy way to solve this problem. I'd recommend you to check one of the available WPF DataGrid such as the XCeeed one that might have this feature built in their control.

    0 讨论(0)
提交回复
热议问题