提高WPF DataGrid的性能

时间:2012-12-07 14:00:50

标签: c# wpf datagrid wpfdatagrid

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

实际上应用程序将花费大约20秒来更新布局。 Layout_Updated()事件将在20秒后触发。

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

如何改善DataGrid效果?

5 个答案:

答案 0 :(得分:67)

您可以使用一些选项来帮助您使用 DataGrid 对象

EnableColumnVirtualization = true
EnableRowVirtualization = true

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

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

最后,我听说设置最大高度和宽度可以帮助,即使它超过最大屏幕尺寸,但我自己没有发现差异(声称与自动尺寸测量有关)

MaxWidth="2560"
MaxHeight="1600"

也永远不会将DataGrid放在ScrollViewer中,因为您将基本上失去虚拟化。如果这有帮助,请告诉我!

答案 1 :(得分:4)

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

答案 2 :(得分:1)

设置{ "url": "https://example_site.in/new/blogs", "server": { "port": 2368, "host": "127.0.0.1" }, "database": { "client": "mysql", "connection": { "host": "localhost", "user": "admin", "password": "<DB Pass>", "database": "<DB name>" } }, "mail": { "transport": "SMTP", "options": { "host": "smtp.zoho.com", "port": 587, "secureConnection": false, "auth": { "user": "<email>", "pass": "<pass>" } } }, "logging": { "transports": [ "file", "stdout" ] }, "process": "systemd", "paths": { "contentPath": "/var/www/html/example_blogs/content" } } 值,这将带来很大的不同。

我知道这是一个非常老的问题,但是我碰到了这个问题,这是我最大的不同。我的默认身高是25。

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

第 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 instad 之前的 4 GB。

第 2 步:10 秒到 0.5 秒

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