BindingList的应用与改进

news/2025/9/29 12:29:16/文章来源:https://www.cnblogs.com/BettaFish/p/19118540

在编写UI的过程中,我们通常使用ObservableCollection来监听列表的变化。然而,ObservableCollection只能在添加/移动/移除元素时通知界面,这意味着元素内部更改时,ObservableCollection是无法通知的

如果需要监听列表元素内部的更改,可以使用System.ComponentModel.BindingList

BindingList作用是将列表中元素内部的更改"转发"到外部。由于需要监听每个元素内部的属性更改,BindingList中的所有元素必须实现INotifyPropertyChanged

使用

现有Item类如下:

public partial class Item : ObservableObject
{[ObservableProperty]public partial string? Name { get; set; }[ObservableProperty]public partial int Value { get; set; }
}

Items列表中存储多个Item,如果需要计算列表中所有Value的总和,我们就可以使用BindingList

[ObservableProperty]
public partial BindingList<Item> Items { get; set; } = [];public int TotalValue => Items.Sum(i => i.Value);

然而修改Items中元素后,TotalValue并没有被更新,这是为什么呢?

事实上,BindingList并不能主动通知TotalValue属性。但它提供了十分强大的ListChanged事件,它在添加/删除元素或元素内部更改时均会触发(会根据更改类型会在ListChangedEventArgs中提供不同的ListChangedType),这是ObservableCollection无法做到的

public enum ListChangedType
{Reset,// 清空列表或列表行为变化(AllowNew/AllowEdit/AllowRemove发生改变)ItemAdded,// 添加元素ItemDeleted// 删除元素ItemMoved,// 移动元素ItemChanged,// 元素内部属性更改// BindingList未使用下面三个成员PropertyDescriptorAdded,PropertyDescriptorDeleted,PropertyDescriptorChanged
}

我们可以订阅此事件并完成对TotalValue的通知

public MainViewModel()
{// 此处OnPropertyChanged为MVVM工具包中ObservableObject的代码,可替换为PropertyChanged?.Invoke()Items.ListChanged += (s, e) => OnPropertyChanged(nameof(TotalValue));
}

现在,TotalValue在元素更改时就会重新计算,可直接用于单向绑定

缺陷以及解决方案

在Avalonia测试时,会发现一个很奇怪的现象:如果将BindingList作为列表控件的ItemSource使用,在添加/删除元素时,尽管TotalValue会被正确更新,但列表没有任何变化。同时,Count属性也没有得到正确通知

video_01

查看Avalonia中ItemSourceView的代码后发现,它只通过INotifyCollectionChangedCollectionChanged事件来刷新列表,而BindingList并未实现和INotifyCollectionChanged接口,这也就是为什么BindingList无法正确通知UI

同时,BindingList也未实现INotifyPropertyChanged,造成Count属性未更新

WinUI 3中,列表未刷新但Count属性能更新,可能是不同UI框架实现的问题

private protected void SetSource(IEnumerable source)
{...if (_listening && _source is INotifyCollectionChanged inccNew)CollectionChangedEventManager.Instance.AddListener(inccNew, this);
}

现在解决方法就很简单了:继承BindingList,实现这两个接口并在添加/移除元素进行通知即可。

完整代码如下:

public class ObservableBindingList<T> : BindingList<T>, INotifyCollectionChanged, INotifyPropertyChanged
{public event NotifyCollectionChangedEventHandler? CollectionChanged;public event PropertyChangedEventHandler? PropertyChanged;protected override void InsertItem(int index, T item){base.InsertItem(index, item);CollectionChanged?.Invoke(index, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index));PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Count)));PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Item[]"));// 通知集合索引器的变化(通过索引器绑定列表第几项时使用)}protected override void RemoveItem(int index){var item = this[index];base.RemoveItem(index);CollectionChanged?.Invoke(index, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index));PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Count)));PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Item[]"));}
}

使用:

[ObservableProperty]
public partial ObservableBindingList<Item> Items { get; set; } = [];public int TotalValue => Items.Sum(i => i.Value);public MainViewModel()
{   // 此处OnPropertyChanged为MVVM工具包中ObservableObject的代码,可替换为PropertyChanged?.Invoke()Items.ListChanged += (s, e) => OnPropertyChanged(nameof(TotalValue));
}

现在,增删(移动)元素/修改元素内部的值均可正确通知界面

video_02

示例代码

BindingListTest

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/921823.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

谷歌 SEO 新词 xx animate 等实操教程

如上图,最近 AI 圈又冒出新词:wan animate 等,你们都看到了吗? 今天聊聊 SEO 新词这个"淘金"生意,为什么有些词能做,有些词碰都不能碰。 一、wan animate vs veo3:天壤之别如上图:❌ veo3:打死别碰…

US$248 Xhorse VVDI2 BMW FEM/BDC + Copy 48 Transponder (96 Bit) + MQB Authorization

Xhorse VVDI2 BMW FEM/BDC + Copy 48 Transponder (96 Bit) + MQB Authorization Xhorse Promotion for loyal customers till Christmas!!! This is Authorization Only! No Need Shipping, please pass us serial nu…

完整教程:【读书笔记】架构整洁之道 P6 实现细节

完整教程:【读书笔记】架构整洁之道 P6 实现细节pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas",…

Print Conductor打印软件安装教程!一款非常好用的批量打印软件!支持PDF、Word、Excel、图片等

软件介绍 Print Conductor是一款由国外开发者制作的批量打印软件,支持PDF、Word、Excel、图片等多种格式文件的快速打印。它通过拖拽文件到软件界面即可实现批量打印,无需逐个打开文档,特别适合需要处理大量打印任务…

Python 面向对象编程基础:类与对象初体验

面向对象编程(OOP)是一种编程范式,它通过对象和类的概念来组织代码,使程序更加模块化、可维护和可扩展。Python 是一种支持面向对象编程的语言,提供了强大的类和对象机制。今天,就让我们一起学习 Python 中的面向…

Drools 7.0基础环境搭建

Drools 7.0基础环境搭建一、环境概述 Drools 7.0当前最新的是7.74.1 Final,Drools 8.0不兼容JDK8了(你发任你发,我用java8),7.73.0.Final这个兼容最稳定所以选这个 JDK:openjdk version "1.8.0_452" Mav…

o2o网站大全asp.net网站

系列文章目录 本系列课程主要针对于Ehcache缓存框架功能的开发实践全流程技术指南&#xff01; 第一节&#xff1a;Ehcache缓存框架的基本概念和简介第二节&#xff1a;Ehcache缓存框架的配置分析和说明第三节&#xff1a;Ehcache缓存框架的缓存方式的探索第四节&#xff1a;E…

邯郸市网络建站aspx网站开发 案例

前段时间到印度的马德拉斯市出差了3个月(4月到6月)&#xff0c;今天终于有时间将自己的出差心得和见闻记录下来&#xff0c;可能以后就会忘记。下午16:00时在深圳坐车到香港机场&#xff0c;上车没多久会让填一个入境香港的单子&#xff0c;然后是过海关&#xff0c;过海关时会…

自动驾驶中的传感器技术54——USS(0) - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

网站整体规划建设银行网站半天进不去

XSS 概念&#xff1a;由于web应用程序对用户的输入过滤不严&#xff0c;通过html注入篡改网页&#xff0c;插入恶意脚本&#xff0c;从而在用户浏览网页时&#xff0c;控制用户浏览器的一种攻击。XSS类型&#xff1a;Reflected(反射型)&#xff1a;只是简单的把用户输入的数据反…

基于微信小程序的旅游景点体系【2026最新】

基于微信小程序的旅游景点体系【2026最新】pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "…

US$64 NEC KEY II Adapter for CKM100 and Digimaster III

NEC KEY II Adapter for CKM100 and Digimaster IIIPackage List:1set x NEC KEY II Adapter for CKM100 and Digimaster III Pictures of NEC KEY II Adapter for CKM100 and Digimaster IIINEC KEY II Adapter for C…

反电动势法控制BLDC电机的原理图分析

1.概述 无霍尔的BLDC控制方案与有霍尔BLDC的基本原理相似,都是用所谓“六步换向法”,根据转子当前的位置,按照一定的顺序给定子绕组通电使BLDC电机转动。所不同的是无霍尔BLDC不需要霍尔效应传感器,通过检测定子绕…

网站建设属于网络设计解决:如何将初步规划中的各个子系统从内部

一、 提示 需要重启服务器 操作之前备份 k8s 中所有资源的 yaml 文件 如下是备份脚本&#xff0c;仅供参考 # 创建备份目录 test -d $3 || mkdir $3 # $1 命名空间 # $2 资源名称&#xff1a; sts deploy configMap svc 等 # $3 资源备份存放的目录名称for app in kubec…

完整教程:Altium Designer(AD)设计规则检查设置

完整教程:Altium Designer(AD)设计规则检查设置pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", …

理查德西尔斯做的网站dw个人网页制作教程学生

1、Dubbo的基本架构是怎样的&#xff1f; Dubbo是一个高性能的Java RPC&#xff08;远程过程调用&#xff09;框架&#xff0c;它的基本架构主要由以下几个核心组件构成&#xff1a; Provider&#xff08;服务提供方&#xff09;&#xff1a; Provider是指暴露服务的服务提供者…

企业物联网安全必须优先考虑的5个不可否认的理由

本文探讨了企业物联网安全面临的五大挑战,包括设备数量激增带来的安全风险、安全团队能力不足、行业快速发展带来的隐私问题、信息共享的重要性以及海量设备管理的复杂性。文章为企业信息安全实践者提供了重要的安全建…

网站开发是叫系统吗怎么做返利网之类的网站

简介&#xff1a;传统MySQL基于binlog复制的主备架构有它的局限性&#xff0c;包括存储空间有限&#xff0c;备份恢复慢&#xff0c;主备复制延迟等问题&#xff0c;为了解决用户对于云上RDS(X-Engine)大容量存储&#xff0c;以及弹性伸缩的诉求&#xff0c;PolarDB推出了历史库…

PSM敏捷认证自考学习指南

PSM敏捷认证自考学习指南来分享我自考psm认证课程心得吧,希望可以帮到你。 第一,关于复习 (Scrum指南) 必读材料,读5遍以上,别问为什么,题目基本都是围绕这个的。 第二,关于考试 考试题型有,选择题,单选,多…

(基于江协科技)51单片机入门:3.静态数码管 - 实践

(基于江协科技)51单片机入门:3.静态数码管 - 实践2025-09-29 12:02 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; displ…