5

ListCollectionView.AddNew作成するオブジェクトのタイプをどのように決定し、どのように影響を与えることができますか?

いくつかのタイプ(、、、および)の階層がありBaseDerivedA現在DerivedBWPF ToolkitがオブジェクトDataGridを作成しDerivedAています(なぜ、わかりません-おそらくグリッド内のほとんどすべてのデータがそのタイプであるためです)が、DerivedB代わりにオブジェクトを作成するのが好きです。

更新:新しいクラスを派生ListCollectionViewさせて新しいメソッドを実装しようとしましたが、もうすぐAddNewです。残っている唯一の問題は、新しいアイテムを追加した後、新しい新しいアイテムのプレースホルダーが追加されないことです。追加できるアイテムは1つだけです。私の現在のアプローチは次のようになります。

public class CustomView : ListCollectionView, IEditableCollectionView
{
    public CustomView(System.Collections.IList list)
        : base(list)
    {
    }

    object IEditableCollectionView.AddNew()
    {
        DerivedB obj = new DerivedB();
        InternalList.Add(obj);
        return obj;
    }
}
4

3 に答える 3

4

古い質問は新鮮な答えに値します:)

からクラスを派生させること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すべての本当の魔法が起こる場所です。イベントを発生させ、サポートされている場合は新しいアイテムを呼び出しBeginInitBeginEdit最終的にはデータグリッドのコールバックを介して、セルバインディングを確立します。

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の動作を制御するために使用します。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このアプローチは、実行時にタイプを調整する必要がある場合に最大限の柔軟性を提供するため、私はこのアプローチが好きです。また、コレクションの最初のアイテムを追加するための作業も可能AddNewです。これは、リストソースが最初は空の場合に便利ですが、基になるタイプを判別できます。

このリンクでは、によって使用されるタイプを強制する別の方法について説明していAddNew()ます。リフレクションを使用して、_itemConstructorによって使用されるプライベートプロパティAddNewを指定されたタイプのパラメーターなしのコンストラクターに設定します。これは、影響力のないコンポーネントから来ている場合、または既存のコードに機能を追加する必要があり、物事を壊すことを心配している場合に特に役立ちますListCollectionView(私は大酒飲みのコーダーであるため、私は決してそうはなりません)コレクション付き)。

于 2012-01-30T00:42:29.507 に答える
2

.NET 4には、新しいメソッドを備えた、IEditableCollectionViewAddNewItemによって実装された新しいインターフェイスがあります。新しく追加されたアイテムを制御する代わりに、これを使用できます。ListCollectionViewAddNewItem(object)AddNew()

于 2012-05-13T13:04:09.797 に答える
1

TomiJ、

それが役立つかどうかを確認しますが、答えは大丈夫ではありませんか?

http://www.cnblogs.com/winkingzhang/archive/2008/05/22/1204581.html

于 2009-05-08T20:30:44.893 に答える