此视图不允许使用WPF“EditItem”
我知道有很多关于这个错误的问题( 1,2,3,4,5等),但我找不到解释这个错误的原因并适合我的情况。 如果我错过了一个,请告诉我!
首先,我使用自定义类(不是ObservableCollection
或任何其他.NET内置的可观察集合)绑定到我的DataGrid ItemsSource
。 在向您展示其代码之前,让我解释一下我是如何想到的(我的假设可能是错误的)。
在我看来,要成为可绑定的,集合必须至少实现IEnumerable
和INotifyCollectionChanged
。 IEnumerable以视图获取要显示的项目(感谢GetEnumerator
方法)和INotifyCollectionChanged以便视图知道集合上的更改。
所以我最终得到了这个课程:
public class ObservableDictionary : IDictionary, IEnumerable, INotifyCollectionChanged { #region fields private IDictionary _innerDictionary; #endregion #region properties public int Count { get { return _innerDictionary.Count; } } public ICollection Keys { get { return _innerDictionary.Keys; } } public ICollection Values { get { return _innerDictionary.Values; } } public bool IsReadOnly { get { return false; } } #endregion #region indexors public TValue this[TKey key] { get { return _innerDictionary[key]; } set { this.InternalAdd(new KeyValuePair(key, value)); } } #endregion #region events public event NotifyCollectionChangedEventHandler CollectionChanged; #endregion #region constructors public ObservableDictionary() { _innerDictionary = new Dictionary(); } public ObservableDictionary(int capacity) { _innerDictionary = new Dictionary(capacity); } public ObservableDictionary(IEqualityComparer comparer) { _innerDictionary = new Dictionary(comparer); } public ObservableDictionary(IDictionary dictionary) { _innerDictionary = new Dictionary(dictionary); } public ObservableDictionary(int capacity, IEqualityComparer comparer) { _innerDictionary = new Dictionary(capacity, comparer); } public ObservableDictionary(IDictionary dictionary, IEqualityComparer comparer) { _innerDictionary = new Dictionary(dictionary, comparer); } #endregion #region public methods public bool ContainsKey(TKey key) { return _innerDictionary.ContainsKey(key); } public bool Contains(KeyValuePair item) { return _innerDictionary.Contains(item); } public void Add(TKey key, TValue value) { this.InternalAdd(new KeyValuePair(key, value)); } public void AddRange(IEnumerable<KeyValuePair> items) { if (!items.Any()) { return; } var added = new List(); var removed = new List(); foreach (var item in items) { TValue value; if (_innerDictionary.TryGetValue(item.Key, out value)) { removed.Add(value); } added.Add(item.Value); _innerDictionary[item.Key] = item.Value; } this.CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, added, null)); if (removed.Count > 0) { this.CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, null, removed)); } } public void Add(KeyValuePair item) { this.InternalAdd(item); } public bool TryGetValue(TKey key, out TValue value) { return _innerDictionary.TryGetValue(key, out value); } public bool Remove(TKey key) { return this.InternalRemove(key); } public bool Remove(KeyValuePair item) { return this.InternalRemove(item.Key); } public void Clear() { _innerDictionary.Clear(); this.CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } public void CopyTo(KeyValuePair[] array, int arrayIndex) { _innerDictionary.CopyTo(array, arrayIndex); } public IEnumerator GetEnumerator() { return Values.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } IEnumerator<KeyValuePair> IEnumerable<KeyValuePair>.GetEnumerator() { return _innerDictionary.GetEnumerator(); } #endregion #region private methods /// /// Adds the specified value to the internal dictionary and indicates whether the element has actually been added. Fires the CollectionChanged event accordingly. /// /// /// private void InternalAdd(KeyValuePair item) { IList added = new TValue[] { item.Value }; TValue value; if (_innerDictionary.TryGetValue(item.Key, out value)) { this.CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, null, new TValue[] { value })); } _innerDictionary[item.Key] = item.Value; this.CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, added, null)); } /// /// Remove the specified key from the internal dictionary and indicates whether the element has actually been removed. Fires the CollectionChanged event accordingly. /// /// /// private bool InternalRemove(TKey key) { TValue value; if (_innerDictionary.TryGetValue(key, out value)) { _innerDictionary.Remove(key); this.CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, null, new TValue[] { value })); } return value != null; } #endregion }
它隐式实现了IEnumerable.GetEnumerator
并显式地实现了其他GetEnumerator
方法( IDictionary
和IEnumerable
),以便我的视图只显示我的字典的值,并且我在CollectionChanged
事件的调用周围映射了添加/删除方法。
我的ViewModel定义如下:
class MyViewModel { public ObservableDictionary Foos { get; private set; } public MyViewModel() { this.Foos = new ObservableDictionary(); } }
并将其绑定到我的视图,如下所示:
然后,当我尝试编辑Value时,我得到指定的错误:
此视图不允许使用“EditItem”
当我在代码中放入一些断点时,我从未到达ObservableDictionary
索引器设置器或Foo.Value
设置器。
我对关于视图如何从绑定集合中获取项目的想法进行了更正? 为什么我收到此错误和/或如何将我的视图授权给EditItem
?
如果希望能够编辑DataGrid
的数据,则源集合类型( ObservableDictionary
)应实现IList
接口。
无论何时绑定到WPF中的某个集合属性,您始终绑定到自动生成的视图,而不是绑定到实际的源集合本身。
运行时为您创建的视图类型取决于源集合的类型,并且源集合必须实现非通用IList
接口,以使DataGrid
控件的内部编辑function起作用。
上述就是C#学习教程:此视图不允许使用WPF“EditItem”分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/989128.html