WPF - VirtualizingStackPanel 在 DataGrid 中进入编辑模式时请求所有项

本文关键字:模式 请求 编辑 VirtualizingStackPanel DataGrid WPF | 更新日期: 2023-09-27 18:36:47

我正在使用带有CellEditingTemplatesDataGridItemsSource使用数据虚拟化集合(AlphaChiTech 解决方案),该解决方案一次仅按需获取 100 个项目的页面。

在双击单元格进入编辑表单之前,它工作得很好,然后VirtualizingStackPanel一个接一个地请求所有项目。当然,作为副作用,最终会请求所有页面。

有没有办法解决这个问题?

编辑:

我找到了一个解决方法,可能会对处于我这种情况的人有所帮助:

最终,我观察到 VirtualizingStackPanel 在切换到编辑表单后行高保持不变的情况下不会请求所有项目。在解决方法之前,我的编辑表单略高。

现在,我在单元格(正常和编辑)中设置控件的 MinHeight,这样切换到编辑表单时高度不会改变。

不幸的是,这仅在某些条件下有效。在某些情况下,它不起作用:

  • 使用RowDetailsTemplate .一旦可见,虚拟化就被破坏了。我假设行详细信息属于行本身,因此行高再次增加。

  • 根据集合视图引发集合的重置事件。根据我的经验,这通常是使用DataGrids进行数据虚拟化的杀手。

  • 取消集合的Count(这也不会引发 Reset 事件的问题)。

有趣的是,增加收藏Count确实奏效了。但是我必须增强 AlphaChiTech 的功能(幸运的是,源代码在 github 上),因为如果不开箱即用地引发重置事件,就无法更改Count(至少我没有找到)。此外,DataGrid's项必须在之后立即刷新,否则会引发异常,指出ItemsControl和集合确实具有不一致的状态。

行详细信息对我来说是可选的,但在不破坏数据虚拟化的情况下删除项目至关重要。因此,问题仍然存在。我的解决方法很可能会帮助人们使用固定大小的集合,但不幸的是不是我自己。

WPF - VirtualizingStackPanel 在 DataGrid 中进入编辑模式时请求所有项

解决方法

我自己找到了解决此问题的方法。此解决方法适用于在 WPF 中使用数据虚拟化的可编辑集合(无需解决方法即可实现数据虚拟化只读集合)。

首先,行的大小必须是单一的。我的一个问题是CellEditingTemplates高于CellTemplates。因此,每次触发编辑表单时,DataGrid都会获取集合中的所有项目。将CellTemplatesMinHeight设置为与CellEditingTemplates的高度相匹配就可以解决问题。

显然,RowDetailsTemplate属于该行,因此当它可见时,它会更改行的高度,从而破坏数据虚拟化。因此,最好不要使用行详细信息并使用主从模式,其中"详细信息"显示在DataGrid之外。后者我现在正在尝试实现(未完全实现的第一次尝试效果很好,足以说明这不会造成任何麻烦)。我确实想到了行详细信息的一个例外:如果行详细信息始终可见并且每个项目都具有相同大小的行详细信息,那么它可能会起作用。这个想法是行的高度是单一大小的,但是在我的应用程序中,整个集合中只有少数项目需要详细信息,我没有尝试这种方法。

其次,减少计数(意味着删除项目)并在集合或DataGrid上重置项目也会触发所有项目的获取。此处的解决方法是在添加或删除项时,将现有集合替换为相同项的新集合对象。幸运的是,这个新集合也是数据虚拟化的。因此,它仍然省时,流畅,用户不会注意到它。但是,如果在DataGrid中选择项目时执行这样的"刷新",仍然存在问题。这里有一个令人讨厌的解决方法:我在管理虚拟化集合的ViewModel中实现了两个事件。这些是PreVirtualizedRefreshPostVirtualizedRefresh.带有DataGridView订阅它们,并在PreVirtualizedRefreshPostVirtualizedRefresh取消选择的项目索引(如果记忆)可能再次选择时取消选择DataGrid中的每个项目。后来一个对我来说仍然不太好用。

重要的是,有了这些解决方法(使用替代的主从模式并使用新的集合对象刷新和取消选择项目),数据虚拟化就不会被破坏。

言论

在处理这些问题时尝试的所有虚拟化解决方案中,我认为AlphaChi解决方案是最好的。

WPF 在构建时绝对不会考虑数据虚拟化。另一方面,它的成功者UWP甚至具有自己的数据虚拟化接口。因为我没有任何UWP项目,所以我无法自己尝试,但我想这会很有趣。话虽如此, UWP 没有本机DataGrid ,因此必须将数据虚拟化集合馈送到Lists或第三方DataGrids。因此,也需要权衡取舍。