WPF DataGrid 似乎没有虚拟化行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/44786431/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF DataGrid doesn't seem to be virtualizing rows
提问by Danny
I'm working on a application where the bulk of my content is presented to users with the built in WPFDataGrid. Here is what my DataGridlooks like. I don't set anything but the RowDefinitionson the parent Grid.
我正在开发一个应用程序,其中我的大部分内容通过内置的WPFDataGrid. 这是我的DataGrid样子。我没有设置任何东西,但RowDefinitions在 parent 上Grid。
<UserControl xmlns="blah blah blah">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DataGrid x:Name="dgrMaterialCollection"
IsReadOnly="True"
ItemsSource="{Binding Path=MyObservableCollection, UpdateSourceTrigger=PropertyChanged}"
AutoGenerateColumns="True"
AutoGeneratingColumn="dgrMaterialCollection_AutoGeneratingColumn"
AutoGeneratedColumns="dgrMaterialCollection_AutoGeneratedColumns"
CanUserResizeColumns="True"
CanUserReorderColumns="True"
CanUserSortColumns="True"
EnableRowVirtualization="True"
EnableColumnVirtualization="True"
VirtualizingPanel.IsVirtualizingWhenGrouping="True"
VirtualizingPanel.VirtualizationMode="Standard"
VirtualizingPanel.IsVirtualizing="True"
SelectionMode="Single"
SelectionUnit="FullRow"
ScrollViewer.CanContentScroll="False"
RowHeaderWidth="0"
Grid.Row="0"
RowHeight="32"
RowDetailsVisibilityMode="Collapsed">
<DataGrid.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="DataGridStyle.xaml"/>
</ResourceDictionary.MergedDictionaries>
<!-- A few value converters -->
</ResourceDictionary>
</DataGrid.Resources>
<!-- Some Manually Declared Columns -->
</DataGrid>
<StackPanel Grid.Row="1">
<SomeTextBoxes/>
</StackPanel>
</Grid>
</UserControl>
When my application displays the DataGrid, there is about a 10 - 20 second delay depending the size of the dataset. During this delay the UI is locked up. Once the data grid is loaded - I can scroll through all few thousand items without any delay. When I say without delay, I mean clicking on the scroll bar and moving it up and down as fast as humanly possible, with no delay in rendering the rows as it scrolls. It seems like the virtualization is not working, and instead the datagrid is creating all the rows at one time instead of while the user is scrolling.
当我的应用程序显示 时DataGrid,会有大约 10 - 20 秒的延迟,具体取决于数据集的大小。在此延迟期间,UI 被锁定。加载数据网格后 - 我可以毫不拖延地滚动浏览所有几千个项目。当我说毫不拖延时,我的意思是单击滚动条并尽可能快地上下移动它,在滚动时不延迟渲染行。似乎虚拟化不起作用,而是数据网格一次创建所有行,而不是在用户滚动时创建。
My Datagrid is nested in the following structure (spread out over multiple xaml files). There are no extra ScrollViewers, StackPanels, or anything. Just this.
我的 Datagrid 嵌套在以下结构中(分布在多个 xaml 文件中)。没有额外的ScrollViewers, StackPanels, 或任何东西。只是这个。
<RibbonWindow>
<Grid>
<ContentControl> <!-- Populated via a DataTemplate and ContentTemplateSelector -->
<UserControl>
<UserControl>
<UserControl>
<Grid>
<Here is the DataGrid>
Some things I have attempted to speed up the loading
我试图加快加载的一些事情
- Explicitly set all the column widths (shaved about 10 second off my load time)
- Turned off
AutoGenerateColumns(didn't make a difference). - Disabling the styles set in the
DataGrid'sRessourceDictionary(no difference) - Load items into my
ObservableCollectionon a background thread, using async/await, and other multithreaded strategies. This has made no difference in load times. - Add items to a new
ObservableCollection, then setting it to the databound property (so the events aren't triggered) - Add items to the
ObservableCollectionone at a time (events are triggered upon each add) - Turning virtualization on and off makes no difference in load time.
- 显式设置所有列宽(将我的加载时间缩短了大约 10 秒)
- 关闭
AutoGenerateColumns(没有区别)。 - 禁用
DataGrid'sRessourceDictionary(无区别)中设置的样式 ObservableCollection使用 async/await 和其他多线程策略在后台线程上将项目加载到 my 中。这对加载时间没有影响。- 将项目添加到 new
ObservableCollection,然后将其设置为 databound 属性(因此不会触发事件) ObservableCollection一次向一个添加项目(每次添加都会触发事件)- 打开和关闭虚拟化对加载时间没有影响。
I know the delay is not caused by populating the ObservableCollection. It starts after the collection is fully populated, and when the WPFDataGridis rendering all the rows/columns. I have virtualization enabled and it still takes forever. I am using the .NET framework 4.5.1 (so the 4.6 issue with Virtualizationis not causing this). There are also long delays when sorting (using built in datagrid sorting) and resizing columns from the UI.
我知道延迟不是由填充ObservableCollection. 它在集合完全填充后开始,并在WPFDataGrid呈现所有行/列时开始。我启用了虚拟化,但它仍然需要永远。我正在使用 .NET 框架 4.5.1(因此 4.6 问题Virtualization不会导致此问题)。排序(使用内置数据网格排序)和从 UI 调整列大小时也有很长的延迟。
What am I missing here? Is there something I can do to ensure Virtualizationis working? What are some things that might speed this up? If I know Virtualizationis working then I may move onto a new strategy, like paging or some kind of lazy loading. Another solution I would be willing to work with is one where the user interface is not blocked/frozen while all the rows are being rendered. That way the users could at least click around on other thing while rows are added in.
我在这里缺少什么?我能做些什么来确保Virtualization它正常工作吗?有哪些事情可以加快速度?如果我知道Virtualization有效,那么我可能会采用新的策略,例如分页或某种延迟加载。我愿意使用的另一个解决方案是在呈现所有行时不阻止/冻结用户界面的解决方案。这样用户至少可以在添加行的同时点击其他东西。
采纳答案by Danny
The ScrollViewer.CanContentScrollvalue on the DataGridelement must be set to Truein order for row virtualization to work properly. Here is an explanationof why it must be set this way.
在ScrollViewer.CanContentScroll对价值DataGrid元素必须设置为True以正确的行虚拟化的工作。这里解释了为什么必须这样设置。
Thanks to ChrisWfor catching that in the comments on this question.
感谢ChrisW在关于这个问题的评论中发现了这一点。

