CollectionView刷新上的DataGrid虚拟化

时间:2019-05-20 08:19:39

标签: wpf performance datagrid virtualization

具体来说,这是此问题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),但没有一个真正解决这个特定的问题,我们要将所有现有容器重新用于一组新项目

第二个问题是:任何人都可以解释这种方法是否可行吗?我该怎么办?

0 个答案:

没有答案