WPFのComboBoxでIsEditable=TrueにするとIsTabStop=Falseにしてもタブストップしてしまう

#はじめに
WPFで開発をしている時に、コントロールによってタブでフォーカスが移らないようにIsTabStopをFalseにすることがあります。
ところが、ComboBoxでIsTabStopをFalseにしても、IsEditableをTrueにしてしまうと、タブで移動してしまうという現象が発生します。
開発当時、まだWPFを勉強し始めたころは、もうチンプンカンプンで、何が起きているのかわかりませんでした。
とりあえず慌ててググッて、対策を・・・ということをしてきましたが、今なら落ちついて(笑)考察できるようになったので、原因と対策を書き留めておこうと思います。

#原因
ComboBoxでIsTabStopを設定した場合、当然ComboBox自体にこのプロパティがセットされるのですが、どうやらIsEditable=Trueにすると、ComboBox内のPART_EditableTextBoxが使用されるみたいです。
この時問題なのが、ComboBoxのControlTemplateで、Microsoftの[ComboBox のスタイルとテンプレート](https://docs.microsoft.com/ja-jp/dotnet/desktop/wpf/controls/combobox-styles-and-templates?view=netframeworkdesktop-4.8)をみるとこうなっています。

```C#
<TextBox x:Name="PART_EditableTextBox"
                   Style="{x:Null}"
                   Template="{StaticResource ComboBoxTextBox}"
                   HorizontalAlignment="Left"
                   VerticalAlignment="Bottom"
                   Margin="3,3,23,3"
                   Focusable="True"
                   Background="Transparent"
                   Visibility="Hidden"
                   IsReadOnly="{TemplateBinding IsReadOnly}" />
```
なんと、IsTabStopの項目がないです。
だから、IsEditable=Trueにすると、IsTabStopはもう関係なしということで、何をしても必ずタブが移ってしまいます。

#対策1　ControlTemplate
一つ目の対策としては、Window.Resourcesとか、App.xamlでリソースを設定して、ControlTemplateを書きます

```C#
//～中略～
<TextBox x:Name="PART_EditableTextBox"
                   Style="{x:Null}"
                   Template="{StaticResource ComboBoxTextBox}"
                   HorizontalAlignment="Left"
                   VerticalAlignment="Bottom"
                   Margin="3,3,23,3"
                   Focusable="True"
                   Background="Transparent"
                   Visibility="Hidden"
                   IsReadOnly="{TemplateBinding IsReadOnly}" 
                   IsTabStop="{Binding IsTabStop, RelativeSource={RelativeSource TemplatedParent}}"/>
//～中略～
```
でも、これだととにかく長いリソースを書かないといけないのでめんどいです。
以前、他にもいじりたいところがあったので、ComboBoxExというカスタムコントロールを作って、そこでGeneric.xamlにリソースを書いて利用しました。
だけど、本当に面倒でした。また新規に開発するときに・・・と思うと嫌です(~_~;)

#対策2　コードビハインド
二つ目の対策としては、コードビハインドに書いてしまうという方法です。
Window_Loadedに以下のようなコードを書きます。

```C#
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            var textbox = combobox1.Template.FindName("PART_EditableTextBox", combobox1) as TextBox;
            if (textbox != null)
                textbox.IsTabStop = combobox1.IsTabStop;
        }
```
これで、ComboBoxのIsTabStopと連携して、タブで移動してこなくなります。

#対策3　ビヘイビア(Behavior)
最後に、ビヘイビアを作るという方法です。
コードビハインドと同じようなコードでBehaviorを作ります

```C#
    public class ComboBoxBehavior : Behavior<ComboBox>
    {
        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.Loaded += AssociatedObjectLoaded;
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();
            AssociatedObject.Loaded -= AssociatedObjectLoaded;
        }
        void AssociatedObjectLoaded(object sender, System.Windows.RoutedEventArgs e)
        {
            ComboBox comboBox = sender as ComboBox;
            var textBox = comboBox.Template.FindName("PART_EditableTextBox", comboBox) as TextBox;
            if (textBox == null) return;

            textBox.IsTabStop = comboBox.IsTabStop;
        }
    }
```
でこれをコントロールに当てはめる

```C#
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:behavior="clr-namespace:ControlTest.Behaviors"  // この名前は任意で

<ComboBox x:Name="combobox1"
            ItemsSource="{Binding Items}"
            IsEditable="True"
            IsTabStop="False">
    <i:Interaction.Behaviors>
        <behavior:ComboBoxBehavior/>
    </i:Interaction.Behaviors>
</ComboBox>
```

だいたいこんな感じでうまくいきました。
何か他にも方法をご存じの方がいましたら、教えていただけるとありがたいです。