在ScrollViewer中使用虚拟化技术来处理WPF的DataGrid

5

我知道DataGrid支持虚拟化,所以它只会为可见行创建网格单元。然而,这似乎只适用于DataGrid受到大小限制的情况。

在我的场景中,一个DataGrid被放置在一个滚动查看器内,如下所示:

<ScrollViever>
    <StackPanel>

        <more elements .../>

        <DataGrid ... />

        <more elements .../>

    </StackPanel>
</ScrollViever>

这似乎破坏了虚拟化。在DataGrid应该显示大量项目的情况下,即使在外部ScrollViewer中向下滚动之前,可视树也会变得非常非常大。
有没有办法防止DataGrid预先创建所有单元格,而是随着ScrollViewer向下滚动而创建它们?
编辑:基本上,托管此内容的页面应该像具有顶部文本、大型表格和底部其他文本的网页一样。而不是一个DockView,其中顶部/底部始终可见,只有网格被滚动,整个页面应该滚动。这种设置可以实现这一点,但遭受了所有内容都被预先创建的问题。
另一个编辑:是否有一种方法检测到DataGrid的特定行已滚动到视图中?典型的懒加载文章使用datagrid的scrollviewer向网格添加更多项,但这里不起作用。

虚拟化堆栈面板? - Craig Graham
但是,将VirtualizingStackPanel(作为DataGrid的父级)用于会导致DataGrid仅生成其可见子项吗?我的理解是,VirtualizingStackPanel将按需创建它的子项,这意味着一旦DataGrid的第一个顶部像素变得可见,整个DataGrid就会被创建?还是我漏掉了什么? - user1211286
1
刚刚测试了一下:ScrollViewer-VirtualizingStackPanel-DataGrid并不能解决问题。DataGrid仍然会预先生成所有行。 - user1211286
啊,好吧,这只是一个想法。我不知道有什么解决方案可以保留 StackPanel 中的额外元素并避免 DataGrid 显示自己的滚动条。StackPanel 告诉它的子元素可以使用无限高度,所以当然 DataGrid 会使用它。如果是我,下一步尝试的事情就是将 DataGrid 的高度限制为 StackPanel 的高度,隐藏两个滚动条,创建一个新的滚动条,并将其绑定到控制 StackPanel 和 DataGrid 滚动位置的某些内容,使其看起来正确。很复杂。 - Craig Graham
2个回答

4

是的,你已经有了自己的答案。如果将DataGrid放在ScrollViewer或StackPanel等不传递固定约束给DataGrid的控件中,它会破坏DataGrid中的虚拟化。

你可以通过给DataGrid.Width和DataGrid.Height设置固定值来解决这个问题。

你需要知道这些固定值对于虚拟化是必须的。虚拟化需要固定的祖先元素。

以下是如何为DataGrid设置固定大小:

简单地将Height/Width绑定到ScrollViewer或Grid即可。

<Grid x:Name="grid" >
   <ScrollViever>
       <StackPanel>

           <more elements .../>

           <DataGrid Width={Binding ElementName=grid, Path=Width..} Height={Binding ElementName...} />

           <more elements .../>

       </StackPanel>
   </ScrollViever>
<Grid>

那就这样吧 :)

1
这样做的缺点是我会得到一个不受欢迎的滚动条内部嵌套滚动条的效果。用户很难与右侧的两个滚动条进行交互 - 一个滚动整个视图,另一个只滚动视图内部的数据表格行。 - user1211286
好的,这是一个问题吗?哈哈,我猜你得考虑改变UI设计了吧?如果你在stackoverflow上发布长代码,你会得到滚动条,当然默认浏览器滚动条也是可见的。最终你会有类似于你的情况。答案是42 :) 我开玩笑的。但让我们再次认真起来。如果你希望为你的视图设计另一种样式,请告诉我是否可以帮忙。 :) - dev hedgehog

0
不要将它放在 ScrollViewer 中,否则它会在那里自由伸展,直到占据整个空间。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接