实际上,应用程序需要大约20秒才能更新布局。Layout_Updated()事件将在20秒后触发。
如果我将列数减少到50个或更少,应用程序将非常响应。根据我的调查结果,性能与列数直接相关。
我该如何改善DataGrid的性能?
有一些选项可以打开,帮助您使用DataGrid对象。
EnableColumnVirtualization = true
EnableRowVirtualization = true
我认为这两个可能会有帮助。接下来,尝试将您的绑定设为异步。
ItemsSource="{Binding MyStuff, IsAsync=True}"
最后,我听说设置最大高度和宽度可以帮助即使超过了最大屏幕尺寸,但我个人没有注意到差别(该说法与自动大小测量有关)
MaxWidth="2560"
MaxHeight="1600"
同时,永远不要将 DataGrid
放在 ScrollViewer
中,因为这样会导致虚拟化失效。如果有帮助,请告诉我!
检查是否已将属性ScrollViewer.CanContentScroll
设置为False
。将此属性设置为false将禁用虚拟化,这将降低数据网格的性能。要获取更多澄清,请参考CanContentScroll
设置 DataGrid.RowHeight
的值,这将产生巨大的影响。
我知道这是一个非常旧的问题,但我刚刚遇到它,并且这是我端的最大差异。我的默认高度为25。
这个答案(将ScrollViewer.CanContentScroll设置为True)让我找到了正确的方向。但是我需要将其设置为false
。在进行刷新时将其设置为true
,我编写了这两个方法。
internal static void DataGridRefreshItems(DataGrid dataGridToRefresh)
{
/// Get the scrollViewer from the datagrid
ScrollViewer scrollViewer = WpfToolsGeneral.FindVisualChildren<ScrollViewer>(dataGridToRefresh).ElementAt(0);
bool savedContentScrollState = scrollViewer.CanContentScroll;
scrollViewer.CanContentScroll = true;
dataGridToRefresh.Items.Refresh();
/// Was set to false, restore it
if (!savedContentScrollState)
{
/// This method finishes even when the update of the DataGrid is not
/// finished. Therefore we use this call to perform the restore of
/// the setting after the UI work has finished.
Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => SetScrollViewerCanContentScrollFalse(scrollViewer)), DispatcherPriority.ContextIdle, null);
}
}
private static void SetScrollViewerCanContentScrollFalse(ScrollViewer scrollViewer)
{
scrollViewer.CanContentScroll = false;
}
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
在此之后,我刷新了50,000个新项目,仅需要10秒,而不是以前的2分钟,并且仅消耗2 MB的RAM,而不是4 GB。
为了测试,我禁用了所有的IValueConverter
并实现了直接绑定属性。没有转换器,DataGrid会立即刷新。所以我保留了它。
http://www.codeproject.com/Articles/34405/WPF-Data-Virtualization
我发现的一个在加载和滚动性能方面取得最佳折衷的解决方案是为所有列的绑定(而不是DataGrid的ItemsSource绑定)设置IsAsync=True
。例如:
<DataGridTextColumn Binding="{Binding Path=MaterialName, Mode=OneTime, IsAsync=True}" Header="Name" />
顺便说一句,在关闭数据网格的虚拟化时,这个解决方案效果更好。然而,即使开启了虚拟化,仍然值得一试。此外,当应用于显示图像或其他内容的DataGridTemplateColumn时,这个解决方案非常有效。