C++/WinRT XAML中ComboBox设置DisplayMemberPath项显示为空
问题原因
- 自定义WinRT结构体
Info通过winrt::box_value装箱后,实际存入ComboBox项集合的是IReference<Info>类型对象,XAML运行时无法穿透装箱包装读取结构体内部的字段,因此DisplayMemberPath找不到对应属性,显示空白。 - 自定义
InfoItem运行时类仅添加[bindable]特性时,XAML运行时的反射机制无法获取类的属性定义:DisplayMemberPath是运行时解析的属性路径,不参与x:Bind的编译期绑定生成逻辑,因此读不到DisplayName值。此时移除DisplayMemberPath后显示类名或接口名,是XAML找不到显示属性时直接调用对象ToString()方法的默认行为。
可行解决方案
方案一(推荐,改动最小):使用ItemTemplate + 编译期x:Bind绑定
放弃使用DisplayMemberPath,直接为ComboBox定义项模板,通过x:Bind在编译期生成属性访问代码,完全绕开运行时反射的限制,无需给InfoItem实现额外接口。
- 首先在XAML页面头部添加项目命名空间映射:
<UserControl xmlns:local="using:my_app" ...>
- 修改ComboBox的XAML代码,替换
DisplayMemberPath为自定义项模板:
<ComboBox x:Name="cbInfo" ItemsSource="{x:Bind InfoList}"> <ComboBox.ItemTemplate> <DataTemplate x:DataType="local:InfoItem"> <TextBlock Text="{x:Bind DisplayName}"/> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox>
修改后直接编译运行即可正常显示DisplayName字段内容,后续如果需要同时显示Id等其他字段,直接在DataTemplate里调整布局即可,灵活性更高。
方案二:实现ICustomPropertyProvider接口支持DisplayMemberPath
如果必须使用DisplayMemberPath属性,需要让InfoItem实现ICustomPropertyProvider接口,为XAML运行时提供属性访问的反射入口:
- 修改
InfoItem.idl,声明实现接口:
import "Windows.UI.Xaml.Data.idl"; namespace my_app { [bindable] [default_interface] runtimeclass InfoItem : Windows.UI.Xaml.Data.ICustomPropertyProvider { InfoItem(); String Id; String DisplayName; } }
- 在
InfoItem.h中添加接口方法声明,在InfoItem.cpp中实现接口逻辑,核心是在GetCustomProperty方法中返回Id、DisplayName对应的属性访问实现,供XAML运行时调用读取值。该方案需要手写大量属性包装样板代码,无特殊需求不推荐使用。
注意事项
不要尝试直接将自定义WinRT结构体作为ComboBox项使用:结构体装箱后的IReference<T>包装类不会暴露自定义字段,无论怎么配置都无法通过DisplayMemberPath或常规绑定读取内部字段值,必须使用自定义运行时类作为项类型。
内容的提问来源于stack exchange,提问作者Waterman
相关产品推荐
相关产品推荐

