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

私には2つの解決策がありますが、どちらも好きではありません。

  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

から派生したクラスを作成しComboBoxOnSelectedItemChanged(またはOnSelectionChangeCommitted.)

于 2011-12-22T18:30:53.460 に答える
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);

変更 ComboBox クラスの実装:

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 に答える