Вопрос по wpf, data-binding, c# – Общий наблюдаемый словарный класс для привязки данных / WPF C #

25

Я пытаюсь создать класс наблюдаемого словаря для привязки данных WPF в C #. Я нашел хороший пример от Энди здесь:Двухстороннее связывание данных со словарем в 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");
        }
    }
}

}

К сожалению, я до сих пор не знаю, как пройти «общее» Словарь объектов .. Есть идеи?

Спасибо!

ура

Не могли бы вы рассказать немного подробнее о том, что вы пытаетесь сделать? Можете ли вы показать пример кода, который вы хотели бы написать, когда говорите "передать общий словарь ..." JMarsch
У меня есть разные словари, например, Почтовый индекс и город. Я пытаюсь сделать следующее: - связать данные (модель / словарь) с моим WPF ItemsControl, чтобы пользователь мог, например, измените город почтового индекса, и модель автоматически обновится. К сожалению, возможна только OneWay-Binding с «нормальной» связью. Словарь, потому что мне нужно INotifyPropertyChanged. - Создайте ObservableDictionary, который реализует INotifyPropertyChanged, а также содержит словарь Joseph jun. Melettukunnel

Ваш Ответ

6   ответов
0

что сделает чужой словарь, не говоря уже о IDictionary, наблюдаемым без использования какой-либо формы отражения. Проблема в том, что Словарь может быть подклассом с дополнительными мутаторами (скажем, Sort или Filter или любым другим), которые не вызывают Add и Remove и в результате обходят ваши события.

Я считаю, что существуют структуры для генерации кода, которые позволяют вам делать такие вещи, но я не знаком с ними.

1

MSFT.ParallelExtensionsExtras пакет доступен через Nuget:https://www.nuget.org/packages/ParallelExtensionsExtras/

ObservableConcurrentDictionary<TKey, TValue>

35

ObservableDictionaryЯ предлагаю создать класс, который реализует обаIDictionary а такжеINotifyCollectionChanged, Вы всегда можете использоватьDictionary внутренне для реализации методовIDictionary так что вам не придется переопределять это самостоятельно.

Так как у вас есть полное знание того, когда внутреннийDictionary изменения, вы можете использовать эти знания для реализацииINotifyCollectionChanged.

@BKSpurgeon Образец уже доступен:blogs.microsoft.co.il/shimmy/2010/12/26/… (с помощьюstackoverflow.com/questions/5663395/net-observabledictionary, связанный в комментариях к вопросу).
какой-нибудь шанс вы могли бы уточнить с кодом? Вы будете помогать многим новичкам (как и я), траляя стекOverflow для ответов - уже 23 тыс. просмотров. ХР
1

где объясняется, как реализовать наблюдаемый словарь, а исходный код доступен с образцом:

http://drwpf.com/blog/2007/09/16/can-i-bind-my-itemscontrol-to-a-dictionary/

6

чтобы ставить людей на "текущий" путь ... Важно знать, что Microsoft теперь решает это требование в своей Windows Store & quot; Базовая страница & quot; шаблон в Visual Studio 2012. Для поддержки LayoutAwarePage они генерируют закрытый класс ObservableDictionary.

Однако они реализуют новый интерфейс IObservableMap, а не IDictionary напрямую. Этот интерфейс добавляет событие MapChanged и MapChangedEventHandler, определенные в пространстве имен Windows.Foundation.Collections.

Фрагмент ниже - это просто класс ObservableDictionary из LayoutAwarePage.cs, созданный в & quot; Common & quot; папка вашего проекта:

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

Дальнейшее изучение нового пространства имен Windows.Foundation.Collections показывает загрузку новых определенных интерфейсов, но только одинPropertySet класс реализован. На самом деле это похоже на довольно хороший ObservableDictionary. Но должна быть причина, почему MS все еще генерирует частный ObservableDictionary. Таким образом, дальнейшее изучение требуется здесь, чтобы определить плюсы и минусы.

Короче говоря, либо PropertySet, либо ваш собственный ObservableDictionary, основанный на IObservableMap, должен решить неотложные требования для & quot; current & quot; Проекты Windows 8 и Phone 8. Однако для более старых платформ (WPF 4 и Phone 7.5) еще предстоит проделать большую работу.

19
Я не могу реализовать INotifyCollectionChanged. Это говорит о недостающей сборке. Я импортировал все сборки вверху вашего поста (C #), и у меня есть .NET 3.5, но он не может его найти. Есть идеи?
Вы импортировали пространства имен, но, возможно, отсутствуют ссылки на важные сборки. Убедитесь, что сборка System.dll упоминается в вашем проекте. См примерhere.

Похожие вопросы