在依赖项对象上启用XAML中的直接内容创建

时间:2009-07-08 19:43:51

标签: c# silverlight xaml silverlight-3.0 dependencyobject

我有一个班级CollectionOfThings。正如其名称所示,它是Thing类的简单实例集合。 Thing类有一个公共默认构造函数和两个简单​​的公共get,set属性IDDisplayName,两者都是字符串。 CollectionOfThing也有公共默认构造函数。

在XAML中,我想使用这样的标记: -

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

只要CollectionOfThings派生自Collection类型,一切都很好。不过,我希望CollectionOfThings也是DependencyObject。我认为创建ICollection<T>INotifyCollectionChanged等实现并不是那么难。然后我可以从DependencyObject派生。

不幸的是ICollection<T>因某些原因没有删除它。使用ICollection<Thing>我得到'CollectionOfThings不支持Thing as content'。回到Collection<Thing>,一切正常,但没有DependencyObject实施。

建议任何人?

2 个答案:

答案 0 :(得分:7)

XAML希望System.Collections.IList(非通用的!)用于集合。如果您只实现通用IList<T>接口,则不会删除它。

它还希望在类上看到公共Add方法,并从这些方法的参数中为集合派生合适的子类型。因此,典型的方法是显式实现IList - 以使其Add(object)方法不公开,因此不被XAML解析器选中 - 然后为所有子项隐式实现IList<T>您想要支持的类型。

它适用于大多数内置集合类型(List<T>Collection<T>等)的原因是因为它们遵循上述模式并实现了通用和非通用接口。

答案 1 :(得分:5)

通常在xaml中使用集合,以便在ContentPropertyAttribute("PropertyName")通常为PropertyNameIList的自定义类中定义IList<T>

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

但是,如果某个类没有为ContentPropertyAttribute提供值,并且实现了IList<T>IListICollection<T>ICollection类型的任何接口,名称为“Items”的属性(如果存在,如果是适当的类型,例如IList)通过自动反射检测(为了人口通过xaml的目的),{{1 }。class。

您甚至可以在Reflector中检查类,以确保它没有定义内容属性。

Collection<T>类具有此属性

Collection<T>

并将类似内容添加到您的集合类型中(即使属性受到保护)足以让它在xaml中按照需要运行。

我认为这种行为是以这种方式实现的,以实现向后兼容。