具体来说,这是此问题datagrid filter performance的后续,但是与stackoverflow上的WPF datagrid性能有关的更多类似问题。
经过大量分析并通过.NET源代码,我意识到许多性能问题,例如过滤和排序,仅沸腾了一个问题: acollectionView.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(的在线资源,但是没有一个真正地址这个特定的问题,我们要重用所有现有容器作为新项目。
因此,次要问题是:有人可以解释是否可能发生这种方法?我该怎么做?
我从不直接从CollectionView使用RESET,因为CollectionView源上的Methode会这样做。为了我的需求,这种iList已被修改。我做的就像保罗·麦克林(Paul McClean(在这里解释的。
在此课程中,您可以通知OnCollectionChanged,以告知CollectionView。Sondergard解释了什么NotifyCollectionChangedAction.Reset做。但请通知CollectionChangedAction.Replace继续运行对项目的回收。
也许我的研究有帮助。