ComboBox の編集時のみ背景色を変更する
WindowsForms のアプリを WPF に移植しようとして、またまた引っかかったが、ComboBox 編集時の背景色変更。
TextBox なら 以下のようにトリガーで簡単に設定できるのですが、ComboBox の場合はそうもいきません。
<Style TargetType="{x:Type TextBox}"> <Style.Triggers> <Trigger Property="IsFocused" Value="true"> <Setter Property="Background" Value="LemonChiffon"/> </Trigger> </Style.Triggers> </Style>
ComboBox の場合、以下のようにトリガーを設定しても、IsEdiable=false (WinForm なら DropDownList) なら問題ないですが、IsEdiable=true (WinForm の DropDown) にした ComboBox では Background に設定したブラシは反映されません。
<Style TargetType="{x:Type ComboBox}"> <Style.Triggers> <Trigger Property="IsFocused" Value="true"> <Setter Property="Background" Value="LemonChiffon"/> </Trigger> </Style.Triggers> </Style>
(2011/04/23 修正)
これは ComboBox の構造的問題によるもので、IsEdiable な ComboBox でフォーカス時にのみ Background を設定したいなら ControlTemplate を編集する以外ありませんか、もしくは IsKeyboardFocusWithin プロパティを使います。
<Style TargetType="{x:Type ComboBox}"> <Style.Triggers> <Trigger Property="IsKeyboardFocusWithin" Value="true"> <Setter Property="Background" Value="LemonChiffon"/> </Trigger> </Style.Triggers> </Style>
上記のように、IsFocused の代わりに IsKeyboardFocusWithin プロパティを使うと Background の設定がビューに反映されます。これだとテンプレートを編集する必要がないので手っ取り早いです。
もしくは ControlTemplate を編集する方法もあります。 2011/04/23 修正 時点ではもはや古い解決方法になるのですが、なにかの参考までに一応残しておきます。
ComboBox の Template 内の ComboBoxEditableTextBox というリソースを探し、Template の設定に以下のトリガを加えます。この例では Yellow を設定しました。
<ControlTemplate.Triggers> <Trigger Property="IsFocused" Value="True"> <Setter Property="Background" TargetName="PART_ContentHost" Value="Yellow" /> </Trigger> </ControlTemplate.Triggers>
するとこうなります。
以下 スタイルの全文です。
<Style x:Key="ComboBoxFocusVisual"> <Setter Property="Control.Template"> <Setter.Value> <ControlTemplate> <Rectangle Margin="4,4,21,4" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/> </ControlTemplate> </Setter.Value> </Setter> </Style> <SolidColorBrush x:Key="ListBorder" Color="#FF7F9DB9"/> <Style x:Key="ComboBoxTransparentButtonStyle" TargetType="{x:Type ToggleButton}"> <Setter Property="MinWidth" Value="0"/> <Setter Property="MinHeight" Value="0"/> <Setter Property="Width" Value="Auto"/> <Setter Property="Height" Value="Auto"/> <Setter Property="Background" Value="Transparent"/> <Setter Property="Focusable" Value="false"/> <Setter Property="ClickMode" Value="Press"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ToggleButton}"> <Grid Background="{TemplateBinding Background}" SnapsToDevicePixels="true"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition SharedSizeGroup="ComboBoxButton" Width="Auto"/> </Grid.ColumnDefinitions> <Microsoft_Windows_Themes:ScrollChrome x:Name="Chrome" Grid.Column="1" HasOuterBorder="false" Padding="1,0,0,0" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsChecked}" Microsoft_Windows_Themes:ScrollChrome.ScrollGlyph="DownArrow" ThemeColor="NormalColor" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="ComboBoxEditableTextBox" TargetType="{x:Type TextBox}"> <Setter Property="OverridesDefaultStyle" Value="true"/> <Setter Property="AllowDrop" Value="true"/> <Setter Property="MinWidth" Value="0"/> <Setter Property="MinHeight" Value="0"/> <Setter Property="FocusVisualStyle" Value="{x:Null}"/> <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/> <Setter Property="Stylus.IsFlicksEnabled" Value="False"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type TextBox}"> <ScrollViewer x:Name="PART_ContentHost" Background="Transparent" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/> <ControlTemplate.Triggers> <Trigger Property="IsFocused" Value="True"> <Setter Property="Background" TargetName="PART_ContentHost" Value="Yellow" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <ControlTemplate x:Key="ComboBoxEditableTemplate" TargetType="{x:Type ComboBox}"> <Grid SnapsToDevicePixels="true"> <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="1"> <Grid Grid.IsSharedSizeScope="true"> <Grid.ColumnDefinitions> <ColumnDefinition Width="1"/> <ColumnDefinition Width="*"/> <ColumnDefinition SharedSizeGroup="ComboBoxButton" Width="Auto"/> </Grid.ColumnDefinitions> <TextBox x:Name="PART_EditableTextBox" Grid.Column="1" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" IsReadOnly="{Binding IsReadOnly, RelativeSource={RelativeSource TemplatedParent}}" Margin="{TemplateBinding Padding}" Style="{StaticResource ComboBoxEditableTextBox}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/> <ToggleButton Background="{x:Null}" Grid.ColumnSpan="3" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ComboBoxTransparentButtonStyle}"/> </Grid> </Border> <Popup x:Name="PART_Popup" AllowsTransparency="true" Focusable="false" IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom"> <Microsoft_Windows_Themes:SystemDropShadowChrome x:Name="Shdw" Color="Transparent" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{TemplateBinding ActualWidth}"> <Border x:Name="DropDownBorder" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"> <ScrollViewer x:Name="DropDownScrollViewer"> <Grid RenderOptions.ClearTypeHint="Enabled"> <Canvas HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0"> <Rectangle x:Name="OpaqueRect" Fill="{Binding Background, ElementName=DropDownBorder}" Height="{Binding ActualHeight, ElementName=DropDownBorder}" Width="{Binding ActualWidth, ElementName=DropDownBorder}"/> </Canvas> <ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> </Grid> </ScrollViewer> </Border> </Microsoft_Windows_Themes:SystemDropShadowChrome> </Popup> </Grid> <ControlTemplate.Triggers> <Trigger Property="HasItems" Value="false"> <Setter Property="MinHeight" TargetName="DropDownBorder" Value="95"/> </Trigger> <Trigger Property="IsEnabled" Value="false"> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/> </Trigger> <Trigger Property="IsGrouping" Value="true"> <Setter Property="ScrollViewer.CanContentScroll" Value="false"/> </Trigger> <Trigger Property="HasDropShadow" SourceName="PART_Popup" Value="true"> <Setter Property="Margin" TargetName="Shdw" Value="0,0,5,5"/> <Setter Property="Color" TargetName="Shdw" Value="#71000000"/> </Trigger> <Trigger Property="ScrollViewer.CanContentScroll" SourceName="DropDownScrollViewer" Value="false"> <Setter Property="Canvas.Top" TargetName="OpaqueRect" Value="{Binding VerticalOffset, ElementName=DropDownScrollViewer}"/> <Setter Property="Canvas.Left" TargetName="OpaqueRect" Value="{Binding HorizontalOffset, ElementName=DropDownScrollViewer}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> <Style TargetType="{x:Type ComboBox}"> <Setter Property="FocusVisualStyle" Value="{StaticResource ComboBoxFocusVisual}"/> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/> <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/> <Setter Property="BorderBrush" Value="{StaticResource ListBorder}"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="Padding" Value="1"/> <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/> <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/> <Setter Property="ScrollViewer.CanContentScroll" Value="true"/> <Setter Property="ScrollViewer.PanningMode" Value="Both"/> <Setter Property="Stylus.IsFlicksEnabled" Value="False"/> <Setter Property="VerticalContentAlignment" Value="Center"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ComboBox}"> <Grid SnapsToDevicePixels="true"> <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="1"> <Grid Grid.IsSharedSizeScope="true"> <Grid.ColumnDefinitions> <ColumnDefinition Width="1"/> <ColumnDefinition Width="*"/> <ColumnDefinition SharedSizeGroup="ComboBoxButton" Width="Auto"/> </Grid.ColumnDefinitions> <Border x:Name="SelectedItemBorder" Grid.ColumnSpan="2" Margin="{TemplateBinding Padding}"/> <ContentPresenter ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" Content="{TemplateBinding SelectionBoxItem}" Grid.Column="1" ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> <ToggleButton Grid.ColumnSpan="3" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ComboBoxTransparentButtonStyle}"/> </Grid> </Border> <Popup x:Name="PART_Popup" AllowsTransparency="true" Focusable="false" IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom"> <Microsoft_Windows_Themes:SystemDropShadowChrome x:Name="Shdw" Color="Transparent" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{TemplateBinding ActualWidth}"> <Border x:Name="DropDownBorder" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"> <ScrollViewer x:Name="DropDownScrollViewer"> <Grid RenderOptions.ClearTypeHint="Enabled"> <Canvas HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0"> <Rectangle x:Name="OpaqueRect" Fill="{Binding Background, ElementName=DropDownBorder}" Height="{Binding ActualHeight, ElementName=DropDownBorder}" Width="{Binding ActualWidth, ElementName=DropDownBorder}"/> </Canvas> <ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> </Grid> </ScrollViewer> </Border> </Microsoft_Windows_Themes:SystemDropShadowChrome> </Popup> </Grid> <ControlTemplate.Triggers> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsSelectionBoxHighlighted" Value="true"/> <Condition Property="IsDropDownOpen" Value="false"/> </MultiTrigger.Conditions> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/> </MultiTrigger> <Trigger Property="IsSelectionBoxHighlighted" Value="true"> <Setter Property="Background" TargetName="SelectedItemBorder" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/> </Trigger> <Trigger Property="HasDropShadow" SourceName="PART_Popup" Value="true"> <Setter Property="Margin" TargetName="Shdw" Value="0,0,5,5"/> <Setter Property="Color" TargetName="Shdw" Value="#71000000"/> </Trigger> <Trigger Property="HasItems" Value="false"> <Setter Property="MinHeight" TargetName="DropDownBorder" Value="95"/> </Trigger> <Trigger Property="IsEnabled" Value="false"> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/> </Trigger> <Trigger Property="IsGrouping" Value="true"> <Setter Property="ScrollViewer.CanContentScroll" Value="false"/> </Trigger> <Trigger Property="ScrollViewer.CanContentScroll" SourceName="DropDownScrollViewer" Value="false"> <Setter Property="Canvas.Top" TargetName="OpaqueRect" Value="{Binding VerticalOffset, ElementName=DropDownScrollViewer}"/> <Setter Property="Canvas.Left" TargetName="OpaqueRect" Value="{Binding HorizontalOffset, ElementName=DropDownScrollViewer}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> <Style.Triggers> <Trigger Property="IsEditable" Value="true"> <Setter Property="IsTabStop" Value="false"/> <Setter Property="Padding" Value="0,1"/> <Setter Property="Template" Value="{StaticResource ComboBoxEditableTemplate}"/> </Trigger> </Style.Triggers> </Style>
ちなみにテンプレートの編集ですが、Expression Blend があれば、ComboBox を選択して、メニューの「オブジェクト」→「テンプレートの編集」→「コピーして編集」で 「Style リソースの作成」ウィンドウが表示されますので、名前は「すべて適用」、定義先は「このドキュメント」にチェックし、「OK」ボタンをクリックすると Window のリソースにスタイルの定義が展開されますので、これを編集します。