26

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

我们有一个组合框,更改选择会导致数据丢失。基本上,用户选择一种类型,然后他们就可以输入该类型的属性。如果他们更改类型,我们将清除所有属性,因为它们可能不再适用。问题是在选择下您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。这会起作用,但我不喜欢使用标志来基本上使事件处理程序无效。

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

4

5 回答 5

24

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

 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

于 2012-01-12T23:06:53.873 回答
1

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

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

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


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

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;
        }
    }
}
于 2012-03-06T18:58:10.993 回答
1

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

于 2011-12-22T18:30:53.460 回答
1

在 WPF 中动态设置对象

    if (sender.IsMouseCaptured)
    {
      //perform operation
    }
于 2018-08-13T12:27:57.273 回答
0

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

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

在视图代码中挂钩 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();
                }
            }
        }
    }
于 2017-02-28T10:38:24.557 回答