如何取消ComboBox SelectionChanged事件?

是否有一种简单的方法来提示用户确认combobox选择更改,如果用户选择否,则不处理更改?

我们有一个combobox,更改选择将导致数据丢失。 用户基本上选择一种类型,然后他们就能输入该类型的属性。 如果他们更改了类型,我们会清除所有属性,因为它们可能不再适用。 问题是,在选择下,您再次引发SelectionChanged事件。

这是一个片段:

 if (e.RemovedItems.Count > 0) { result = MessageBox.Show("Do you wish to continue?", "Warning", MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result == MessageBoxResult.No) { if (e.RemovedItems.Count > 0) ((ComboBox)sender).SelectedItem = e.RemovedItems[0]; else ((ComboBox)sender).SelectedItem = null; } } 

我有两个解决方案,我都不喜欢。

  1. 用户选择“否”后 ,删除SelectionChanged事件处理程序,更改所选项目,然后再次注册SelectionChanged事件处理程序。 这意味着您必须保留类中事件处理程序的引用,以便您可以添加和删除它。

  2. 创建ProcessSelectionChanged布尔值作为类的一部分。 始终在事件处理程序的开头检查它。 在我们更改选择之前将其设置为false,然后将其重置为true。 这将工作,但我不喜欢使用标志基本上使事件处理程序无效。

任何人都有替代解决方案或改进我提到的?

我记得有一段时间需要这样做。 在我找到一个好的解决方案之前,我花了大约一周的研究和尝试。 我在这里发布了:

WPF:取消数据绑定列表框中的用户选择?

仅供参考,这是一个基于MV-VM的解决方案(如果你没有使用MV-VM模式,你应该是!)

我发现这个很好的实现。

  private bool handleSelection=true; private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (handleSelection) { MessageBoxResult result = MessageBox.Show ("Continue change?", MessageBoxButton.YesNo); if (result == MessageBoxResult.No) { ComboBox combo = (ComboBox)sender; handleSelection = false; combo.SelectedItem = e.RemovedItems[0]; return; } } handleSelection = true; } 

来源: http : //www.amazedsaint.com/2008/06/wpf-combo-box-cancelling-selection.html

也许创建一个派生自ComboBox的类,并重写OnSelectedItemChanged (或OnSelectionChangeCommitted 。)

如果选择无效,则在SelectionChanged事件处理程序中进行validation允许您取消逻辑,但我不知道取消事件或项目选择的简单方法。

我的解决方案是对WPFcombobox进行子类化,并为SelectionChanged事件添加内部处理程序。 每当事件触发时,我的私有内部处理程序都会引发自定义SelectionChanging事件。

如果在相应的SelectionChangingEventArgs上设置了Cancel属性,则不会引发该事件,并且SelectedIndex将还原为其先前的值。 否则会引发一个新的SelectionChanged ,它会遮蔽基本事件。 希望这有帮助!


SelectionChanging事件的EventArgs和handler委托:

 public class SelectionChangingEventArgs : RoutedEventArgs { public bool Cancel { get; set; } } public delegate void SelectionChangingEventHandler(Object sender, SelectionChangingEventArgs e); 

ChangingComboBox类的实现:

 public class ChangingComboBox : ComboBox { private int _index; private int _lastIndex; private bool _suppress; public event SelectionChangingEventHandler SelectionChanging; public new event SelectionChangedEventHandler SelectionChanged; public ChangingComboBox() { _index = -1; _lastIndex = 0; _suppress = false; base.SelectionChanged += InternalSelectionChanged; } private void InternalSelectionChanged(Object s, SelectionChangedEventArgs e) { var args = new SelectionChangingEventArgs(); OnSelectionChanging(args); if(args.Cancel) { return; } OnSelectionChanged(e); } public new void OnSelectionChanged(SelectionChangedEventArgs e) { if (_suppress) return; // The selection has changed, so _index must be updated _index = SelectedIndex; if (SelectionChanged != null) { SelectionChanged(this, e); } } public void OnSelectionChanging(SelectionChangingEventArgs e) { if (_suppress) return; // Recall the last SelectedIndex before raising SelectionChanging _lastIndex = (_index >= 0) ? _index : SelectedIndex; if(SelectionChanging == null) return; // Invoke user event handler and revert to last // selected index if user cancels the change SelectionChanging(this, e); if (e.Cancel) { _suppress = true; SelectedIndex = _lastIndex; _suppress = false; } } } 

我不相信使用调度程序发布(或延迟)属性更新是一个很好的解决方案,它更像是一种并非真正需要的解决方法。 以下解决方案我完全mvvm,它不需要调度程序。

  • 首先使用显式绑定模式绑定SelectedItem。 //这使我们能够决定是使用UpdateSource()方法提交对VM的更改还是使用 UI中的UpdateTarget()方法进行恢复
  • 接下来,向VM添加一个方法,确认是否允许更改(此方法可以包含提示用户确认并返回bool的服务)。

在挂钩到SelectionChanged事件后面的视图代码中,根据VM.ConfirmChange(…)方法是否返回值更新Source(即VM)或Target(即V),如下所示:

  private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { if(e.AddedItems.Count != 0) { var selectedItem = e.AddedItems[0]; if (e.AddedItems[0] != _ViewModel.SelectedFormatType) { var comboBoxSelectedItemBinder = _TypesComboBox.GetBindingExpression(Selector.SelectedItemProperty); //_TypesComboBox is the name of the ComboBox control if (_ViewModel.ConfirmChange(selectedItem)) { // Update the VM.SelectedItem property if the user confirms the change. comboBoxSelectedItemBinder.UpdateSource(); } else { //otherwise update the view in accordance to the VM.SelectedItem property comboBoxSelectedItemBinder.UpdateTarget(); } } } } 

在WPF中动态设置对象

  if (sender.IsMouseCaptured) { //perform operation }