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

自定义MediaFileItemControl绑定ListBox出现XBF语法错误,求解决方案

问题:XBF生成器语法错误0x80004005排查与修复

问题场景

实现了如下自定义控件:

public sealed class MediaFileItemControl : Control
{
    public static readonly DependencyProperty MediaFileProperty =
        DependencyProperty.Register(nameof(MediaFile), typeof(StorageFile), typeof(MediaFileItemControl), new PropertyMetadata(null));

    public MediaFileItemControl()
    {
        DefaultStyleKey = typeof(MediaFileItemControl);
    }

    public StorageFile MediaFile
    {
        get => (StorageFile)GetValue(MediaFileProperty);
        set => SetValue(MediaFileProperty, value);
    }
}

并编写了对应的样式:

<!-- Generic.xaml -->
<Style TargetType="controls:MediaFileItemControl" >
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="controls:MediaFileItemControl">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{TemplateBinding MediaFile.Name}" />
                    <TextBlock Text="{TemplateBinding MediaFile.Path}" />
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

最后在ListBox中使用该控件:

<ListBox ItemsSource="{x:Bind ViewModel.MediaFiles, Mode=OneWay}">
    <ListBox.ItemTemplate>
        <DataTemplate x:DataType="win_storage:StorageFile" xmlns:win_storage="using:Windows.Storage">
            <controls:MediaFileItemControl MediaFile="{x:Bind}" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

编译时Generic.xaml出现错误:

The XAML Binary Format (XBF) generator reported syntax error '0x80004005'

错误原因

TemplateBinding不支持链式属性访问(即MediaFile.Name这种嵌套属性写法)。TemplateBinding的设计仅支持直接绑定到控件自身的依赖属性,无法深入访问属性的子属性,这就是触发XBF编译语法错误的核心原因。

正确实现方式

方法一:替换为RelativeSource绑定

将Generic.xaml中的TemplateBinding替换为基于TemplatedParent的RelativeSource绑定,这种方式支持嵌套属性访问:

<!-- Generic.xaml -->
<Style TargetType="controls:MediaFileItemControl" >
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="controls:MediaFileItemControl">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding MediaFile.Name, RelativeSource={RelativeSource TemplatedParent}}" />
                    <TextBlock Text="{Binding MediaFile.Path, RelativeSource={RelativeSource TemplatedParent}}" />
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

方法二:新增依赖属性(推荐,更符合控件设计规范)

在自定义控件中新增FileName和FilePath依赖属性,直接暴露需要绑定的子属性,这样可以继续使用TemplateBinding:

修改后的C#控件代码:

public sealed class MediaFileItemControl : Control
{
    public static readonly DependencyProperty MediaFileProperty =
        DependencyProperty.Register(nameof(MediaFile), typeof(StorageFile), typeof(MediaFileItemControl), 
            new PropertyMetadata(null, OnMediaFileChanged));

    public static readonly DependencyProperty FileNameProperty =
        DependencyProperty.Register(nameof(FileName), typeof(string), typeof(MediaFileItemControl), new PropertyMetadata(string.Empty));

    public static readonly DependencyProperty FilePathProperty =
        DependencyProperty.Register(nameof(FilePath), typeof(string), typeof(MediaFileItemControl), new PropertyMetadata(string.Empty));

    public MediaFileItemControl()
    {
        DefaultStyleKey = typeof(MediaFileItemControl);
    }

    public StorageFile MediaFile
    {
        get => (StorageFile)GetValue(MediaFileProperty);
        set => SetValue(MediaFileProperty, value);
    }

    public string FileName
    {
        get => (string)GetValue(FileNameProperty);
        private set => SetValue(FileNameProperty, value);
    }

    public string FilePath
    {
        get => (string)GetValue(FilePathProperty);
        private set => SetValue(FilePathProperty, value);
    }

    private static void OnMediaFileChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var control = (MediaFileItemControl)d;
        var newFile = e.NewValue as StorageFile;
        control.FileName = newFile?.Name ?? string.Empty;
        control.FilePath = newFile?.Path ?? string.Empty;
    }
}

修改后的Generic.xaml样式:

<!-- Generic.xaml -->
<Style TargetType="controls:MediaFileItemControl" >
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="controls:MediaFileItemControl">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{TemplateBinding FileName}" />
                    <TextBlock Text="{TemplateBinding FilePath}" />
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 14:57:42