在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));
}
}