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