You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WinUI3:如何在XAML中向集合属性添加自定义控件?排查报错

问题原因

出现Error XHR0015的核心原因是CustomControl1的Items依赖属性对应的ObservableCollection未预先实例化。在XAML解析过程中,当尝试向Items集合添加CustomControl2实例时,集合对象还处于null状态,WPF无法将元素添加到不存在的集合中,因此抛出该错误。

正确实现方式

要解决这个问题,需要确保Items集合在XAML解析前已经完成实例化,有两种可行的实现方式:

方式1:在依赖属性元数据中设置默认实例

注册Items依赖属性时,直接在PropertyMetadata中传入一个新的ObservableCollection<CustomControl2>实例作为默认值,确保控件被创建时集合就存在。

方式2:在CustomControl1的构造函数中初始化集合

在控件的构造函数里手动实例化Items集合,同样能保证XAML解析时集合已就绪。

完整代码示例

CustomControl1 后台代码

using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;

namespace YourNamespace
{
    public class CustomControl1 : Control
    {
        // 方式1:依赖属性元数据设置默认实例
        public static readonly DependencyProperty ItemsProperty =
            DependencyProperty.Register(
                nameof(Items),
                typeof(ObservableCollection<CustomControl2>),
                typeof(CustomControl1),
                new PropertyMetadata(new ObservableCollection<CustomControl2>()));

        public ObservableCollection<CustomControl2> Items
        {
            get => (ObservableCollection<CustomControl2>)GetValue(ItemsProperty);
            set => SetValue(ItemsProperty, value);
        }

        // 方式2:构造函数初始化(注释掉方式1的元数据默认值,启用这段代码即可)
        // public CustomControl1()
        // {
        //     Items = new ObservableCollection<CustomControl2>();
        // }

        static CustomControl1()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl1), new FrameworkPropertyMetadata(typeof(CustomControl1)));
        }
    }
}

CustomControl2 后台代码

using System.Windows;
using System.Windows.Controls;

namespace YourNamespace
{
    public class CustomControl2 : Control
    {
        static CustomControl2()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl2), new FrameworkPropertyMetadata(typeof(CustomControl2)));
        }
    }
}

控件模板(Generic.xaml)

CustomControl1 的模板

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:YourNamespace">

    <Style TargetType="{x:Type local:CustomControl1}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:CustomControl1}">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">
                        <!-- 通过TemplatedParent绑定到Items集合 -->
                        <ItemsControl ItemsSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Items}"/>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

CustomControl2 的模板

<Style TargetType="{x:Type local:CustomControl2}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:CustomControl2}">
                    <!-- 红色边框模板 -->
                    <Border BorderBrush="Red" BorderThickness="1" Margin="2" Padding="4"/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

最终XAML使用代码(与原代码一致,现在可正常运行)

<Window x:Class="YourNamespace.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:myControls="clr-namespace:YourNamespace"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <myControls:CustomControl1>
            <myControls:CustomControl1.Items>
                <myControls:CustomControl2></myControls:CustomControl2>
                <myControls:CustomControl2></myControls:CustomControl2>
                <myControls:CustomControl2></myControls:CustomControl2>
            </myControls:CustomControl1.Items>
        </myControls:CustomControl1>
    </Grid>
</Window>

内容的提问来源于stack exchange,提问作者Daniele Pugliese

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 05:15:42