Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何取消组合框SelectionChanged事件?_C#_Wpf_Combobox_Selectionchanged - Fatal编程技术网

C# 如何取消组合框SelectionChanged事件?

C# 如何取消组合框SelectionChanged事件?,c#,wpf,combobox,selectionchanged,C#,Wpf,Combobox,Selectionchanged,是否有一种简单的方法提示用户确认组合框选择的更改,如果用户选择“否”,则不处理更改 我们有一个组合框,更改选择将导致数据丢失。基本上,用户选择一种类型,然后就可以输入该类型的属性。如果它们更改了类型,我们将清除所有属性,因为它们可能不再适用。问题在于,要在选择项下再次引发SelectionChanged事件 以下是一个片段: if (e.RemovedItems.Count > 0) { result = MessageBox.Show("Do you wish to contin

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

我们有一个组合框,更改选择将导致数据丢失。基本上,用户选择一种类型,然后就可以输入该类型的属性。如果它们更改了类型,我们将清除所有属性,因为它们可能不再适用。问题在于,要在选择项下再次引发
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;
    }
}
我有两种解决方案,我都不喜欢

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

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


  • 有人对我提到的解决方案有替代方案或改进吗?

    可能会创建一个派生自
    组合框的类,并重写
    OnSelectedItemChanged
    (或
    OnSelectionChangeCommitted

    我发现了这个很好的实现

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

    来源:

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

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

    如果在相应的
    SelectionChangingEventArgs
    上设置了
    Cancel
    属性,则不会引发事件,并且
    SelectedIndex
    将恢复为其以前的值。否则,将引发一个新的
    SelectionChanged
    ,该选项将隐藏基本事件。希望这有帮助


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

    public class SelectionChangingEventArgs : RoutedEventArgs
    {
        public bool Cancel { get; set; }
    }
    
    public delegate void 
    SelectionChangingEventHandler(Object sender, SelectionChangingEventArgs e);
    
    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;
            }
        }
    }
    
    更改ComboBox类实现:

    public class SelectionChangingEventArgs : RoutedEventArgs
    {
        public bool Cancel { get; set; }
    }
    
    public delegate void 
    SelectionChangingEventHandler(Object sender, SelectionChangingEventArgs e);
    
    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;
            }
        }
    }
    

    我不认为使用dispatcher发布(或延迟)属性更新是一个好的解决方案,它更多的是一种不需要的解决方法。下面的解决方案完全支持mvvm,并且不需要调度器

    • 首先使用显式绑定模式绑定SelectedItem//这使我们能够决定是使用UpdateSource()方法提交对VM的更改,还是在UI中使用UpdateTarget()方法恢复
    • 接下来,向VM添加一个方法,用于确认是否允许更改(该方法可以包含一个服务,提示用户确认并返回bool)
    在视图中,代码隐藏钩住SelectionChanged事件,并根据VM.ConfirmChange(…)方法是否返回如下值更新源(即VM)或目标(即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
        }
    

    它很旧,但会有帮助吗?我正要说为什么不使用javascript进行此检查,但后来我注意到它的winform应用程序抱歉:(.bool标志是标准解决方案。不让用户通过简单地不将项目包括在项目集合中来选择项目是一个好的解决方案。不确定不将项目包括在项目集合中是什么意思。列表中没有一个特定项目会导致此问题,这是对所选项目的任何更改。我想允许他们更改类型,组合框包含可用类型的列表,但如果他们确实选择了新类型,我想首先警告他们并允许他们退出。注意:
    SelectionChanged
    不是WinForms
    ComboBox
    上的事件处理程序,只有WPF
    ComboBox
    ,因此我正在编辑要修复的问题和标记。是的我也在想这个问题,我希望看到一个实现。当选择更改事件触发其他控件中的选择更改事件时,这很有效。区分系统和用户交互更改。