【问题标题】:How to cancel a ComboBox SelectionChanged event?如何取消 ComboBox SelectionChanged 事件?
【发布时间】:2011-12-22 18:12:32
【问题描述】:

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

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

这是一个sn-p:

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. 用户选择'No'后,移除SelectionChanged事件处理器,更改选中项,然后重新注册SelectionChanged事件处理器。这意味着您必须保留类中事件处理程序的引用,以便您可以添加和删除它。

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

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

【问题讨论】:

  • 它很旧但stackoverflow.com/questions/314503/… 有帮助吗?
  • 我正要说你为什么不使用javascript来做这个检查,但后来我注意到它的winform应用程序很抱歉:(。
  • bool 标志是标准解决方案。不让用户通过简单地不将其包含在 Items 集合中来选择项目是很好的解决方案。
  • 不知道你的意思是不包括项目集合中的项目。列表中没有一个特定项目导致此问题,它是对所选项目的任何更改。我想让他们更改类型,ComboBox 包含可用类型的列表,但如果他们确实选择了新类型,我想先警告他们并允许他们退出。
  • 注意:SelectionChanged 不是 WinForms ComboBox 上的事件处理程序,只有 WPF ComboBox,所以我正在编辑问题和标签以修复。

标签: c# wpf combobox selectionchanged


【解决方案1】:

我发现了这个很好的实现。

 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

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 是的,我也在想这个,我想看看实现。
    【解决方案3】:

    SelectionChanged 事件处理程序中验证允许您在选择无效时取消逻辑,但我不知道取消事件或项目选择的简单方法。

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

    如果在相应的SelectionChangingEventArgs 上设置了Cancel 属性,则不会引发事件,SelectedIndex 会恢复为之前的值。否则会引发一个新的SelectionChanged,它会影响基本事件。希望这会有所帮助!


    SelectionChanging 事件的 EventArgs 和处理程序委托:

    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;
            }
        }
    }
    

    【讨论】:

      【解决方案4】:

      在WPF中动态设置对象

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

      【讨论】:

      • This works well when the selection changed events triggers selection change event in other controls.区分系统和用户交互变化。
      【解决方案5】:

      我不认为使用调度程序发布(或延迟)属性更新是一个好的解决方案,它更多的是一种实际上并不需要的解决方法。以下解决方案我完全 mvvm,它不需要调度程序。

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

      在view后面的代码中钩住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();
                      }
                  }
              }
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-03-17
        • 2014-03-26
        • 1970-01-01
        • 2014-05-02
        • 2012-02-03
        • 2010-12-10
        • 2012-01-29
        相关资源
        最近更新 更多