在WPF中绑定到字典中的类属性 [英] Binding to a class property in a dictionary in wpf

查看:141
本文介绍了在WPF中绑定到字典中的类属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果一个人绑定到列表框的 ItemsSource 到一个列表类型结构,例如 ObservableCollection (或者实际上是任何仅值容器),并且具有类的类型( List< MyClass> )可以访问所述类的属性.

If one binds to a listbox's ItemsSource to a list type structure such as an ObservableCollection (or any value-only container really) with the type of a class (List< MyClass>) one can access the properties of said class.

但是如果一个人有一个 Dictionary< long,MyClass> 并将项目源绑定到 Dictionary.Values ,则一个人将无法再访问该类的属性.

But if one has a Dictionary<long, MyClass> and binds the itemssource to Dictionary.Values one can not access the class properties anymore.

所以基本上这是我的XAML

So basically this is my XAML

    <ListBox ItemsSource="{Binding bm.Values}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                   <TextBlock Text="{Binding Name}"/>
                   <TextBlock Text="{Binding Property2}"/>
                   <TextBlock Text="{Binding Property3}"/>
                 </StackPanel>
            </DataTemplate>
         </ListBox.ItemTemplate>
    </ListBox>

在视图模型中是

    public Dictionary<long,MyClass> bm { get; set; }

使用这样的代码,您可以将Texblock DataContext设置为 MyClass ,但是您无权访问Name,property2和property3.但是,如果将字典更改为列表,则TextBlock DataContext也将设置为 MyClass ,但是它将有权访问这些字段.

With code like this you have the Texblock DataContext set to MyClass, but you do not have access to Name, property2 and property3. But if you change the dictionary to a List the TextBlock DataContext will also be set to MyClass, but it will have access to those fields.

出于架构原因,我无法从词典"切换到非关键集合.

For architectural reasons I can not switch from the Dictionary to a non-key collection.

问题是:如何让XAML看到属性,以及为什么这种情况实际上会发生?

So the question is: how can you make XAML see the properties and why exactly does this situation actually happen?

推荐答案

随意使用此ObservableDictionary类代码

Feel free to use this code of ObservableDictionary class

public class ObservableDictionary<TKey, TValue> : IDictionary<TKey, TValue>, INotifyCollectionChanged, INotifyPropertyChanged {
    private const string CountString = "Count";
    private const string IndexerName = "Item[]";
    private const string KeysName = "Keys";
    private const string ValuesName = "Values";

    private IDictionary<TKey, TValue> _Dictionary;
    protected IDictionary<TKey, TValue> Dictionary {
        get { return _Dictionary; }
    }

    #region Constructors
    public ObservableDictionary() {
        _Dictionary = new Dictionary<TKey, TValue>();
    }
    public ObservableDictionary(IDictionary<TKey, TValue> dictionary) {
        _Dictionary = new Dictionary<TKey, TValue>(dictionary);
    }
    public ObservableDictionary(IEqualityComparer<TKey> comparer) {
        _Dictionary = new Dictionary<TKey, TValue>(comparer);
    }
    public ObservableDictionary(int capacity) {
        _Dictionary = new Dictionary<TKey, TValue>(capacity);
    }
    public ObservableDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer) {
        _Dictionary = new Dictionary<TKey, TValue>(dictionary, comparer);
    }
    public ObservableDictionary(int capacity, IEqualityComparer<TKey> comparer) {
        _Dictionary = new Dictionary<TKey, TValue>(capacity, comparer);
    }
    #endregion

    #region IDictionary<TKey,TValue> Members

    public void Add(TKey key, TValue value) {
        Insert(key, value, true);
    }

    public bool ContainsKey(TKey key) {
        return Dictionary.ContainsKey(key);
    }

    public ICollection<TKey> Keys {
        get { return Dictionary.Keys; }
    }

    public bool Remove(TKey key) {
        if(key == null) throw new ArgumentNullException("key");

        TValue value;
        Dictionary.TryGetValue(key, out value);
        var removed = Dictionary.Remove(key);
        if(removed)
            //OnCollectionChanged(NotifyCollectionChangedAction.Remove, new KeyValuePair<TKey, TValue>(key, value));
            OnCollectionChanged();

        return removed;
    }


    public bool TryGetValue(TKey key, out TValue value) {
        return Dictionary.TryGetValue(key, out value);
    }


    public ICollection<TValue> Values {
        get { return Dictionary.Values; }
    }


    public TValue this[TKey key] {
        get {
            return Dictionary[key];
        }
        set {
            Insert(key, value, false);
        }
    }


    #endregion


    #region ICollection<KeyValuePair<TKey,TValue>> Members


    public void Add(KeyValuePair<TKey, TValue> item) {
        Insert(item.Key, item.Value, true);
    }


    public void Clear() {
        if(Dictionary.Count > 0) {
            Dictionary.Clear();
            OnCollectionChanged();
        }
    }


    public bool Contains(KeyValuePair<TKey, TValue> item) {
        return Dictionary.Contains(item);
    }


    public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) {
        Dictionary.CopyTo(array, arrayIndex);
    }


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


    public bool IsReadOnly {
        get { return Dictionary.IsReadOnly; }
    }


    public bool Remove(KeyValuePair<TKey, TValue> item) {
        return Remove(item.Key);
    }


    #endregion


    #region IEnumerable<KeyValuePair<TKey,TValue>> Members


    public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() {
        return Dictionary.GetEnumerator();
    }


    #endregion


    #region IEnumerable Members


    IEnumerator IEnumerable.GetEnumerator() {
        return ((IEnumerable) Dictionary).GetEnumerator();
    }


    #endregion


    #region INotifyCollectionChanged Members


    public event NotifyCollectionChangedEventHandler CollectionChanged;


    #endregion


    #region INotifyPropertyChanged Members


    public event PropertyChangedEventHandler PropertyChanged;


    #endregion


    public void AddRange(IDictionary<TKey, TValue> items) {
        if(items == null) throw new ArgumentNullException("items");


        if(items.Count > 0) {
            if(Dictionary.Count > 0) {
                if(items.Keys.Any((k) => Dictionary.ContainsKey(k)))
                    throw new ArgumentException("An item with the same key has already been added.");
                else
                    foreach(var item in items) Dictionary.Add(item);
            } else
                _Dictionary = new Dictionary<TKey, TValue>(items);


            OnCollectionChanged(NotifyCollectionChangedAction.Add, items.ToArray());
        }
    }


    private void Insert(TKey key, TValue value, bool add) {
        if(key == null) throw new ArgumentNullException("key");


        TValue item;
        if(Dictionary.TryGetValue(key, out item)) {
            if(add) throw new ArgumentException("An item with the same key has already been added.");
            if(Equals(item, value)) return;
            Dictionary[key] = value;


            OnCollectionChanged(NotifyCollectionChangedAction.Replace, new KeyValuePair<TKey, TValue>(key, value), new KeyValuePair<TKey, TValue>(key, item));
        } else {
            Dictionary[key] = value;

            OnCollectionChanged(NotifyCollectionChangedAction.Add, new KeyValuePair<TKey, TValue>(key, value));
        }
    }


    private void OnPropertyChanged() {
        OnPropertyChanged(CountString);
        OnPropertyChanged(IndexerName);
        OnPropertyChanged(KeysName);
        OnPropertyChanged(ValuesName);
    }


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


    private void OnCollectionChanged() {
        OnPropertyChanged();
        if(CollectionChanged != null) CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    }


    private void OnCollectionChanged(NotifyCollectionChangedAction action, KeyValuePair<TKey, TValue> changedItem) {
        OnPropertyChanged();
        if(CollectionChanged != null) CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, changedItem));
    }


    private void OnCollectionChanged(NotifyCollectionChangedAction action, KeyValuePair<TKey, TValue> newItem, KeyValuePair<TKey, TValue> oldItem) {
        OnPropertyChanged();
        if(CollectionChanged != null) CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, newItem, oldItem));
    }


    private void OnCollectionChanged(NotifyCollectionChangedAction action, IList newItems) {
        OnPropertyChanged();
        if(CollectionChanged != null) CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, newItems));
    }
}

这篇关于在WPF中绑定到字典中的类属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆