2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

WPFのComboBoxの選択をロールバックする

Last updated at Posted at 2019-09-02

概要

ComboBoxの選択を変更した際に、なんらかの理由でロールバック(選択前の状態に戻す)方法です。コードビハインドで処理するのが常套(?)なのかもしれませんが、MVVMを使用しており、処理が散逸するのを避けたかったという理由があります。

回避方法1は実現はできましたが、今一つ理解に苦しんでいます。
回避方法2を教えていただきました。

コード

        <ComboBox HorizontalAlignment="Left"
                  Margin="10,38,0,0"
                  VerticalAlignment="Top"
                  Width="147"
                  ItemsSource="{Binding Path=ComboBoxList, Mode=OneWay}"
                  SelectedValue="{Binding Path=TextBoxValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"

こんな ComboBoxがあったとする。

やりたいこと

        private string textBoxValue;
        public string TextBoxValue
        {
            get => textBoxValue;
            set
            {
                if (value is string)
                {
                    var _textBoxValue = TextBoxValue;
                    textBoxValue = value;

                    if (value == "test")
                    {
                        // 例えば "test" という文字は選択された場合、選択できなくする
                        textBoxValue = _textBoxValue;
                    }
                    RaisePropertyChanged(nameof(TextBoxValue));
                }
            }
        }

TextBoxValueの値は変わっているのだが、ComboBoxの値は変わらない(ロールバックしてくれない)。不思議。

回避方法1

        private ObservableCollection<string> comboBoxList { get; set; }
        public ObservableCollection<string> ComboBoxList
        {
            get => comboBoxList;
            set
            {
                if (value == comboBoxList)
                    return;
                comboBoxList = value;
                RaisePropertyChanged(nameof(ComboBoxList));
            }
        }

        private string textBoxValue;
        public string TextBoxValue
        {
            get => textBoxValue;
            set
            {
                if (value is string)
                {
                    var _textBoxValue = TextBoxValue;
                    textBoxValue = value;
                    RaisePropertyChanged(nameof(TextBoxValue));

                    if (value == "test")
                    {
                        // 例えば "test" という文字は選択された場合、選択できなくする

                        // 元のデータをバックアップ
                        var _comboBoxList = ComboBoxList.ToList();

                        // リストを更新することで強制的にComboBoxの更新を行う
                        ComboBoxList.Clear();
                        _comboBoxList.ForEach(x => ComboBoxList.Add(x));

                        // 元のデータを戻す
                        textBoxValue = _textBoxValue;
                        RaisePropertyChanged(nameof(TextBoxValue));
                    }
                }
            }
        }

ComboBoxの中身を全部消して、どこかに保持されているであろうComboBoxの選択値を消した上で、TextBoxValueを再設定すると上手くいく。

回避方法2

@NCT48 さんにコメントで教えていただきました。
たぶん、こっちの方が簡単で実用的。

        <ComboBox HorizontalAlignment="Left"
                  Margin="10,38,0,0"
                  VerticalAlignment="Top"
                  Width="147"
                  ItemsSource="{Binding Path=ComboBoxList, Mode=OneWay}"
                  SelectedValue="{Binding Path=TextBoxValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Delay=1}"

Delayはミリ秒。

        public string TextBoxValue
        {
            get => textBoxValue;
            set
            {
                // 例えば "test" という文字が選択された場合、選択できなくする
                if (value != "test")
                {
                    textBoxValue = value;
                }
                // ComboBox以外にも通知する
                RaisePropertyChanged(nameof(TextBoxValue));
            }
        }

ComboBoxだけしかないならRaisePropertyChangedは不要です。

参考

2
3
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?