WPF字典集合類ObservableDictionary

来源:http://www.cnblogs.com/lisweden/archive/2017/06/14/7009600.html
-Advertisement-
Play Games

WPF最核心的技術優勢之一就是數據綁定。數據綁定,可以通過對數據的操作來更新界面。 數據綁定最經常用到的是ObservableCollection<T> 和 Dictionary<T, T> 這兩個類。 ObservableCollection表示一個動態數據集合,在添加項、移除項或刷新整個列表時, ...


WPF最核心的技術優勢之一就是數據綁定。數據綁定,可以通過對數據的操作來更新界面。

數據綁定最經常用到的是ObservableCollection<T> 和 Dictionary<T, T> 這兩個類。

ObservableCollection表示一個動態數據集合,在添加項、移除項或刷新整個列表時,此集合將提供通知,可以通過更新集合數據來更新界面顯示。

Dictionary字典類,檢索和數據操作性能極性,所以一些配置項的集合都使用它來保存。

因此,大家就想到的,有沒有ObservableCollection和Dictionary相結合的類呢,於是就形成的ObservableDictionary類。

網上有很多版本的ObservableDictionary類,據我瞭解到的,最早且最經典的就是Dr.WPF裡面的ItemsControl to a dictionary,其他的版本多數是參考這個來修改的(不對的那就是我孤陋寡聞了)。

今天我提供的這個版本,也是參考了網上的其他版本和Dr.WPF里的。

Dr.WPF里的定義是這樣的:

public class ObservableDictionary <TKey, TValue> :
        IDictionary<TKey, TValue>,
        ICollection<KeyValuePair<TKey, TValue>>,
        IEnumerable<KeyValuePair<TKey, TValue>>,
        IDictionary,
        ICollection,
        IEnumerable,
        ISerializable,
        IDeserializationCallback,
        INotifyCollectionChanged,
        INotifyPropertyChanged

大家細心點就會發現,這裡繼承的介面和Dictionary<TKey, TValue>所繼承的大部分相同,只是多了INotifyCollectionChanged, INotifyPropertyChanged

於是,今天我提供的版本,就直接繼承於Dictionary<TKey, TValue>和INotifyCollectionChanged, INotifyPropertyChanged。

本人測試過,無BUG,性能也極佳,下麵上代碼:

    public class ObservableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, INotifyCollectionChanged, INotifyPropertyChanged
    {
        public ObservableDictionary()
            : base()
        { }

        private int _index;
        public event NotifyCollectionChangedEventHandler CollectionChanged;
        public event PropertyChangedEventHandler PropertyChanged;

        public new KeyCollection Keys
        {
            get { return base.Keys; }
        }

        public new ValueCollection Values
        {
            get { return base.Values; }
        }

        public new int Count 
        {
            get { return base.Count; }
        }

        public new TValue this[TKey key]
        {
            get { return this.GetValue(key); }
            set { this.SetValue(key, value); }
        }

        public TValue this[int index]
        {
            get { return this.GetIndexValue(index); }
            set { this.SetIndexValue(index, value); }
        }

        public new void Add(TKey key, TValue value)
        {
            base.Add(key, value);
            this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, this.FindPair(key), _index));
            OnPropertyChanged("Keys");
            OnPropertyChanged("Values");
            OnPropertyChanged("Count");
        }

        public new void Clear()
        {
            base.Clear();
            this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
            OnPropertyChanged("Keys");
            OnPropertyChanged("Values");
            OnPropertyChanged("Count");
        }

        public new bool Remove(TKey key)
        {
            var pair = this.FindPair(key);
            if (base.Remove(key))
            {
                this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, pair, _index));
                OnPropertyChanged("Keys");
                OnPropertyChanged("Values");
                OnPropertyChanged("Count");
                return true;
            }
            return false;
        }

        protected void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
        {
            if (this.CollectionChanged != null)
            {
                this.CollectionChanged(this, e);
            }
        }

        protected void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #region private方法
        private TValue GetIndexValue(int index)
        {
            for (int i = 0; i < this.Count; i++)
            {
                if (i == index)
                {
                    var pair = this.ElementAt(i);
                    return pair.Value;
                }
            }

            return default(TValue);
        }

        private void SetIndexValue(int index, TValue value)
        {
            try
            {
                var pair = this.ElementAtOrDefault(index);
                SetValue(pair.Key, value);                
            }
            catch (Exception)
            {
                
            }
        }

        private TValue GetValue(TKey key)
        {
            if (base.ContainsKey(key))
            {
                return base[key];
            }
            else
            {
                return default(TValue);
            }
        }

        private void SetValue(TKey key, TValue value)
        {
            if (base.ContainsKey(key))
            {
                var pair = this.FindPair(key);
                int index = _index;
                base[key] = value;
                var newpair = this.FindPair(key);
                this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, newpair, pair, index));
                OnPropertyChanged("Values");
                OnPropertyChanged("Item[]");
            }
            else
            {
                this.Add(key, value);
            }
        }

        private KeyValuePair<TKey, TValue> FindPair(TKey key)
        {
            _index = 0;
            foreach (var item in this)
            {
                if (item.Key.Equals(key))
                {
                    return item;
                }
                _index++;
            }
            return default(KeyValuePair<TKey, TValue>);
        }

        private int IndexOf(TKey key)
        {
            int index = 0;
            foreach (var item in this)
            {
                if (item.Key.Equals(key))
                {
                    return index;
                }
                index++;

            }
            return -1;
        }

        #endregion

    }

擴展方面,大家可以以Dr.WPF版本來修改,那個更加有技術含量和可擴展性更強!

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1 背景概述 在大多數的開發項目中,尤其是集成項目,都會有涉及到數據分析部分的工作,數據分析多數是各種圖表的展現和交互(所謂數據可視化),數據分析的展現速度直接影響著用戶的體驗,而且絕大多數管理系統(MES、PDM/PLM、ERP、SCM、OA、HR等等)的數據都存儲在資料庫中,資料庫相關的性能優化 ...
  • 大數據時代來臨,信息化建設對企業的生存發展的重要作用越發凸顯,如何跨越信息孤島,打破部門之間的聯動壁壘,實現以大數據分析與應用為前提,成為企業提高市場競爭能力和應變能力成為關鍵所在。企業迫求“實用快上” 信息孤島無可迴避博為軟體與企業合作時發現,幾乎所有企業都會因為信息化建設缺乏總體規劃,往往以實現 ...
  • Nginx配置文件結構 nginx配置文件由指令(directive)組成,指令分為兩種形式,簡單指令和區塊指令。 一條簡單指令由指令名、參數和結尾的分號(;)組成,例如: listen 80 backlog 4096; ,其中“listen”是指令名,“80”、“backlog”、“4096”都是 ...
  • 1:準備一個最少16G的U盤在這個https://sourceforge.net/projects/usbwriter/files/latest/download網址下載並製作U盤引導程式。 2:去官網下載CentOS的安裝程式,下載地址為http://ftp.sjtu.edu.cn/centos/ ...
  • 背景前面把樹莓派裝上了CentOS 7,趁著國慶放假回來趕緊把服務端環境搭起來,為了方便就準備用一鍵lnmp快速部署一個,結果死活安裝不成功... ...
  • Linux 常用的壓縮命令有 gzip 和 zip,兩種壓縮包的結尾不同:zip 壓縮的後文件是 *.zip ,而 gzip 壓縮後的文件 *.gz 相應的解壓縮命令則是 gunzip 和 unzip gzip 命令: # gzip test.txt 它會將文件壓縮為文件 test.txt.gz,原 ...
  • 1.載入BIOS 當你打開電腦電源,電腦首先會載入BIOS信息,BIOS信息是如此的重要,以至於電腦必須在最開始找到它。這是因為BIOS中包含了CPU的相關信息、設備啟動順序信息、硬碟信息、記憶體信息、時鐘信息、pnp等等。在此之後,電腦信息就有譜了,知道要去找哪個硬體設備。 2.讀取MBR ...
  • 在linux系統中,為了避免主機時間因為長時間運行下所導致的時間偏差,進行時間同步(synchronize)的工作是非常必要的。linux系統下,一般使用ntp服務來同步不同機器的時間。NTP是網路時間協議(Network Time Protocol)的簡稱,就是通過網路協議使電腦之間的時間同步化 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...