WPF ListBox设置NotifyOnSourceUpdated后SourceUpdated事件未触发
解决WPF ListBox SourceUpdated事件未触发的问题
你遇到的问题其实是对SourceUpdated事件的触发时机理解有偏差哦!咱们先理清楚这个事件到底什么时候会触发,再给你对应的解决方案。
为什么SourceUpdated没触发?
SourceUpdated事件监听的是绑定的源属性本身的引用变化,而不是集合内部项的添加/删除/修改。换句话说:
- 当你给
ListBox.ItemsSource绑定的Collection属性重新赋值(比如Collection = new ObservableCollection<string>())时,源属性的引用变了,这时候SourceUpdated才会触发。 - 而你现在是向已有的
ObservableCollection里添加项,这属于集合内部的变更,ObservableCollection通过INotifyCollectionChanged接口通知UI更新,所以ListBox能显示新项,但这不会触发SourceUpdated事件。
正确的解决方案
根据你的需求,分两种情况处理:
1. 要监听集合内部项的变化(添加/删除/修改)
直接订阅ObservableCollection的CollectionChanged事件就可以了,这才是监听集合内部变更的正确方式:
public partial class MainWindow : Window, INotifyPropertyChanged { public ObservableCollection<string> Collection { get; set; } public MainWindow() { InitializeComponent(); Collection = new ObservableCollection<string>(); // 订阅集合变更事件 Collection.CollectionChanged += Collection_CollectionChanged; DataContext = this; } private void Collection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { // 根据变更类型处理逻辑 switch (e.Action) { case NotifyCollectionChangedAction.Add: foreach (var newItem in e.NewItems) { Console.WriteLine($"新增了项:{newItem}"); } break; case NotifyCollectionChangedAction.Remove: foreach (var oldItem in e.OldItems) { Console.WriteLine($"移除了项:{oldItem}"); } break; // 还可以处理Move、Replace等类型 } } // 如果你需要重新赋值Collection,要实现INotifyPropertyChanged通知UI public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
2. 确实需要触发SourceUpdated事件(监听集合引用变化)
如果你是想监听Collection属性本身被重新赋值的情况,那需要确保:
- 绑定设置了
NotifyOnSourceUpdated="true"(你已经做了) Collection属性实现INotifyPropertyChanged接口,这样重新赋值时UI能收到通知,同时触发SourceUpdated
XAML绑定示例:
<ListBox ItemsSource="{Binding Collection, NotifyOnSourceUpdated=True}" SourceUpdated="ListBox_SourceUpdated"/>
然后在代码里重新赋值Collection并触发通知:
private void ResetCollectionBtn_Click(object sender, RoutedEventArgs e) { // 重新赋值集合 Collection = new ObservableCollection<string> { "新项1", "新项2" }; // 通知UI属性变化 OnPropertyChanged(nameof(Collection)); } // 处理SourceUpdated事件 private void ListBox_SourceUpdated(object sender, DataTransferEventArgs e) { Console.WriteLine("SourceUpdated事件触发了!"); }
这样当你点击按钮重新赋值Collection时,SourceUpdated就会正常触发了。
内容的提问来源于stack exchange,提问作者Rob.Ak
相关产品推荐
相关产品推荐

