在 XAML 中设置 IEnumerable DependencyProperty 时会引发错误

发布于 2024-09-06 14:46:20 字数 1342 浏览 1 评论 0原文

我有一个继承自 Control 的自定义控件 Workspace,其中有一个 DependencyProperty,我需要包含用户指定的 IEnumerable< ;IFoo> (我也尝试将其设为非泛型 IEnumerable)。

Public Shared ReadOnly FoosProperty As DependencyProperty = DependencyProperty.Register("Foos", GetType(IEnumerable(Of IFoo)), GetType(Workspace), New FrameworkPropertyMetadata())
Public Property Foos() As IEnumerable(Of IFoo)
    Get
        Return CType(Me.GetValue(FoosProperty), IEnumerable(Of IFoo))
    End Get
    Set(ByVal value As IEnumerable(Of IFoo))
        Me.SetValue(FoosProperty, CType(value, IEnumerable(Of IFoo)))
    End Set
End Property

当我在代码中创建并设置 IFoo 数组时,一切都运行良好,但是当我尝试在 XAML 中添加它们时,我收到错误。如果我添加一个 IFoo,我会收到错误

  1. “'FooItem' 不是属性 'Foos' 的有效值”。

在运行时。如果我尝试添加多个 IFoo 项,我会在编译时收到三个错误

  1. 对象“Workspace”已经有一个子项,无法添加“FooItem”。 “工作区”只能接受一个孩子。
  2. 属性“Foos”不支持“FooItem”类型的值。
  3. 属性“Foos”被设置多次。

我读到的错误意味着 WPF 没有像通常那样将 xaml 转换为项目数组。以下是我尝试在 XAML 中添加项目的方法,

<Workspace>
    <Workspace.Foos>
        <FooItem />
        <FooItem />
    </Workspace.Foos>
</Workspace>

我过去创建过类似的 DependencyProperties 并且从未遇到过问题,所以我猜我错过了一些简单的东西。

感谢您的帮助!

I have a custom control Workspace that inherits from Control and within it is a DependencyProperty that I need to contain a user-specified IEnumerable<IFoo> (I have also tried making it an non-generic IEnumerable).

Public Shared ReadOnly FoosProperty As DependencyProperty = DependencyProperty.Register("Foos", GetType(IEnumerable(Of IFoo)), GetType(Workspace), New FrameworkPropertyMetadata())
Public Property Foos() As IEnumerable(Of IFoo)
    Get
        Return CType(Me.GetValue(FoosProperty), IEnumerable(Of IFoo))
    End Get
    Set(ByVal value As IEnumerable(Of IFoo))
        Me.SetValue(FoosProperty, CType(value, IEnumerable(Of IFoo)))
    End Set
End Property

Everything works perfectly when I create and set an array of IFoo in code but when I try to add them in XAML I get errors. If I add a single IFoo I get the error

  1. "'FooItem' is not a valid value for property 'Foos'."

at run time. If I try to add multiple IFoo items I get three errors at compile time

  1. The object 'Workspace' already has a child and cannot add 'FooItem'. 'Workspace' can accept only one child.
  2. Property 'Foos' does not support values of type 'FooItem'.
  3. The property 'Foos' is set more than once.

I read the errors to mean that WPF isn't converting the xaml to an array of items like it normally would. Here is how I'm trying to add the items in XAML

<Workspace>
    <Workspace.Foos>
        <FooItem />
        <FooItem />
    </Workspace.Foos>
</Workspace>

I have created similar DependencyProperties in the past and never had a problem so I'm guessing I'm missing something simple.

Thanks for any help!

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

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

发布评论

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

评论(1

情绪失控 2024-09-13 14:46:20

为了能够添加多个元素,集合属性必须是 IListIDictionary。当它是 IEnumerable 时,XAML 解析器尝试将第一个值分配给属性本身(而不是像列表那样调用 Add),并对连续项感到困惑。这就是你错误的根源。

另外,如果您想从 XAML 填充集合,请确保您的列表已实例化并且一开始就不是 null,因为 XAML 不会为您实例化列表,它只会对其调用 Add 。因此,为了避免 NullReferenceException,请删除 IList 属性上的 setter 并从构造函数实例化列表。

它不一定是依赖属性:

private readonly ObservableCollection<FooItem> _foos = new ObservableCollection<FooItem>();

public ObservableCollection<FooItem> Foos
{
    get { return _foos; }
}

To be able to add multiple elements the collection property has to be IList or IDictionary. When it is IEnumerable XAML parser tries to assign first value to the property itself (instead of calling Add like with lists) and gets confused about consecutive items. This is the source of your errors.

Also, if you want to populate collection from XAML, make sure that your list is instantiated and not null to begin with, since XAML will not instantiate a list for you, it'll just call Add on it. So to avoid NullReferenceException, get rid of setter on your IList property and instantiate list from constructor.

It doesn't have to be dependency property:

private readonly ObservableCollection<FooItem> _foos = new ObservableCollection<FooItem>();

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