2009-05-08 9 views
5

ListCollectionView.AddNewは、作成するオブジェクトのタイプをどのように決定し、どのように影響を与えますか?ListCollectionView.AddNewによって作成されたオブジェクトのタイプ

私はいくつかの種類(BaseDerivedA、およびDerivedB)の階層構造を持っており、現在、私のWPF ToolkitのDataGridDerivedAオブジェクトを作成します(なぜ、私は知らない - おそらく、グリッド内のほぼすべてのデータがあるので、そのタイプの代わりにDerivedBオブジェクトを作成したいと思います)。

更新:私はListCollectionViewから新しいクラスを派生し、そのための新しいAddNew方法を実現しようとしました、そして今、私はほとんどそこだ:唯一の残りの問題は、その新しい項目を追加した後、新たに新しいですitemプレースホルダは追加されないので、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

古い質問には、新鮮な答えに値する:) 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、ソースコードを含めました:サポートされている場合は、新しいアイテムにBeginInitBeginEditを呼び出し、そして最終的にはデータグリッド上のコールバックを通じて、セルバインディングを確立し、イベントを発射私は設計時に必要とされるどのような種類がわからないとき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があなたの影響力の外にあるコンポーネントから来ている場合、または既存のコードに機能を追加する必要がある場合に、特に便利です(私は無邪気なコーダーであるため、コレクション付きのカエル)。

+0

私のアプリケーションでアーキテクチャを変更したので、これはもはや私の問題ではありませんでしたが、あなたの答えはちょうどそれを見ていると思われます。 –

+0

何らかの理由で、私は昨年この答えを受け入れたようではありません。 –

1

TomiJ、

それは役立ちますが、答えはOKでないかどうかを確認?

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

+1

この記事(元の記事は)は、ヘルプは、私に 'ListCollectionView'を見させてくれました。 –

+0

私は正しい答えを得ることができました。ここで更新することを忘れないでください。 非常に興味深い質問です:D –

+0

私はまだ_one_新しい項目を追加することができますが、少なくとも正しいAddNewメソッドが呼び出されるので、まだありません。適切な機能を実現するために何を実装する必要があるかを理解する必要があります。 –

1

.NET 4には、ListCollectionViewで実装された新しいインターフェイスIEditableCollectionViewAddNewItemがあります。新しいメソッドAddNewItem(object)を持っています。 AddNew()の代わりに使用して、新しく追加された項目を制御できます。

+0

確かにあります。この答えは、私が受け入れたErikestのもの(これは古く、 'ListCollectionView.AddNewItem(オブジェクト)'にも言及しています)と同等です。 –

関連する問題