ホームページ >バックエンド開発 >C#.Net チュートリアル >WPF データ バインディングのコア テクノロジ

WPF データ バインディングのコア テクノロジ

零下一度
零下一度オリジナル
2017-06-23 16:04:092242ブラウズ

WPF の中核となる技術的利点の 1 つはデータ バインディングです。データ バインディングは、データ操作を通じてインターフェイスを更新できます。

データ バインディングに最もよく使用される 2 つのクラスは、ObservableCollection8742468051c85b06f0a0af9e3e506b5c と Dictionary6e081e925c6a2fa99508161fe1ff33ed です。

ObservableCollection は動的データ コレクションを表します。このコレクションは、アイテムが追加されたとき、アイテムが削除されたとき、またはリスト全体が更新されたときに通知を提供します。コレクション データを更新することでインターフェイスの表示を更新できます。

Dictionary 辞書クラスは検索やデータ操作のパフォーマンスが非常に悪いため、一部の設定項目のコレクションはこれを使用して保存されます。

そこで、ObservableCollectionとDictionaryを組み合わせたクラスがないか皆で考え、ObservableDictionaryクラスが形成されました。

ObservableDictionary クラスのバージョンはインターネット上にたくさんあります。私の知る限り、最も古くて古典的なものは、Dr.WPF の辞書への ItemsControl です (私が間違っている場合)。 、私は無知です))。

今日提供するバージョンは、インターネット上の他のバージョンや 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

よく見ると、ここで継承されたインターフェイスは、Dictionaryb6842da76bed01162354d37c4f2d3464 によって継承されたインターフェイスとほとんど同じであることがわかりますが、次の点が異なります。 INotifyCollectionChanged、INotifyPropertyChanged

したがって、今日私が提供するバージョンは、Dictionary と INotifyCollectionChanged、INotifyPropertyChanged を直接継承しています。

テストしましたが、バグはなく、パフォーマンスは優れています。コードは以下のとおりです:

    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 バージョンを使用して変更できます。 !

以上がWPF データ バインディングのコア テクノロジの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。