WinUI3中ListView如何直接绑定模型对象而非模型的属性?
问题原因
MessageControl中的Message是普通CLR属性,不是依赖属性,WinUI3对x:Bind的实现比UWP更严格,在DataTemplate中无Path的全对象绑定场景,要求目标属性是支持变更通知的依赖属性,普通CLR属性无法正确接收绑定值,这也是你之前UWP代码能运行、迁移到WinUI3后失效的核心原因。- 代码存在笔误:
MessageControl对应的XAML文件中x:Class属性写为MessageClient.Controls.EmailControl,与后台类名MessageControl不一致,会导致控件初始化异常。 MainWindow中的Messages、TestMessage是公共字段而非属性,x:Bind仅支持绑定属性,且你在InitializeComponent执行完成后才给字段赋值,默认OneTime模式的绑定已经触发完成,无法拿到后续赋值的数据源。
解决方案
1. 将MessageControl的Message改为依赖属性
替换MessageControl后台的Message属性定义:
public sealed partial class MessageControl : UserControl { public static readonly DependencyProperty MessageProperty = DependencyProperty.Register( nameof(Message), typeof(Message), typeof(MessageControl), new PropertyMetadata(null)); /// <summary> /// 待展示的消息 /// </summary> public Message Message { get => (Message)GetValue(MessageProperty); set => SetValue(MessageProperty, value); } public MessageControl() { this.InitializeComponent(); } }
同时修改XAML的x:Class为正确的类名:
x:Class="MessageClient.Controls.MessageControl"
2. 修正MainWindow的绑定源定义
将公共字段改为属性,如需在InitializeComponent之后赋值,可实现INotifyPropertyChanged接口:
using System.ComponentModel; using System.Runtime.CompilerServices; public sealed partial class MainWindow : Window, INotifyPropertyChanged { private ObservableCollection<Message> _messages; public ObservableCollection<Message> Messages { get => _messages; set { _messages = value; OnPropertyChanged(); } } private Message _testMessage; public Message TestMessage { get => _testMessage; set { _testMessage = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public MainWindow() { this.InitializeComponent(); this.PopulateTestMessages(); } private void PopulateTestMessages() { this.Messages = new ObservableCollection<Message>(TestDataGenerator.GetTestMessages(10)); this.TestMessage = this.Messages.First(); } }
修改ListView的ItemsSource绑定为OneWay模式,确保数据源变更时能刷新:
<ListView x:Name="MessagesListView" ItemsSource="{x:Bind Messages, Mode=OneWay}">
修改完成后无Path的全对象绑定即可正常生效。
内容的提问来源于stack exchange,提问作者Michael Kintscher they-them
相关产品推荐
相关产品推荐

