2009-07-08 8 views
4

Ich habe eine Klasse CollectionOfThings. Wie der Name schon sagt, ist es eine einfache Sammlung von Instanzen der Thing Klasse. Thing Klasse hat einen öffentlichen Standardkonstruktor und zwei einfache öffentliche Get, Set-Eigenschaften ID und DisplayName, beide sind String. CollectionOfThing hat auch einen öffentlichen Standardkonstruktor.Direkte Inhaltserstellung in XAML auf einem abhängigen Objekt aktivieren

In XAML würde Ich mag Markup wie folgt verwenden: -

<Grid.Resources> 
    <local:CollectionOfThings x:Key="Things"> 
     <local:Thing ID="1" DisplayName="Hello" /> 
     <local:Thing ID="2" DisplayName="World" /> 
    <local:CollectionOfThings> 
</Grid.Resources> 

Alle so lange gut, wie CollectionOfThings aus einer Sammlungstyp ableitet. Jedoch möchte ich CollectionOfThings auch eine DependencyObject sein. Ich dachte, das ist in Ordnung, eine Implementierung von , INotifyCollectionChanged usw. ist nicht so schwer. Dann kann ich von DependencyObject ableiten.

Leider ICollection<T> schneidet es aus irgendeinem Grund nicht. Mit ICollection<Thing> bekomme ich 'CollectionOfThings unterstützt Thing nicht als Inhalt'. Geh zurück zu Collection<Thing> und alles funktioniert, aber lässt mich ohne eine DependencyObject Implementierung.

Vorschläge jemand?

Antwort

7

XAML will System.Collections.IList (das nicht-generische!) Für Sammlungen. Wenn Sie nur die generische Schnittstelle IList<T> implementieren, wird es nicht geschnitten.

Es erwartet auch öffentliche Add Methoden für die Klasse und leitet geeignete untergeordnete Typen für die Auflistung von Argumenten dieser Methoden ab. Der typische Ansatz besteht also darin, IList explizit zu implementieren - so dass seine Methode Add(object) nicht öffentlich ist und daher nicht vom XAML-Parser ausgewählt wird - und dann implizit IList<T> für alle untergeordneten Typen implementiert, die Sie unterstützen möchten.

Der Grund, warum es für die meisten integrierten Sammlungstypen (List<T>, Collection<T> usw.) funktioniert, liegt daran, dass sie dem obigen Muster folgen und sowohl generische als auch nicht generische Schnittstellen implementieren.

+0

Das ist es! Die Vanille-IList war, was ich vermisst habe, danke. – AnthonyWJones

+0

Perfekte Antwort, ich erwartete, IList zu denken, es wäre zu Liste bevorzugt, jetzt dank dieses Beitrags weiß ich, warum und bin glücklich mit der Verwendung der Liste als der Eigenschaftstyp. Ich bekomme die Unterstützung für die Entwurfszeit, die ich mit IList vermisst habe –

5

Kollektionen werden in der Regel in XAML verwendet, um ein ContentPropertyAttribute("PropertyName") auf der benutzerdefinierten Klasse zu definieren, wo in der Regel PropertyNameIList oder IList<T> ist.

[ContentProperty(SomeProp)] 
class SomeClass 
{ 
    //this is where subitems created in xaml would get added automatically 
    public IList<int> SomeProp { get; set; } 
} 

Wenn jedoch eine Klasse bietet keinen Wert für die ContentPropertyAttribute und implementiert jede Schnittstelle vom Typ IList<T>, IList, ICollection<T> oder ICollection, eine Eigenschaft des Namen „Items“ (falls vorhanden, und wenn die entsprechenden Typ, zB IList) wird durch Reflektion automatisch erkannt (zum Zwecke der Population Trog xaml), und das ist der Fall mit der Klasse Collection<T>.

Sie können sogar die Klasse in Reflector überprüfen, um sicherzustellen, dass keine Inhaltseigenschaft definiert ist.

Die Collection<T> Klasse hat dieses Objekt

protected IList<T> Items 
{ 
    get 
    { 
     return _items; 
    } 
} 

und das Hinzufügen von so etwas zu Ihrer Sammlung Art (auch wenn das Eigentum geschützt ist) ist genug, um es zu haben, verhält sich wie in XAML gewünscht.

Ich nehme an, das Verhalten wird auf diese Weise für die Abwärtskompatibilität implementiert.

+0

@ kky444: Danke für die Antwort. Wie ich bereits in meiner Frage ausgeführt habe, implementiere ich ICollection bereits, aber das scheint nicht zu helfen. Ich habe auch versucht, IList zu implementieren und eine Items-Eigenschaft mit einem ContentProperty-Attribut auszustellen, das die Klasse schmückt. Nichts davon funktioniert. (BTW IList ist eine ICollection nicht umgekehrt). – AnthonyWJones

+0

@AnthonyWJones: okay, zu wiederholen, setzen Sie nicht die Inhaltseigenschaft, verwenden IList , legen Sie eine Items-Eigenschaft des Typs IList , und das wird funktionieren, ich habe es gerade überprüft. Der xaml-Editor mag zwar argumentieren, das stimmt, aber es wird bauen. –

+0

@ kky444: +1 danke, dass ich es jetzt verstehe. – AnthonyWJones