WPF MVVM如何将UserControl内部的SelectedItem绑定到外部TextBox
问题根因
- PersonViewModel的
SelectedPerson属性未实现INotifyPropertyChanged通知,属性值变化时无法同步到UI - PersonView构造函数中硬编码创建了独立的
PersonViewModel实例并赋值给自身DataContext,导致和主窗口的数据源实例不统一,自然无法拿到内部选中的值 - PersonModel的ID属性未实现属性变更通知,若后续需要修改ID会无法同步显示
修复步骤
1. 改造PersonViewModel,添加属性变更通知
首先让PersonViewModel实现INotifyPropertyChanged接口,给SelectedPerson加变更通知:
public class PersonViewModel : INotifyPropertyChanged { public PersonViewModel() { Persons = new ObservableCollection<PersonModel>(); LoadPersons(); } public ObservableCollection<PersonModel> Persons { get; set; } private PersonModel _selectedPerson; public PersonModel SelectedPerson { get => _selectedPerson; set { _selectedPerson = value; RaisePropertyChanged(nameof(SelectedPerson)); } } public void LoadPersons() { ObservableCollection<PersonModel> persons = new ObservableCollection<PersonModel>(); persons.Add(new PersonModel { ID = 1, Forname = "Thomas", Surname = "Sogen" }); persons.Add(new PersonModel { ID = 2, Forname = "Seth", Surname = "Xu" }); persons.Add(new PersonModel { ID = 3, Forname = "Derik", Surname = "Mayers" }); persons.Add(new PersonModel { ID = 4, Forname = "Daisy", Surname = "Doros" }); Persons = persons; } public event PropertyChangedEventHandler PropertyChanged; private void RaisePropertyChanged(string property) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(property)); } } }
2. 移除PersonView内部硬编码的DataContext赋值
删掉PersonView.xaml.cs构造函数里的DataContext设置行,UserControl的数据源由父容器提供:
public partial class PersonView : UserControl { public PersonView() { InitializeComponent(); // 删掉原有的DataContext赋值行 // this.DataContext = new MVVMExample.ViewModel.PersonViewModel(); } }
3. 给MainWindow设置统一的数据源
在MainWindow的构造函数中实例化PersonViewModel,赋值给自身的DataContext,这样主窗口的控件和内部的PersonView会共享同一个数据源实例:
public MainWindow() { InitializeComponent(); this.DataContext = new MVVMExample.ViewModel.PersonViewModel(); }
4. 给MainWindow的TextBox添加正确绑定
修改MainWindow.xaml中的三个TextBox的绑定路径:
<TextBox Grid.Row="0" Text="{Binding SelectedPerson.ID}"/> <TextBox Grid.Row="1" Text="{Binding SelectedPerson.Forname}"/> <TextBox Grid.Row="2" Text="{Binding SelectedPerson.Surname}"/>
可选优化:给PersonView中DataGrid的SelectedItem绑定加上双向绑定声明,确保选中变化能及时同步到ViewModel:
SelectedItem="{Binding SelectedPerson, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
补充说明
完全不需要把主窗口的TextBox放到PersonView内部,只要保证所有绑定控件共享同一个ViewModel实例、需要通知的属性都正确实现了INotifyPropertyChanged接口,就能实现跨控件的属性同步。
内容的提问来源于stack exchange,提问作者FloSu
相关产品推荐
相关产品推荐

