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

发布于 2024-07-26 05:58:31 字数 1031 浏览 5 评论 0原文

我有一个类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。 我认为创建 ICollectionINotifyCollectionChanged 等的实现并不难。 然后我可以从 DependencyObject 派生。

不幸的是,由于某种原因,ICollection 并没有削减它。 使用 ICollection 我得到“CollectionOfThings 不支持 Thing 作为内容”。 返回到 Collection ,一切正常,但我没有 DependencyObject 实现。

有人建议吗?

I have a class CollectionOfThings. As its name suggests its a simple collection of instances of the Thing class. Thing class has a public default constructor and two simple public get, set properties ID and DisplayName, both are string. CollectionOfThing also has public default constructor.

In XAML I would like to use markup like this:-

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

All is good as long as CollectionOfThings derives from a Collection type. However I want CollectionOfThings to also be a DependencyObject. I thought that's fine creating an implementation of ICollection<T>, INotifyCollectionChanged etc is not that hard. Then I can derive from DependencyObject.

Unfortunately ICollection<T> doesn't cut it for some reason. With ICollection<Thing> I get 'CollectionOfThings does not support Thing as content'. Go back to Collection<Thing> and everything works but leaves me without a DependencyObject implementation.

Suggestions anyone?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

稀香 2024-08-02 05:58:31

XAML 需要 System.Collections.IList (非泛型!)作为集合。 如果您只实现通用的 IList 接口,它不会削减它。

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

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

XAML wants System.Collections.IList (the non-generic one!) for collections. If you only implement generic IList<T> interface, it won't cut it.

It also expects to see public Add methods on the class, and derives suitable child types for the collection from arguments of those methods. So the typical approach is to explicitly implement IList - so that its Add(object) method isn't public, and thus isn't picked by XAML parser - and then implicitly implement IList<T> for all child types that you want to support.

The reason why it works for most built-in collection types (List<T>, Collection<T> etc) is because they follow the pattern above and implement both generic and non-generic interfaces.

水水月牙 2024-08-02 05:58:31

集合通常在 xaml 中使用,以便在自定义类上定义 ContentPropertyAttribute("PropertyName"),其中 PropertyName 通常是 IListIList

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

但是,如果类没有为 ContentPropertyAttribute 提供值,并且实现了 IListIList类型的任何接口>ICollectionICollection,通过反射检测名称为“Items”的属性(如果存在,并且类型适当,例如 IList)自动(为了通过 xaml 进行填充),Collection 类就是这种情况。

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

Collection 类具有此属性

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

,并且向您的集合类型添加类似的内容(即使该属性受保护)就足以使其在 xaml 中按照所需的方式运行。

我想这种行为是为了向后兼容而实现的。

Collections are usually used in xaml so as to define a ContentPropertyAttribute("PropertyName") on the custom class where PropertyName is usually IList or IList<T>.

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

However, if a class does not provide a value for the ContentPropertyAttribute, and implements any interface of type IList<T>, IList, ICollection<T> or ICollection, a property of name "Items" (if present, and if of appropriate type, e.g. IList) is detected trough reflection automatically (for the purpose of population trough xaml), and that is the case with the Collection<T> class.

You can even check the class in Reflector to make sure it has no content property defined.

The Collection<T> class has this property

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

and adding something like that to your collection type (even if the property is protected) is enough to have it behave as desired in xaml.

I suppose the behavior is implemented in that way for backward compatibility.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文