title: WPF 'EditItem' is not allowed for this view
body: <p>I know there are a lots of questions (<a href="https://stackoverflow.com/questions/3002063/edititem-is-not-allowed-for-this-view-databinding-issue">1</a>, <a href="https://stackoverflow.com/questions/41088750/edititem-is-not-allowed-for-this-view-when-editing-a-detail-item">2</a>, <a href="https://stackoverflow.com/questions/19334326/wpf-datagrid-edititem-is-not-allowed-for-this-view-exception">3</a>, <a href="https://stackoverflow.com/questions/6949022/datagrid-edititem-is-not-allowed-for-this-view-when-dragging-multiple-items">4</a>, <a href="https://stackoverflow.com/questions/40816294/edititem-is-not-allowed-for-this-view-list">5</a>, etc) about that error, but I can't find one that explains the cause of this error and suitable for my case. Let me know if I miss one!</p>
  
  <p>First of all, I am binding to my DataGrid <code>ItemsSource</code> with a custom class (not <code>ObservableCollection</code> or any other .NET built-in observable collection). Before showing you its code, let me explain how I thought of it (my assumptions are may be be wrong). </p>
  
  <p>In my mind, to be bindable, a collection must implements at least <code>IEnumerable</code> and <code>INotifyCollectionChanged</code>. IEnumerable in order to the view to get the items to display (thanks to the <code>GetEnumerator</code> method) and INotifyCollectionChanged in order to the view to know the changes on the collection.</p>
  
  <p>So I end up with this class:</p>
  
  <pre><code>public class ObservableDictionary&lt;TKey, TValue&gt; : IDictionary&lt;TKey, TValue&gt;, IEnumerable&lt;TValue&gt;, INotifyCollectionChanged
  {
      #region fields
  
      private IDictionary&lt;TKey, TValue&gt; _innerDictionary;
  
      #endregion
  
      #region properties
  
      public int Count { get { return _innerDictionary.Count; } }
  
      public ICollection&lt;TKey&gt; Keys { get { return _innerDictionary.Keys; } }
  
      public ICollection&lt;TValue&gt; 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&lt;TKey, TValue&gt;(key, value)); }
      }
  
      #endregion
  
      #region events
  
      public event NotifyCollectionChangedEventHandler CollectionChanged;
  
      #endregion
  
      #region constructors
  
      public ObservableDictionary()
      {
          _innerDictionary = new Dictionary&lt;TKey, TValue&gt;();
      }
  
      public ObservableDictionary(int capacity)
      {
          _innerDictionary = new Dictionary&lt;TKey, TValue&gt;(capacity);
      }
  
      public ObservableDictionary(IEqualityComparer&lt;TKey&gt; comparer)
      {
          _innerDictionary = new Dictionary&lt;TKey, TValue&gt;(comparer);
      }
  
      public ObservableDictionary(IDictionary&lt;TKey, TValue&gt; dictionary)
      {
          _innerDictionary = new Dictionary&lt;TKey, TValue&gt;(dictionary);
      }
  
      public ObservableDictionary(int capacity, IEqualityComparer&lt;TKey&gt; comparer)
      {
          _innerDictionary = new Dictionary&lt;TKey, TValue&gt;(capacity, comparer);
      }
  
      public ObservableDictionary(IDictionary&lt;TKey, TValue&gt; dictionary, IEqualityComparer&lt;TKey&gt; comparer)
      {
          _innerDictionary = new Dictionary&lt;TKey, TValue&gt;(dictionary, comparer);
      }
  
      #endregion
  
      #region public methods
  
      public bool ContainsKey(TKey key)
      {
          return _innerDictionary.ContainsKey(key);
      }
  
      public bool Contains(KeyValuePair&lt;TKey, TValue&gt; item)
      {
          return _innerDictionary.Contains(item);
      }
  
      public void Add(TKey key, TValue value)
      {
          this.InternalAdd(new KeyValuePair&lt;TKey, TValue&gt;(key, value));
      }
  
      public void AddRange(IEnumerable&lt;KeyValuePair&lt;TKey, TValue&gt;&gt; items)
      {
          if (!items.Any())
          {
              return;
          }
  
          var added = new List&lt;TValue&gt;();
          var removed = new List&lt;TValue&gt;();
  
          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 &gt; 0)
          {
              this.CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, null, removed));
          }
      }
  
      public void Add(KeyValuePair&lt;TKey, TValue&gt; 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&lt;TKey, TValue&gt; item)
      {
          return this.InternalRemove(item.Key);
      }
  
      public void Clear()
      {
          _innerDictionary.Clear();
          this.CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
      }
  
      public void CopyTo(KeyValuePair&lt;TKey, TValue&gt;[] array, int arrayIndex)
      {
          _innerDictionary.CopyTo(array, arrayIndex);
      }
  
      public IEnumerator&lt;TValue&gt; GetEnumerator()
      {
          return Values.GetEnumerator();
      }
  
      IEnumerator IEnumerable.GetEnumerator()
      {
          return this.GetEnumerator();
      }
  
      IEnumerator&lt;KeyValuePair&lt;TKey, TValue&gt;&gt; IEnumerable&lt;KeyValuePair&lt;TKey, TValue&gt;&gt;.GetEnumerator()
      {
          return _innerDictionary.GetEnumerator();
      }
  
      #endregion
  
      #region private methods
  
      /// &lt;summary&gt;
      /// Adds the specified value to the internal dictionary and indicates whether the element has actually been added. Fires the CollectionChanged event accordingly.
      /// &lt;/summary&gt;
      /// &lt;param name="key"&gt;&lt;/param&gt;
      /// &lt;param name="value"&gt;&lt;/param&gt;
      private void InternalAdd(KeyValuePair&lt;TKey, TValue&gt; 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));
      }
  
      /// &lt;summary&gt;
      /// Remove the specified key from the internal dictionary and indicates whether the element has actually been removed. Fires the CollectionChanged event accordingly.
      /// &lt;/summary&gt;
      /// &lt;param name="key"&gt;&lt;/param&gt;
      /// &lt;param name="value"&gt;&lt;/param&gt;
      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
  }
  </code></pre>
  
  <p>It implements implicitly the <code>IEnumerable&lt;TValue&gt;.GetEnumerator</code> and explicitly the others <code>GetEnumerator</code> methods (<code>IDictionary</code> and <code>IEnumerable</code>) in order to my view display only the values of my dictionary, and I map the add/remove methods around the invocation of the <code>CollectionChanged</code> event.</p>
  
  <p>My ViewModel is defined like this:</p>
  
  <pre><code>class MyViewModel
  {
      public ObservableDictionary&lt;string, Foo&gt; Foos { get; private set; }
  
      public MyViewModel()
      {
          this.Foos = new ObservableDictionary&lt;string, Foo&gt;();
      }
  }
  </code></pre>
  
  <p>And bind it to my view like this:</p>
  
  <pre><code>&lt;DataGrid ItemsSource="{Binding Facts}" AutoGenerateColumns="False" CanUserAddRows="False" CanUserDeleteRows="False"&gt;
      &lt;DataGrid.Columns&gt;
          &lt;DataGridTextColumn Header="Name" Binding="{Binding Name}" IsReadOnly="True" Width="*" /&gt;
          &lt;DataGridTextColumn Header="Type" Binding="{Binding Type}" IsReadOnly="True" Width="*" /&gt;
          &lt;DataGridTextColumn Header="Value" Binding="{Binding Value}" IsReadOnly="False" Width="*" /&gt;
      &lt;/DataGrid.Columns&gt;
  &lt;/DataGrid&gt;
  </code></pre>
  
  <p>Then, when I try to edit the Value, I get the specified error:</p>
  
  <blockquote>
    <p>'EditItem' is not allowed for this view</p>
  </blockquote>
  
  <p>When I put some breakpoints in my code, I never reach the <code>ObservableDictionary</code> indexor setter nor <code>Foo.Value</code> setter.</p>
  
  <p><strong>Are my thoughts about how the view gets the item from the binded collection corrects? Why am I getting this error and/or how can I authorize my view to <code>EditItem</code>?</strong></p>