WinUI3 XAML ListView:批量插入和删除

问题描述 投票:0回答:1

我们正在设计一个桌面应用程序,它在某个时刻显示 10.000-100.000 个项目的列表。我们使用

ListView
绑定到
ObserableCollection
问题是,有时您需要一次操作向该集合添加或删除最多 100.000 个项目。
ObservableCollection
允许这样做的唯一方法是通过
Add
Remove
,一次执行一项。这是非常低效的并且需要很长时间,因为每个
Add
都会触发一个
NotifyCollectionChangedEvent
,从而触发很多东西。

我一直在研究对

ObservableCollection
的批量更新支持:
NotifyCollectionChangedEventArgs
有一个可以接受
IList
的构造函数,但是
ObservableCollection
现在不提供使用它的方法。显然它被添加到 corefx,但在新版本的 .NET 中又被删除了? 曾尝试将其添加到 .NET,但所有 PR 都被拒绝,因为他们仍然想考虑 API。例如。 这个.

我尝试的是将 PR 的源代码复制到我的本地项目并将其绑定到我们的

ListView
。但它似乎不起作用:当我使用批量插入添加项目时,视图不会更新:这是因为我使用了
new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, itemsAdded, startingIndex)

当我想要批量删除集合中不同位置的项目并通过

new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, itemsRemoved)
时,情况会变得更糟:我收到带有无效索引的 WinRT 异常,导致应用程序崩溃。可能是因为构造函数的重载将
-1
作为起始索引而引起。

看起来

ListView
就是不支持这个,还是不支持?我一直在四处寻找有关该主题的任何信息,但似乎找不到。由于微软几乎不支持 WinUI-3(相信我,过去几年我尝试在他们的 github 上报告几个错误,但很少得到答案),我不指望从他们那里得到任何帮助,除了:“没有计划”或“积压”。我也无法在堆栈溢出上找到任何尝试过此操作的人。我确实找到了一篇(旧的)文章,但那个人得出了相同的结论:ListView 目前不支持它。

有人尝试过并找到解决方案吗?有人知道尝试过这个的人吗?有人在 WinUI-3 上工作吗?

附注我一直在考虑发送一个像

here
建议的NotifyCollectionChangedAction.Reset,但这对应用程序的其余部分不起作用:它不提供带有添加和删除项目的
OnCollectionChanged
事件处理程序,所以很多东西,比如取消订阅已删除项目中的事件处理程序,或解除父级的附加,都不会被触发:这会导致内存泄漏(因为已删除的项目无法被GCed),甚至例外(因为删除的项目仍在处理事件)。

c# listview winrt-xaml observablecollection winui-3
1个回答
0
投票

GitHub 上有一个关于 AddRange

讨论
ObservableCollection
,但不幸的是,暂时没有任何进展。

您可以尝试的是自己添加

AddRage
支持。像这样的东西:

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;

namespace ObservableCollectionExSampleApp;

public class ObservableCollectionEx<T> : ObservableCollection<T>
{
    private readonly static System.ComponentModel.PropertyChangedEventArgs ItemsINPC = new System.ComponentModel.PropertyChangedEventArgs("Item[]");
    private readonly static System.ComponentModel.PropertyChangedEventArgs CountINPC = new System.ComponentModel.PropertyChangedEventArgs(nameof(Count));

    public void AddRange(IEnumerable<T> collection)
    {
        CheckReentrancy();

        int count = 0;
        foreach (var item in collection)
        {
            count++;
            base.Items.Add(item); // Editing this protected list won't raise events
        }

        if(count > 0)
        {
            OnPropertyChanged(ItemsINPC);
            OnPropertyChanged(CountINPC);
            if (count > 1) // Multi-item change
            {
                OnCollectionChanged(
                    new NotifyCollectionChangedEventArgs(
                        action: NotifyCollectionChangedAction.Add,
                        changedItems: collection as System.Collections.IList ?? collection.ToList(),
                        startingIndex: Count - count));
            }
            else // count == 1 - single-item change
            {
                OnCollectionChanged(
                    new NotifyCollectionChangedEventArgs(
                        action: NotifyCollectionChangedAction.Add,
                        changedItem: collection.First(),
                        index: Count - 1));
            }
        }
    }
}

如果您想观看它的实际效果,请在我的 YouTube 频道上观看视频

© www.soinside.com 2019 - 2024. All rights reserved.