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

时间:2016-02-28 20:45:33

标签: c# wpf datagrid virtualizingstackpanel data-virtualization

我正在DataGrid使用CellEditingTemplates。作为ItemsSource,使用数据虚拟化集合(AlphaChiTech解决方案),该解决方案仅按需提取100个项目的页面。

在将单元格双击到编辑表单中之前,它很有效,然后VirtualizingStackPanel一个接一个地请求所有项目。当然,作为副作用,最终会要求所有页面。

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

修改

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

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

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

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

  • 使用RowDetailsTemplate。一旦可见,虚拟化就会被破坏。我假设行详细信息属于它自己的行,因此行高再次增加。

  • 将Collection的Reset事件分别提升为CollectionView。根据我的经验,这通常是使用DataGrids进行数据虚拟化的杀手。

  • 决定集合的Count(这也不会导致重置事件失败)。

有趣的是,增加集合的Count确实有效。但是我必须增强AlphaChiTech的功能(幸运的是github上的源代码),因为没有办法改变Count而没有提升开箱即用的重置事件(至少我没有找到)。此外,DataGrid's项必须立即刷新,否则抛出异常,表明ItemsControl和集合确实存在不一致的状态。

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

1 个答案:

答案 0 :(得分:0)

解决方法

我自己找到了解决此问题的解决方案。 此解决方法是在WPF中使用数据虚拟化可编辑集合(数据虚拟化只读集合可在没有解决方法的情况下实现)。

首先,行必须是单一的。我的一个问题是CellEditingTemplates高于CellTemplates。因此,每次触发编辑表单时,DataGrid都会获取集合中的所有项目。设置MinHeight的{​​{1}}以匹配CellTemplates的高度就可以了。

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

其次,减少计数 - 意味着删除项目 - 并重置集合上的项目或DataGrid也会触发所有项目的获取。此处的解决方法是在添加或删除项目时,使用相同项目的新集合对象替换现有集合。幸运的是,这个新系列也是数据虚拟化的。所以它仍然是时间效率,流畅,用户不会注意到它。但是,如果这样一个"刷新"在DataGrid中选择项目时执行。这是一个讨厌的解决方法:我在DataGrid中实现了两个事件,它管理虚拟化集合。这些是ViewModelPreVirtualizedRefreshPostVirtualizedRefresh View订阅DataGrid并取消选择DataGrid PreVirtualizedRefreshPostVirtualizedRefresh取消选择的项目索引(如果已记住)可能是再次选中。后来一个仍然不适合我。

重要的是,通过这些解决方法(使用备用主 - 详细模式并使用新的集合对象和取消选择项进行刷新),数据虚拟化不会被破坏。

<强>说明

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

WPF绝对不是以数据虚拟化为基础构建的。另一方面,它的成功者UWP甚至还有一个自己的数据虚拟化接口。因为我没有任何UWP项目我无法尝试自己,但我想它会带来很多乐趣。话虽如此,UWP没有原生DataGrid,因此必须将数据虚拟化集合提供给Lists或第三方DataGrids。所以还需要权衡。