<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      BindingList的應用與改進

      在編寫UI的過程中,我們通常使用ObservableCollection來監(jiān)聽列表的變化。然而,ObservableCollection只能在添加/移動/移除元素時通知界面,這意味著元素內(nèi)部更改時,ObservableCollection是無法通知的

      如果需要監(jiān)聽列表元素內(nèi)部的更改,可以使用System.ComponentModel.BindingList

      BindingList作用是將列表中元素內(nèi)部的更改"轉(zhuǎn)發(fā)"到外部。由于需要監(jiān)聽每個元素內(nèi)部的屬性更改,BindingList中的所有元素必須實現(xiàn)INotifyPropertyChanged

      使用

      現(xiàn)有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事件,它在添加/刪除元素或元素內(nèi)部更改時均會觸發(fā)(會根據(jù)更改類型會在ListChangedEventArgs中提供不同的ListChangedType),這是ObservableCollection無法做到的

      public enum ListChangedType
      {
      	Reset,// 清空列表或列表行為變化(AllowNew/AllowEdit/AllowRemove發(fā)生改變)
      	ItemAdded,// 添加元素
      	ItemDeleted// 刪除元素
      	ItemMoved,// 移動元素
      	ItemChanged,// 元素內(nèi)部屬性更改
      
      	// BindingList未使用下面三個成員
      	PropertyDescriptorAdded,
      	PropertyDescriptorDeleted,
      	PropertyDescriptorChanged
      }
      

      我們可以訂閱此事件并完成對TotalValue的通知

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

      現(xiàn)在,TotalValue在元素更改時就會重新計算,可直接用于單向綁定

      缺陷以及解決方案

      在Avalonia測試時,會發(fā)現(xiàn)一個很奇怪的現(xiàn)象:如果將BindingList作為列表控件的ItemSource使用,在添加/刪除元素時,盡管TotalValue會被正確更新,但列表沒有任何變化。同時,Count屬性也沒有得到正確通知

      video_01

      查看Avalonia中ItemSourceView的代碼后發(fā)現(xiàn),它只通過INotifyCollectionChangedCollectionChanged事件來刷新列表,而BindingList并未實現(xiàn)和INotifyCollectionChanged接口,這也就是為什么BindingList無法正確通知UI

      同時,BindingList也未實現(xiàn)INotifyPropertyChanged,造成Count屬性未更新

      WinUI 3中,列表未刷新但Count屬性能更新,可能是不同UI框架實現(xiàn)的問題

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

      現(xiàn)在解決方法就很簡單了:繼承BindingList,實現(xiàn)這兩個接口并在添加/移除元素進行通知即可。

      完整代碼如下:

      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));
      }
      

      現(xiàn)在,增刪(移動)元素/修改元素內(nèi)部的值均可正確通知界面

      video_02

      示例代碼

      BindingListTest

      posted @ 2025-09-29 12:26  zxbmmmmmmmmm  閱讀(105)  評論(1)    收藏  舉報
      主站蜘蛛池模板: 国产成人精品久久一区二区| 亚洲日韩久久综合中文字幕| 成人做爰69片免费看网站野花| 成人小说亚洲一区二区三区| 国产成人亚洲欧美二区综合| 五月婷婷开心中文字幕| 息烽县| 国产极品精品自在线不卡| 男人的天堂av社区在线| 国产成人欧美综合在线影院| 亚洲顶级裸体av片| 亚洲国产成人综合精品| 啪啪av一区二区三区| AV人摸人人人澡人人超碰| 激情啪啪啪一区二区三区| 91久久国产成人免费观看| 激情97综合亚洲色婷婷五| 东方四虎av在线观看| 汨罗市| 国产美女69视频免费观看| 国产精品午夜福利资源| 无码中文字幕乱码一区| 4480yy亚洲午夜私人影院剧情| 2021国产成人精品久久| 精品国产免费第一区二区三区| 亚洲国产欧美日韩欧美特级| 欧美日韩性高爱潮视频| 国产精品国产高清国产av| 国产高清自产拍av在线| 污污内射在线观看一区二区少妇| 四虎影视一区二区精品| 国产精品一区二区久久岳| 国产办公室秘书无码精品99| 长腿校花无力呻吟娇喘| 红桃视频成人传媒| 视频一区视频二区视频三| 韩国av无码| 超碰伊人久久大香线蕉综合| 久久精产国品一二三产品| 熟女性饥渴一区二区三区| 日韩精品无码一区二区三区视频|