Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Stale questions deserve fresh answers :)</p> <p>Deriving a class from <code>ListCollectionView</code> is the path I took to control the objects being added by <code>AddNew</code> as well, but after browsing through the source of <code>ListCollectionView</code> to find out what it does internally, I found that the safest way to redefine <code>AddNew</code> (it's not technically an override) is to use <code>ListCollectionView.AddNewItem</code> after creating my new object, so your code would look like this:</p> <pre><code>public class CustomView : ListCollectionView, IEditableCollectionView { public CustomView(System.Collections.IList list) : base(list) { } object IEditableCollectionView.AddNew() { DerivedB obj = new DerivedB(); return base.AddNewItem(obj); } } </code></pre> <p>This works well because, in addition to having nearly identical implementations otherwise, <code>ListCollectionView.AddNew()</code> and <code>ListCollectionView.AddNewItem(object item)</code> both call <code>AddNewCommon(object newItem)</code>:</p> <pre><code> public object AddNew() { VerifyRefreshNotDeferred(); if (IsEditingItem) { CommitEdit(); // implicitly close a previous EditItem } CommitNew(); // implicitly close a previous AddNew if (!CanAddNew) throw new InvalidOperationException(SR.Get(SRID.MemberNotAllowedForView, "AddNew")); return AddNewCommon(_itemConstructor.Invoke(null)); } public object AddNewItem(object newItem) { VerifyRefreshNotDeferred(); if (IsEditingItem) { CommitEdit(); // implicitly close a previous EditItem } CommitNew(); // implicitly close a previous AddNew if (!CanAddNewItem) throw new InvalidOperationException(SR.Get(SRID.MemberNotAllowedForView, "AddNewItem")); return AddNewCommon(newItem); } </code></pre> <p><code>AddNewCommon</code> is where all the real magic happens; firing events, calling <code>BeginInit</code> and <code>BeginEdit</code> on the new item if supported, and eventually through callbacks on the datagrid, establishing the cell bindings:</p> <pre><code> object AddNewCommon(object newItem) { _newItemIndex = -2; // this is a signal that the next Add event comes from AddNew int index = SourceList.Add(newItem); // if the source doesn't raise collection change events, fake one if (!(SourceList is INotifyCollectionChanged)) { // the index returned by IList.Add isn't always reliable if (!Object.Equals(newItem, SourceList[index])) { index = SourceList.IndexOf(newItem); } BeginAddNew(newItem, index); } Debug.Assert(_newItemIndex != -2 &amp;&amp; Object.Equals(newItem, _newItem), "AddNew did not raise expected events"); MoveCurrentTo(newItem); ISupportInitialize isi = newItem as ISupportInitialize; if (isi != null) { isi.BeginInit(); } IEditableObject ieo = newItem as IEditableObject; if (ieo != null) { ieo.BeginEdit(); } return newItem; } </code></pre> <p>Here I've included the source code to my <code>TypedListCollectionView</code>, which I use to control the <code>AddNew</code> behavior when I don't know what type will be needed at design time:</p> <pre><code> public class TypedListCollectionView : ListCollectionView, IEditableCollectionView { Type AddNewType { get; set; } public TypedListCollectionView(System.Collections.IList source, Type addNewType) : base(source) { AddNewType = addNewType; } object IEditableCollectionView.AddNew() { object newItem = Activator.CreateInstance(AddNewType); return base.AddNewItem(newItem); } } </code></pre> <p>I like this approach since it provides maximum flexibility for cases where <code>AddNew</code>'s type may need to be adjusted at runtime from one to another. It also allows <code>AddNew</code> to work for adding the first item in the collection, which is handy when the list source is initially empty, but its underlying type can be determined.</p> <p><a href="http://social.msdn.microsoft.com/Forums/en/wpf/thread/381dfbbd-1e9a-4a79-8a40-87b4d8767264" rel="nofollow">This link</a> discusses an alternative way to force the type used by <code>AddNew()</code>. It uses reflection to set the private <code>_itemConstructor</code> property used by <code>AddNew</code> to a parameterless constructor of a specified type. This would be particularly useful when your <code>ListCollectionView</code> is coming from a component that's outside of your influence, or you need to add functionality into existing code and you're worried about breaking things (which I never am because I'm a cavalier coder who callously carouses with collections).</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload