我意识到我迟到了……但我最近遇到了这个问题(使用 .NET 4 中内置的 DataGrid)。不幸的是,一旦在 DataGrid 上使用分组,行仍然没有虚拟化...但是我发现了一个非常巧妙的性能增强技巧,希望其他人也会发现它很有用。
假设您在 GroupItem 模板的扩展器中使用 ItemsPresenter,并且默认情况下您的扩展器未扩展,则尝试使用默认的 BooleanToVisibilityConverter 将 ItemsPresenter 的可见性绑定到 Expander 的 IsEnabled 属性:
<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>
如果您遇到 DataGrid 需要很长时间才能加载的问题(因为它本质上是在绘制数据网格中的每条记录,即使它位于折叠的扩展器中)...那么使用上面的代码将导致数据网格无法绘制您的记录,直到您展开一个组,然后,它只会提取该特定组的记录。
缺点是,这仅在您的扩展器默认折叠时才有帮助,并且行仍然没有虚拟化(如果扩展组中有 100 个项目,但屏幕上只有 20 个项目,则所有 100 个项目都将在扩大群组的时间)。
好处是您基本上已经实现了 DataGrid 记录的延迟加载,因此直到您实际需要查看项目(您选择展开组)时才执行绘图工作。对于我的产品,我的组标题内置了按钮,用于对其组内的所有项目执行操作,因此用户通常不会扩展组,除非他们需要对组内的单个项目执行操作。
*如果您使用此技巧,需要注意的一件事是,您可能应该为列标题设置一些显式宽度或最小宽度(因为在 DataGrid 首次加载时不会绘制项目,因此列标题无法自动调整大小以适应最大的宽度)物品)。
希望真正的虚拟化能够在未来的服务包中实现,但如果没有,我希望这对其他人有帮助!
Update
看来这个问题将在 .NET 4.5 中通过新的附加属性得到修复VirtualizingPanel.IsVirtualizingWhenGrouping http://msdn.microsoft.com/en-us/library/system.windows.controls.virtualizingpanel.isvirtualizingwhengrouping%28v=vs.110%29.aspx.