DataBinding/WPF C#的通用可观察字典类

Jos*_*nel 25 c# data-binding wpf

我正在尝试在C#中为WPF DataBinding创建一个Observable Dictionary Class.我在这里找到了Andy的一个很好的例子:双向数据绑定在WPF中的字典

据此,我试图将代码更改为以下内容:

class ObservableDictionary : ViewModelBase
{
    public ObservableDictionary(Dictionary<TKey, TValue> dictionary)
    {
        _data = dictionary;
    }

    private Dictionary<TKey, TValue> _data;

    public Dictionary<TKey, TValue> Data
    {
        get { return this._data; }
    }

    private KeyValuePair<TKey, TValue>? _selectedKey = null;
    public KeyValuePair<TKey, TValue>? SelectedKey
    {
        get { return _selectedKey; }
        set
        {
            _selectedKey = value;
            RaisePropertyChanged("SelectedKey");
            RaisePropertyChanged("SelectedValue");
        }
    }

    public TValue SelectedValue
    {
        get
        {
            return _data[SelectedKey.Value.Key];
        }
        set
        {
            _data[SelectedKey.Value.Key] = value;
            RaisePropertyChanged("SelectedValue");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

}

不幸的是我仍然不知道如何传递"一般"字典对象..任何想法?

谢谢!

干杯

And*_*ndy 35

如果你真的想打一个ObservableDictionary,我建议创建一个实现既类IDictionaryINotifyCollectionChanged.您可以随时使用Dictionary内部方法来实现这些方法,IDictionary这样您就不必重新实现它们.

由于您完全了解内部Dictionary更改的时间,因此您可以使用该知识来实现INotifyCollectionChanged.

  • 你有没有机会详细说明代码?你将帮助很多新手(像我一样)拖网stackOverflow寻找答案 - 已经有23k次观看了.CHRS (2认同)
  • @BKSpurgeon有一个样本已经可用:http://blogs.microsoft.co.il/shimmy/2010/12/26/observabledictionarylttkey-tvaluegt-c/(来自http://stackoverflow.com/questions/5663395/net -observabledictionary,在问题的评论中链接). (2认同)

Ton*_*all 6

出于历史目的并将人们放在"当前"路径上......重要的是要知道Microsoft现在在Visual Studio 2012中的Windows Store"基本页面"模板中解决了这个要求.为了支持LayoutAwarePage,他们生成一个私有ObservableDictionary类.

但是它们直接实现了一个新的IObservableMap接口而不是IDictionary.此接口添加了一个MapChanged事件和MapChangedEventHandler,它在Windows.Foundation.Collections命名空间中定义.

下面的代码段只是项目"Common"文件夹中生成的LayoutAwarePage.cs中的ObservableDictionary类:

    /// <summary>
    /// Implementation of IObservableMap that supports reentrancy for use as a default view
    /// model.
    /// </summary>
    private class ObservableDictionary<K, V> : IObservableMap<K, V>
    {
        private class ObservableDictionaryChangedEventArgs : IMapChangedEventArgs<K>
        {
            public ObservableDictionaryChangedEventArgs(CollectionChange change, K key)
            {
                CollectionChange = change;
                Key = key;
            }

            public CollectionChange CollectionChange { get; private set; }
            public K Key { get; private set; }
        }

        private Dictionary<K, V> _dictionary = new Dictionary<K, V>();
        public event MapChangedEventHandler<K, V> MapChanged;

        private void InvokeMapChanged(CollectionChange change, K key)
        {
            var eventHandler = MapChanged;
            if (eventHandler != null)
            {
                eventHandler(this, new ObservableDictionaryChangedEventArgs(change, key));
            }
        }

        public void Add(K key, V value)
        {
            _dictionary.Add(key, value);
            InvokeMapChanged(CollectionChange.ItemInserted, key);
        }

        public void Add(KeyValuePair<K, V> item)
        {
            Add(item.Key, item.Value);
        }

        public bool Remove(K key)
        {
            if (_dictionary.Remove(key))
            {
                InvokeMapChanged(CollectionChange.ItemRemoved, key);
                return true;
            }
            return false;
        }

        public bool Remove(KeyValuePair<K, V> item)
        {
            V currentValue;
            if (_dictionary.TryGetValue(item.Key, out currentValue) &&
                Object.Equals(item.Value, currentValue) && _dictionary.Remove(item.Key))
            {
                InvokeMapChanged(CollectionChange.ItemRemoved, item.Key);
                return true;
            }
            return false;
        }

        public V this[K key]
        {
            get
            {
                return _dictionary[key];
            }
            set
            {
                _dictionary[key] = value;
                InvokeMapChanged(CollectionChange.ItemChanged, key);
            }
        }

        public void Clear()
        {
            var priorKeys = _dictionary.Keys.ToArray();
            _dictionary.Clear();
            foreach (var key in priorKeys)
            {
                InvokeMapChanged(CollectionChange.ItemRemoved, key);
            }
        }

        public ICollection<K> Keys
        {
            get { return _dictionary.Keys; }
        }

        public bool ContainsKey(K key)
        {
            return _dictionary.ContainsKey(key);
        }

        public bool TryGetValue(K key, out V value)
        {
            return _dictionary.TryGetValue(key, out value);
        }

        public ICollection<V> Values
        {
            get { return _dictionary.Values; }
        }

        public bool Contains(KeyValuePair<K, V> item)
        {
            return _dictionary.Contains(item);
        }

        public int Count
        {
            get { return _dictionary.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public IEnumerator<KeyValuePair<K, V>> GetEnumerator()
        {
            return _dictionary.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return _dictionary.GetEnumerator();
        }

        public void CopyTo(KeyValuePair<K, V>[] array, int arrayIndex)
        {
            if (array == null) throw new ArgumentNullException("array");
            int arraySize = array.Length;
            foreach (var pair in _dictionary)
            {
                if (arrayIndex >= arraySize) break;
                array[arrayIndex++] = pair;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

对新的Windows.Foundation.Collections命名空间的进一步检查显示了已定义的新接口的加载,但只实现了一个PropertySet类.实际上这似乎是一个非常好的ObservableDictionary本身.但是必须有一个原因,MS仍然会生成一个私有的ObservableDictionary.因此,需要进一步检查以确定优缺点.

简而言之,PropertySet或您自己的基于IObservableMap的ObservableDictionary应解决"当前"Windows 8和Phone 8项目的即时需求.但是对于旧框架(WPF 4和Phone 7.5),还有更多工作要做.