MAUI CollectionView 绑定ItemSource后增删元素时会更新UI,修改ItemSource中元素的某个属性时不会更新UI

255 阅读2分钟

背景

先简单介绍下背景,由于有国外客户使用MAUI进行Android开发,我们提供的SDK也需要适配MAUI平台,所以我的老大让我研究在MAUI平台开发Android应用Demo以及使用我们的SDK。

我们做应用开发时一般使用列表进行数据展示时,展示的数据内容一般包含有1个或多个信息。当其中一条数据的某个信息发生变化时,我们需要更新到UI上信息展示。这种情况下我们一般是找到数据发生改变的这条数据,将数据变化通知到UI去进行更新,但是MAUI的CollectionView仅支持增删的方式进行UI列表更新:

使用数据填充 CollectionView - .NET MAUI | Microsoft Learn

使用数据填充CollectionView.png

原先的解决方案

我原先的解决方案比较暴力,而且在体验上并不好。 我是先找到要更新的元素,获取它在数据源中的下标index,先删除再添加新的方式,下面给出一个简单的例子,仅做参考:

    public ObservableCollection<DeviceModel> DeviceModels { get; private set; }
            ...
            DeviceModels.RemoveAt(index);
            DeviceModels.Insert(index, deviceModel);

这样会带来两个问题:一个是因为进行Remove和Insert操作都会发送属性更改通知,所以会有两次UI刷新,这样会使得列表抖动,体验上并不友好;第二个是因为多了的UI刷新也会影响到性能。

新的解决方案

将Model设置为可观察的就可解决这个问题,具体的解决方案是让Model实现INotifyPropertyChanged接口,例如:

    public class DeviceModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler? PropertyChanged;

        private string _address;
        private string _name;

        public string Address 
        {
            get { return _address; }
            set 
            {
                _address = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Address)));
            } 
        }

        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Name)));
            }
        }



        public DeviceModel()
        {

        }
    }

这样的话就可以直接找到对应的要更新数据的元素更新其属性即可:

            DeviceModels[index].Name = deviceModel.Name;

曾尝试的其它方案

我老大给我推了一个VirtualListView,让我研究一下可不可以解决这个问题。由于没能跑动VirtualListView库提供的demo以及提供的Readme介绍有限,我只能硬看代码。我研究了几天发现并不能解决,而且还发现使用VirtualListView的话进行数据更新得在UI线程进行,这就意味着如果在子线程中获取数据后得切换到UI线程中进行数据的添加,删除等,所以后续我还是放弃了使用VirtualListView。如果是我研究有问题,欢迎评论探讨。下面贴出VirtualListView的仓库地址: Maui.VirtualListView

参考

Maui开发 CollectionView 绑定后增删元素时UI会更新,修改属性时不会更新。-lfobb_dubo-ChinaUnix博客