WPF - VirtualizingStackPanel 在 DataGrid 中进入编辑模式时请求所有项目
WPF - VirtualizingStackPanel requests all items when going into editing mode in DataGrid
我正在使用 DataGrid
和 CellEditingTemplates
。由于 ItemsSource
使用了数据虚拟化集合(AlphaChiTech 解决方案),它一次只能按需获取 100 个项目大小的页面。
在双击一个单元格进入编辑表单之前效果很好,然后 VirtualizingStackPanel
一个接一个地请求所有项目。当然,作为副作用,最终会请求所有页面。
有没有办法解决这个问题?
编辑:
我找到了一个解决方法,它可能会对遇到我情况的人有所帮助:
最后观察到切换到编辑表单后,在行高不变的情况下,VirtualizingStackPanel并没有请求所有item。在解决方法之前,我的编辑表单略高。
现在我设置了单元格(正常和编辑)中控件的 MinHeight,这样在切换到编辑表单时高度不会改变。
不幸的是,这仅在特定条件下有效。在某些情况下它不起作用:
使用 RowDetailsTemplate
。一旦它可见,虚拟化就会被破坏。我假设行详细信息属于行本身,因此行高再次增加。
分别在 CollectionView 中引发 Collection 的 Reset 事件。根据我的经验,这通常是 DataGrids
.
数据虚拟化的杀手
Decraesing the Count
of the collection (这也没有引发 Reset 事件的问题)。
有趣的是,增加集合的 Count
确实有效。但是我必须增强 AlphaChiTech 的功能(幸运的是源代码在 github 上),因为没有办法在不引发开箱即用的重置事件的情况下更改 Count
(至少我没有找到)。此外,DataGrid's
项目必须在之后立即刷新,否则会抛出异常,指出 ItemsControl
和集合确实具有不一致状态。
行详细信息对我来说是可选的,但在不破坏数据虚拟化的情况下删除项目是至关重要的。因此,问题仍然存在。我的解决方法很可能会帮助那些拥有固定大小集合的人,但不幸的是我不会。
解决方法
我自己找到了解决这个问题的方法。
此解决方法适用于在 WPF 中使用数据虚拟化的可编辑集合(无需解决方法即可实现数据虚拟化的只读集合)。
首先,行必须是统一大小的。我的问题之一是 CellEditingTemplates
高于 CellTemplates
。因此,每次触发编辑表单时,DataGrid
都会获取集合中的所有项目。设置 CellTemplates
的 MinHeight
以匹配 CellEditingTemplates
的高度就可以了。
显然,RowDetailsTemplate
属于行,因此当可见时,它会改变行的高度,从而破坏数据虚拟化。因此,最好不要使用行详细信息并使用主从模式,其中 "details" 显示在 DataGrid
之外。后者我现在正在尝试实施(第一次未完全实施的尝试效果很好,足以说明这不会造成任何麻烦)。我确实想到了行详细信息的一个例外:如果行详细信息始终可见并且每个项目都具有相同大小的行详细信息,那么它可能会起作用。这个想法是行的高度然后是统一大小的,但在我的应用程序中,整个集合中只有少数项目需要详细信息,我没有尝试这种方法。
其次,减少计数 - 意味着删除项目 - 并重置集合中的项目或 DataGrid
也会触发所有项目的获取。此处的解决方法是在添加或删除项目时,用相同项目的新集合对象替换现有集合。幸运的是,这个新系列也是数据虚拟化的。所以它仍然是省时的,流畅的,用户不会注意到它。但是如果在 DataGrid
中选择了一个项目时执行这样的 "refresh" 仍然存在问题。这是一个令人讨厌的解决方法:我在 ViewModel
中实现了两个事件,它管理虚拟化集合。它们是 PreVirtualizedRefresh
和 PostVirtualizedRefresh
。 View
和 DataGrid
订阅它们并在 PreVirtualizedRefresh
和 PostVirtualizedRefresh
上取消选择 DataGrid
中的每个项目,取消选择的项目索引(如果记住)可能是再次选择。后来一个仍然不适合我。
重要的是,有了这些解决方法(使用备用主从模式并使用新的集合对象刷新并取消选择项目),数据虚拟化将不会被破坏。
备注
在我处理这些问题时尝试过的所有虚拟化解决方案中,我认为 AlphaChi 解决方案是最好的。
WPF 绝对不是在考虑数据虚拟化的情况下构建的。另一方面,它的继任者 UWP 甚至有自己的数据虚拟化接口。因为我没有任何 UWP 项目,所以我无法亲自尝试,但我想这会很有趣。话虽如此,UWP 没有原生 DataGrid
,因此数据虚拟化集合必须提供给 Lists
或第三方 DataGrids
。所以也需要权衡。
我正在使用 DataGrid
和 CellEditingTemplates
。由于 ItemsSource
使用了数据虚拟化集合(AlphaChiTech 解决方案),它一次只能按需获取 100 个项目大小的页面。
在双击一个单元格进入编辑表单之前效果很好,然后 VirtualizingStackPanel
一个接一个地请求所有项目。当然,作为副作用,最终会请求所有页面。
有没有办法解决这个问题?
编辑:
我找到了一个解决方法,它可能会对遇到我情况的人有所帮助:
最后观察到切换到编辑表单后,在行高不变的情况下,VirtualizingStackPanel并没有请求所有item。在解决方法之前,我的编辑表单略高。
现在我设置了单元格(正常和编辑)中控件的 MinHeight,这样在切换到编辑表单时高度不会改变。
不幸的是,这仅在特定条件下有效。在某些情况下它不起作用:
使用
RowDetailsTemplate
。一旦它可见,虚拟化就会被破坏。我假设行详细信息属于行本身,因此行高再次增加。分别在 CollectionView 中引发 Collection 的 Reset 事件。根据我的经验,这通常是
DataGrids
. 数据虚拟化的杀手
Decraesing the
Count
of the collection (这也没有引发 Reset 事件的问题)。
有趣的是,增加集合的 Count
确实有效。但是我必须增强 AlphaChiTech 的功能(幸运的是源代码在 github 上),因为没有办法在不引发开箱即用的重置事件的情况下更改 Count
(至少我没有找到)。此外,DataGrid's
项目必须在之后立即刷新,否则会抛出异常,指出 ItemsControl
和集合确实具有不一致状态。
行详细信息对我来说是可选的,但在不破坏数据虚拟化的情况下删除项目是至关重要的。因此,问题仍然存在。我的解决方法很可能会帮助那些拥有固定大小集合的人,但不幸的是我不会。
解决方法
我自己找到了解决这个问题的方法。 此解决方法适用于在 WPF 中使用数据虚拟化的可编辑集合(无需解决方法即可实现数据虚拟化的只读集合)。
首先,行必须是统一大小的。我的问题之一是 CellEditingTemplates
高于 CellTemplates
。因此,每次触发编辑表单时,DataGrid
都会获取集合中的所有项目。设置 CellTemplates
的 MinHeight
以匹配 CellEditingTemplates
的高度就可以了。
显然,RowDetailsTemplate
属于行,因此当可见时,它会改变行的高度,从而破坏数据虚拟化。因此,最好不要使用行详细信息并使用主从模式,其中 "details" 显示在 DataGrid
之外。后者我现在正在尝试实施(第一次未完全实施的尝试效果很好,足以说明这不会造成任何麻烦)。我确实想到了行详细信息的一个例外:如果行详细信息始终可见并且每个项目都具有相同大小的行详细信息,那么它可能会起作用。这个想法是行的高度然后是统一大小的,但在我的应用程序中,整个集合中只有少数项目需要详细信息,我没有尝试这种方法。
其次,减少计数 - 意味着删除项目 - 并重置集合中的项目或 DataGrid
也会触发所有项目的获取。此处的解决方法是在添加或删除项目时,用相同项目的新集合对象替换现有集合。幸运的是,这个新系列也是数据虚拟化的。所以它仍然是省时的,流畅的,用户不会注意到它。但是如果在 DataGrid
中选择了一个项目时执行这样的 "refresh" 仍然存在问题。这是一个令人讨厌的解决方法:我在 ViewModel
中实现了两个事件,它管理虚拟化集合。它们是 PreVirtualizedRefresh
和 PostVirtualizedRefresh
。 View
和 DataGrid
订阅它们并在 PreVirtualizedRefresh
和 PostVirtualizedRefresh
上取消选择 DataGrid
中的每个项目,取消选择的项目索引(如果记住)可能是再次选择。后来一个仍然不适合我。
重要的是,有了这些解决方法(使用备用主从模式并使用新的集合对象刷新并取消选择项目),数据虚拟化将不会被破坏。
备注
在我处理这些问题时尝试过的所有虚拟化解决方案中,我认为 AlphaChi 解决方案是最好的。
WPF 绝对不是在考虑数据虚拟化的情况下构建的。另一方面,它的继任者 UWP 甚至有自己的数据虚拟化接口。因为我没有任何 UWP 项目,所以我无法亲自尝试,但我想这会很有趣。话虽如此,UWP 没有原生 DataGrid
,因此数据虚拟化集合必须提供给 Lists
或第三方 DataGrids
。所以也需要权衡。