2009-05-08 6 views
5

Wie ermittelt ListCollectionView.AddNew den Typ des Objekts, das es erstellt, und wie könnte es sich darauf auswirken?Art des von ListCollectionView.AddNew erstellten Objekts

Ich habe eine Hierarchie von einigen Typen (Base, DerivedA und DerivedB) und zur Zeit meines WPF Toolkit DataGrid schafft DerivedA Objekte (warum, weiß ich nicht - wahrscheinlich, weil fast alle Daten im Raster ist von diesem Typ), aber ich möchte stattdessen Objekte erstellen.

aktualisieren: Ich habe versucht, eine neue Klasse von ListCollectionView abzuleiten und eine neue AddNew Verfahren zu deren Umsetzung, und ich bin jetzt fast da: die einzige verbleibende Problem ist, dass nach ein neues Element, eine neue neue Hinzufügen Item-Platzhalter wird nicht hinzugefügt, daher kann ich nur ein Element hinzufügen. Mein aktueller Ansatz sieht etwas wie folgt aus:

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; 
    } 
} 

Antwort

4

Stale Fragen verdienen frische Antworten :)

eine Klasse von ListCollectionView ist der Weg Ableitung I durch AddNew als auch hinzugefügt werden die Objekte zu steuern nahm, aber nach der ListCollectionView durch die Quelle des Surfens finde heraus, was es intern tut, fand ich, dass der sicherste Weg, AddNew (es ist technisch ein Override) neu zu definieren ist, ListCollectionView.AddNewItem nach dem Erstellen meines neuen Objekts zu verwenden, so würde Ihr Code wie folgt aussehen:

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

    object IEditableCollectionView.AddNew() 
    { 
     DerivedB obj = new DerivedB(); 
     return base.AddNewItem(obj); 
    } 
} 

Das funktioniert gut, weil zusätzlich sonst nahezu identische Implementierungen AddNewCommon(object newItem), ListCollectionView.AddNew() und ListCollectionView.AddNewItem(object item) beide Aufruf mit:

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 ist, wo alle die wirkliche Magie geschieht; Ereignisse, ruft BeginInit und BeginEdit auf das neue Element Brennen, wenn unterstützt, und schließlich durch Rückrufe auf dem Datagrid, zur Festlegung der Zellbindungen:

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; 
     } 

Hier habe ich den Quellcode meiner TypedListCollectionView enthalten habe, die ich benutze steuert die AddNew Verhalten, wenn ich nicht weiß, welche Art wird zur Entwurfszeit benötigt:

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); 
     } 
    } 

ich diesen Ansatz mag, da es ein Maximum an Flexibilität für den Fall vorsieht, wenn AddNew ‚s Art muß von zur Laufzeit angepasst werden eins zum anderen. Es ermöglicht auch AddNew, um das erste Element in der Auflistung hinzuzufügen, was praktisch ist, wenn die Listenquelle anfänglich leer ist, aber der zugrunde liegende Typ kann bestimmt werden.

This link diskutiert eine alternative Möglichkeit, den Typ zu erzwingen, der von AddNew() verwendet wird. Es verwendet Reflektion, um die private _itemConstructor -Eigenschaft, die von AddNew10 verwendet wird, auf einen parameterlosen Konstruktor eines angegebenen Typs festzulegen.Dies wäre besonders nützlich, wenn Ihr ListCollectionView von einer Komponente kommt, die außerhalb Ihres Einflusses liegt, oder Sie Funktionalität in bestehenden Code hinzufügen müssen und Sie sind besorgt über das Brechen von Dingen (was ich nie bin, weil ich ein Kavalier-Codierer bin, der schwielig Karossen mit Sammlungen).

+0

Ich habe die Architektur in meiner Anwendung so geändert, dass dies für mich kein Problem mehr ist, aber Ihre Antwort erscheint plausibel, wenn Sie sie nur ansehen. –

+0

Aus irgendeinem Grund scheint ich diese Antwort im letzten Jahr nicht akzeptiert zu haben. –

1

TomiJ,

sehen, ob es hilft, aber nicht die Antwort ist ok?

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

+1

Der Artikel (der ursprüngliche ist ) war von einigen Hilfe, da es mich davon abhielt, 'ListCollectionView' zu betrachten. –

+0

Ich sehe, ich habe es geschafft, die richtige Antwort zu bekommen, vergessen Sie nicht, hier zu aktualisieren. Es ist eine sehr interessante Frage: D –

+0

Ich bin noch nicht ganz da, da ich nur _one_ neues Element hinzufügen kann, aber mindestens die richtige AddNew-Methode aufgerufen wird. Ich muss herausfinden, was ich noch implementieren muss, um die richtige Funktionalität zu erhalten. –

1

In .NET 4 gibt es jetzt eine neue Schnittstelle IEditableCollectionViewAddNewItem, implementiert von ListCollectionView, die eine neue Methode AddNewItem(object) besitzt. Sie können es anstelle von AddNew() verwenden, um das neu hinzugefügte Element zu steuern.

+0

Tatsächlich gibt es, und diese Antwort ist ebenso in Ordnung wie die von Erikest, die ich akzeptiert habe (aufgrund dieser Antwort, die älter ist und auch "ListCollectionView.AddNewItem (object)" erwähnt). –

Verwandte Themen