具体来说,这是此问题DataGrid filter performance的后续内容,但是还有更多类似的问题与StackOverflow上的WPF DataGrid性能有关。
经过大量分析并遍历.NET源代码,我意识到许多性能问题(例如过滤和排序)仅归结为一个问题: A CollectionView.Reset事件不会回收容器(就像滚动一样)。
我的意思是,不是为现有行分配新的数据上下文,而是从可视树中删除所有行,生成并添加新行,并执行布局周期(度量和排列)。
主要问题是:有人成功解决了这个问题吗?例如。通过手动操作ItemContainerGenerator还是创建自己的DataGridRowsPresenter版本?
所以这是我到目前为止的要旨。
public class CollectionViewEx
{
public event EventHandler Refresh;
public override void Refresh()
{
Refresh?.Invoke(this, EventArgs.Empty);
}
}
public class DataGridEx : DataGrid
{
protected override OnItemsSourceChanged(IEnumerable oldSource, IEnumerable newSource)
{
if (newSource is CollectionViewEx cvx)
{
cvx.Refresh += (o,a) => OnViewRefreshing;
}
}
private void OnViewRefreshing()
{
RowsPresenter.Refresh();
}
}
public class DataGridRowsPresenterEx : DataGridRowsPresenter
{
public void Refresh()
{
var generator = (IRecyclingItemContainerGenerator)ItemContainerGenerator;
generator.Recycle(new GeneratorPosition(0, 0), ???);
RemoveInternalChildRange(0, VisualChildrenCount);
using (generator.StartAt(new GeneratorPosition(-1, 0), GeneratorDirection.Forward))
{
UIElement child;
bool isNewlyRealised = false;
while ((child = generator.GenerateNext(out isNewlyRealised) as UIElement) != null)
{
AddInternalChild(child);
generator.PrepareItemContainer(child);
}
}
}
}
但是结果非常令人困惑-显然是因为我不太了解如何使用ICG。
我浏览了.net源代码以查看其实现(添加/删除/替换项目时),还找到了一些在线资源,以了解如何创建新的虚拟化面板(例如virtualizingwrappanel),但没有一个真正解决这个特定的问题,我们要将所有现有容器重新用于一组新项目。
第二个问题是:任何人都可以解释这种方法是否可行吗?我该怎么办?