39

在我的.NET 3.5 WPF应用程序中,我有一个WPF DataGrid将填充 500 列和 50 行的内容。应用程序的性能在滚动时非常差,或者当我这样做时DataGrid.Items.Refresh()或在选择行时。

实际上 App 大约需要 20 秒来更新布局。Layout_Updated()事件将在 20 秒后触发。

如果我将列减少到 50 或更少,应用程序将非常敏感。根据我的发现,性能与列数直接相关。

如何提高DataGrid性能?

4

5 回答 5

90

您可以打开几个选项来帮助您处理DataGrid对象

EnableColumnVirtualization = true
EnableRowVirtualization = true

这两个是我认为可能有帮助的主要内容。接下来尝试使您的绑定异步

ItemsSource="{Binding MyStuff, IsAsync=True}"

最后,我听说设置最大高度和宽度会有所帮助,即使它高于最大屏幕尺寸,但我自己并没有注意到差异(声称与自动尺寸测量有关)

MaxWidth="2560"
MaxHeight="1600"

也永远不要把 a 放在 aDataGridScrollViewer,因为你基本上会失去虚拟化。让我知道这是否有帮助!

于 2012-12-07T14:32:35.170 回答
10

检查您是否ScrollViewer.CanContentScroll设置了属性False。将此属性设置为 false 会以某种方式禁用虚拟化,从而降低数据网格的性能。有关更多说明,请参阅此CanContentScroll

于 2016-12-12T06:04:15.860 回答
2

设置DataGrid.RowHeight值,这将产生巨大的影响。

我知道这是一个非常古老的问题,但我只是遇到了它,这是我最大的不同。我的默认高度是 25。

于 2020-06-11T17:04:22.867 回答
1

第 1 步:从 2 分钟到 10 秒

这个答案(Set ScrollViewer.CanContentScroll to 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;
}

这是我用来获取 VisualChildren 的方法:

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。

第 2 步:从 10 秒到 0.5 秒

为了测试,我禁用了我IValueConverter直接绑定的所有和实现的属性。如果没有转换器,DataGrid 会立即刷新。所以我离开了它。

于 2021-01-24T16:06:21.273 回答
0

也许试试这个而不是一次加载所有 50 行

http://www.codeproject.com/Articles/34405/WPF-Data-Virtualization

于 2012-12-07T14:06:06.957 回答