[英]How to catch PropertyChanged event, for an object instance that is bound to the SelectedItem of a listbox
我正在尝试用 C# 学习 WPF,所以如果这个问题很幼稚,请耐心等待。
到目前为止,一切正常:
我现在想要实现的是以某种方式侦听 SelectedPerson 的 PropertyChanged 事件,因此在更改 TextBox 的内容后,我可以运行一些代码。 我希望代码在更改绑定属性后运行一次(例如编辑停止后 ListBox 的更新方式),所以我真的不想听 TextBox 的 TextChanged 事件。
我可以使用 SelectedPerson 的 PropertyChanged 事件,所以无论当前 SelectedItem 是哪个 Person 我都可以监听 PropertyChanged 事件,还是必须对 ObservableCollection 中的每个 Person 实例使用 PropertyChanged 事件? (或者……不同的东西?)
作为参考,这里是上述所有代码的相关摘录
人物类
public class Person : INotifyPropertyChanged
{
...
public string FirstName
{
get { return _firstName; }
set { _firstName = value; OnPropertyChanged("FirstName"); OnPropertyChanged("FullName"); }
}
public string LastName
{
get { return _lastName; }
set { _lastName = value; OnPropertyChanged("LastName"); OnPropertyChanged("FullName"); }
}
public string FullName { get { return $"{LastName} {FirstName}"; } }
}
主窗口
public partial class MainWindow : Window, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection<Person> People { get; set; }
private Person _selectedPerson;
public Person SelectedPerson
{
get { return _selectedPerson; }
set { _selectedPerson = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedPerson")); }
}
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
People = new ObservableCollection<Person>
{
new Person { FirstName = "John", LastName = "Doe" },
new Person { FirstName = "Jane", LastName = "Smith" }
};
}
}
和 XAML 项目
...
<ListBox Grid.Row="1" Grid.Column="1" ItemsSource="{Binding Path=People}" SelectedItem="{Binding SelectedPerson, Mode=TwoWay}" DisplayMemberPath="FullName" Margin="10"/>
<StackPanel Grid.Row="1" Grid.Column="2" Orientation="Vertical" Margin="10" VerticalAlignment="Center">
<StackPanel Orientation="Horizontal">
<TextBlock Text="First Name" HorizontalAlignment="Right" Margin="10"/>
<TextBox Text="{Binding SelectedPerson.FirstName, Mode=TwoWay}" Width="120" Margin="10"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Last Name" HorizontalAlignment="Right" Margin="10"/>
<TextBox Text="{Binding SelectedPerson.LastName, Mode=TwoWay}" Width="120" Margin="10"/>
</StackPanel>
</StackPanel>
...
更改TextBox
,将运行其绑定的属性设置器。 即运行 FirstName.set 或 LastName.set。 你当然知道这一点。 您还可以从 setter 运行额外的代码,该代码仅在TextBox
更改时运行。 为防止多次运行您的代码,请根据支持字段值检查新值,如果匹配,则返回。
我可以使用SelectedPerson的PropertyChanged事件吗,所以无论哪个Person是当前SelectedItem我都可以监听PropertyChanged事件
是的。 但是,你需要添加代码也认购(“听”)到PropertyChanged
你的活动MainWindow
,这样就可以在这个变化的响应SelectedPerson
属性值。 也就是说,当该属性值更改时,您需要取消订阅先前设置的Person
对象的PropertyChanged
事件,并订阅现在设置的Person
对象上的事件。
您在正确的轨道上更喜欢在视图模型级别而不是视图本身(例如TextBox
)执行此操作。 将所有非 UI 逻辑放在视图模型中的次数越多越好。
请注意,这实际上意味着您最好拥有一个“主”视图模型,它保存Person
对象和当前选定项目的列表,而不是让您的窗口实现INotifyPropertyChanged
。
另外,它的价值,我发现它工作得更好(对我来说,反正)来实现一个基类,视图模型对象继承,它有一个辅助方法来更新支持字段,提高PropertyChanged
是必要的,并且提供了一个可选的回调允许响应属性更改,而不必实际订阅事件(至少在您总是想响应的情况下……在这个特定示例中,这可能无济于事,因为您只想在Person
对象处于当前选择的一个)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.