自定义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
相关产品推荐
相关产品推荐

