Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9543

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

$
0
0

はじめに

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

原因

ComboBoxでIsTabStopを設定した場合、当然ComboBox自体にこのプロパティがセットされるのですが、どうやらIsEditable=Trueにすると、ComboBox内のPART_EditableTextBoxが使用されるみたいです。
この時問題なのが、ComboBoxのControlTemplateで、MicrosoftのComboBox のスタイルとテンプレートをみるとこうなっています。

<TextBoxx: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を書きます

//~中略~<TextBoxx: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に以下のようなコードを書きます。

privatevoidWindow_Loaded(objectsender,RoutedEventArgse){vartextbox=combobox1.Template.FindName("PART_EditableTextBox",combobox1)asTextBox;if(textbox!=null)textbox.IsTabStop=combobox1.IsTabStop;}

これで、ComboBoxのIsTabStopと連携して、タブで移動してこなくなります。

対策3 ビヘイビア(Behavior)

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

publicclassComboBoxBehavior:Behavior<ComboBox>{protectedoverridevoidOnAttached(){base.OnAttached();AssociatedObject.Loaded+=AssociatedObjectLoaded;}protectedoverridevoidOnDetaching(){base.OnDetaching();AssociatedObject.Loaded-=AssociatedObjectLoaded;}voidAssociatedObjectLoaded(objectsender,System.Windows.RoutedEventArgse){ComboBoxcomboBox=senderasComboBox;vartextBox=comboBox.Template.FindName("PART_EditableTextBox",comboBox)asTextBox;if(textBox==null)return;textBox.IsTabStop=comboBox.IsTabStop;}}

でこれをコントロールに当てはめる

xmlns:i="http://schemas.microsoft.com/xaml/behaviors"xmlns:behavior="clr-namespace:ControlTest.Behaviors"// この名前は任意で<ComboBoxx:Name="combobox1"ItemsSource="{Binding Items}"IsEditable="True"IsTabStop="False"><i:Interaction.Behaviors><behavior:ComboBoxBehavior/></i:Interaction.Behaviors></ComboBox>

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


Viewing all articles
Browse latest Browse all 9543

Trending Articles