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

# 概要

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

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

# コード

```xml
        <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があったとする。

## やりたいこと

```c#
        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の値は変わらない（ロールバックしてくれない）。不思議。

## 回避方法１

```c#
        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`を再設定すると上手くいく。

- https://github.com/hydrangeas/ComboBoxTest

## 回避方法２

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

```xml
        <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`はミリ秒。

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

```

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

- https://github.com/hydrangeas/ComboBoxTest/tree/delay

## 参考

- [How to rollback selected SelectedValue of the combo box using WPF MVVM](https://stackoverflow.com/questions/5879876/)