古い質問には、新鮮な答えに値する:) ListCollectionView
からクラスを派生
は私もAddNew
によって追加されたオブジェクトを制御するために取った道ですが、ListCollectionView
のソースを閲覧した後、内部で何が行われているかを調べると、AddNew
を再定義する最も安全な方法(技術的にオーバーライドではありません)が新しいオブジェクトを作成した後にListCollectionView.AddNewItem
を使用することがわかったので、コードは次のようになります:
public class CustomView : ListCollectionView, IEditableCollectionView
{
public CustomView(System.Collections.IList list)
: base(list)
{
}
object IEditableCollectionView.AddNew()
{
DerivedB obj = new DerivedB();
return base.AddNewItem(obj);
}
}
そうでなければ、ほぼ同一の実装を有することに加えて、ListCollectionView.AddNew()
とListCollectionView.AddNewItem(object item)
両方コールAddNewCommon(object newItem)
、これはうまく機能:すべての本当の魔法が起こる場所
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);
}
AddNewCommon
です。
ここ
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 && 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;
}
私は私が使用して私のTypedListCollectionView
、ソースコードを含めました:サポートされている場合は、新しいアイテムにBeginInit
とBeginEdit
を呼び出し、そして最終的にはデータグリッド上のコールバックを通じて、セルバインディングを確立し、イベントを発射私は設計時に必要とされるどのような種類がわからないときAddNew
動作を制御:それはAddNew
のタイプから、実行時に調整する必要があるかもしれない場合のために最大限の柔軟性を提供するので
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);
}
}
私はこのアプローチが好きお互いにAddNew
はコレクションの最初の項目を追加することもできます。これは、リストソースが最初は空ですが、基になる型を判別できるときに便利です。
This linkは、使用するタイプを強制的に使用する別の方法について説明しています。AddNew()
。これはリフレクションを使用してAddNew
によって使用されるプライベート_itemConstructor
プロパティを、指定された型のパラメータのないコンストラクタに設定します。これは、ListCollectionView
があなたの影響力の外にあるコンポーネントから来ている場合、または既存のコードに機能を追加する必要がある場合に、特に便利です(私は無邪気なコーダーであるため、コレクション付きのカエル)。
私のアプリケーションでアーキテクチャを変更したので、これはもはや私の問題ではありませんでしたが、あなたの答えはちょうどそれを見ていると思われます。 –
何らかの理由で、私は昨年この答えを受け入れたようではありません。 –