Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF工具包DataGrid滚动性能问题-为什么?_C#_Wpf_Performance_Datagrid - Fatal编程技术网

C# WPF工具包DataGrid滚动性能问题-为什么?

C# WPF工具包DataGrid滚动性能问题-为什么?,c#,wpf,performance,datagrid,C#,Wpf,Performance,Datagrid,(WPF工具包)DataGrid存在性能问题。它包含大约1.000行(只有8列),而且滚动速度非常慢和滞后。另外,包含DataGrid的窗口的初始加载需要5-10秒 我做了一些研究(使用google和StackOverflow),但除了建议开启UI虚拟化之外,我找不到任何东西。但即使在明确启用了滚动之后,滚动仍然非常缓慢 我的DataGrid绑定到ICollectionView/CollectionViewSource。它在XAML中定义如下(列是显式定义的,不是自动生成的): ... 整

(WPF工具包)DataGrid存在性能问题。它包含大约1.000行(只有8列),而且滚动速度非常慢和滞后。另外,包含DataGrid的窗口的初始加载需要5-10秒

我做了一些研究(使用google和StackOverflow),但除了建议开启UI虚拟化之外,我找不到任何东西。但即使在明确启用了滚动之后,滚动仍然非常缓慢

我的DataGrid绑定到ICollectionView/CollectionViewSource。它在XAML中定义如下(列是显式定义的,不是自动生成的):


... 
整个窗口的DataContext设置为包含DataGrid绑定到的ICollectionView的类的实例

我发现的每一篇博客或论坛帖子都在赞扬DataGrid的性能,所以我显然犯了严重的错误。因为我对WPF总体上还是一个新手,尤其是对DataGrid,所以我不知道如何改进它<有人能给我一些建议吗?你对DataGrid有什么经验?我做错了什么?

编辑:只是按照问题的建议将所有列的宽度设置为“自动”。这并没有改变糟糕的滚动性能。此外,我没有使用DataGridTemplateColumns(只是一些DataGridTextColumns和两个DataGridComboxColumns)

Edit2:我用Snoop查看我的应用程序。我所看到的表明虚拟化确实在工作(只有19行,而不是1000行)。但是每一行包含52个元素,所以这些元素加起来超过了1000个元素。这可能是个问题吗


非常感谢

您的datagrid位于哪个容器中?例如,如果将其放入scrollviewer中,datagrid将增长到显示每一行,从而有效地禁用虚拟化(在这种情况下,scrollviewer将使其看起来正常)。确保datagrid大小是有界的

这听起来确实像是一个虚拟化的东西,如果这个建议不起作用,请通过探查器运行您的应用程序,以确保虚拟化正在发生

编辑:下面是一个如何使用snoop(我猜是mole)快速查看虚拟化是否工作的示例。

您可以尝试在datagrid中逐个(或逐行)添加项目,并在每次添加后更新UI线程。 这样,用户就可以看到加载过程,而应用程序似乎什么也没做。
请参阅此方法的更详细描述

就初始加载而言,我发现有必要扩展公共API以显著改善大量的列加载—我们讨论的时间不到一秒。也就是说,我在滚动性能方面也有类似的问题,即使是500多列,滚动速度也非常慢

在我的派生数据网格中设置列:

var columns = new DataGridColumnCollection(true, dataGrid);
        for (int i = 0; i < pivotTable.DetailsColumnCount; i++)
        {
            if (!pivotTable.NullColumns.Contains(i))
            {
                columns.Add(new PivotDetailColumn(pivotTable, i));
            }
        }
        columns.ForceUpdate();

        dataGrid.Columns = columns;

        dataGrid.ItemsSource =
            Enumerable.Range(0, pivotTable.DetailsRowCount)
                .Where(i => !pivotTable.NullRows.Contains(i)) // Only non null rows
                .ToList();
var columns=newdatagridcolumncollection(true,dataGrid);
对于(int i=0;i!pivotTable.NullRows.Contains(i))//仅非空行
.ToList();
对DataGridColumnCollection的修复:

public class DataGridColumnCollection : ObservableCollection<DataGridColumn>
{
    private bool _DeferColumnChangeUpdates = false;

    public DataGridColumnCollection(bool deferColumnChangeUpdates, DataGrid dataGridOwner)
        : this(dataGridOwner)
    {
        _DeferColumnChangeUpdates = deferColumnChangeUpdates;
    }

    public DataGridColumnCollection(DataGrid dataGridOwner)
    {
        Debug.Assert(dataGridOwner != null, "We should have a valid DataGrid");

        DisplayIndexMap = new List<int>(5);
        _dataGridOwner = dataGridOwner;

        RealizedColumnsBlockListForNonVirtualizedRows = null;
        RealizedColumnsDisplayIndexBlockListForNonVirtualizedRows = null;
        RebuildRealizedColumnsBlockListForNonVirtualizedRows = true;

        RealizedColumnsBlockListForVirtualizedRows = null;
        RealizedColumnsDisplayIndexBlockListForVirtualizedRows = null;
        RebuildRealizedColumnsBlockListForVirtualizedRows = true;
    }

    #region Protected Overrides

    public void ForceUpdate()
    {
        if (DisplayIndexMapInitialized)
        {
            UpdateDisplayIndexForNewColumns(this, 0);
        }

        InvalidateHasVisibleStarColumns();
    }

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        switch (e.Action)
        {
            case NotifyCollectionChangedAction.Add:
            if (!_DeferColumnChangeUpdates)
            {
                if (DisplayIndexMapInitialized)
                {
                    UpdateDisplayIndexForNewColumns(e.NewItems, e.NewStartingIndex);
                }

                InvalidateHasVisibleStarColumns();
            }
                break;
公共类DataGridColumnCollection:ObservableCollection
{
private bool\u\columnChangeUpdates=false;
公共DataGridColumnCollection(布尔延迟ColumnChangeUpdates,DataGrid dataGridOwner)
:此(dataGridOwner)
{
_DeferColumnChangeUpdates=DeferColumnChangeUpdates;
}
公共DataGridColumnCollection(DataGrid dataGridOwner)
{
Assert(dataGridOwner!=null,“我们应该有一个有效的DataGrid”);
DisplayIndexMap=新列表(5);
_dataGridOwner=dataGridOwner;
RealizedColumnsBlockListForNonVirtualizedRows=null;
RealizedColumnsDisplayIndexBlockListForNonVirtualizedRows=null;
重建ColumnsBlockListForNonVirtualizedRows=true;
RealizedColumnsBlockListForVirtualizedRows=null;
RealizedColumnsDisplayIndexBlockListForVirtualizedRows=null;
重建虚拟化ColumnsBlockListForVirtualizedRows=true;
}
#区域保护覆盖
public void ForceUpdate()
{
如果(DisplayIndexMapInitialized)
{
UpdateDisplayIndexForNewColumns(此为0);
}
使AsVisibleStarColumns()无效;
}
CollectionChanged上的受保护覆盖无效(NotifyCollectionChangedEventArgs e)
{
开关(电动)
{
案例NotifyCollectionChangedAction。添加:
如果(!\u更新)
{
如果(DisplayIndexMapInitialized)
{
UpdateDisplayIndexForNewColumns(e.NewItems,e.NewStartingIndex);
}
使AsVisibleStarColumns()无效;
}
打破

在终于抽出时间根据最新版本的WPF构建我的应用程序后,滚动问题似乎完全消失了。因此,如果有人仍然使用DataGrid的工具包版本,只需“更新”我使用的是.NET 4.0,但仍然存在滚动性能问题。我所做的是-禁用虚拟化。我在DataGrid中将EnableRowVirtualization设置为“false”。这大大提高了滚动性能


我建议不要假设WPF提供的任何东西在所有情况下都是有用的。

DataGrid有一个附加属性,ScrollViewer.CanContentScroll,用于管理此行为。要获得平滑的scro
public class DataGridColumnCollection : ObservableCollection<DataGridColumn>
{
    private bool _DeferColumnChangeUpdates = false;

    public DataGridColumnCollection(bool deferColumnChangeUpdates, DataGrid dataGridOwner)
        : this(dataGridOwner)
    {
        _DeferColumnChangeUpdates = deferColumnChangeUpdates;
    }

    public DataGridColumnCollection(DataGrid dataGridOwner)
    {
        Debug.Assert(dataGridOwner != null, "We should have a valid DataGrid");

        DisplayIndexMap = new List<int>(5);
        _dataGridOwner = dataGridOwner;

        RealizedColumnsBlockListForNonVirtualizedRows = null;
        RealizedColumnsDisplayIndexBlockListForNonVirtualizedRows = null;
        RebuildRealizedColumnsBlockListForNonVirtualizedRows = true;

        RealizedColumnsBlockListForVirtualizedRows = null;
        RealizedColumnsDisplayIndexBlockListForVirtualizedRows = null;
        RebuildRealizedColumnsBlockListForVirtualizedRows = true;
    }

    #region Protected Overrides

    public void ForceUpdate()
    {
        if (DisplayIndexMapInitialized)
        {
            UpdateDisplayIndexForNewColumns(this, 0);
        }

        InvalidateHasVisibleStarColumns();
    }

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        switch (e.Action)
        {
            case NotifyCollectionChangedAction.Add:
            if (!_DeferColumnChangeUpdates)
            {
                if (DisplayIndexMapInitialized)
                {
                    UpdateDisplayIndexForNewColumns(e.NewItems, e.NewStartingIndex);
                }

                InvalidateHasVisibleStarColumns();
            }
                break;