WPF の ComboBox は「閉じた状態」で見ると本体の背景がややくすんだ灰色に見え、アプリのトーンに合わないことがあります。ここでは、ドロップダウンを開いていない通常表示の背景色を、XAML だけで確実かつ安全に緑など任意の色へ差し替える方法を、最短手順からテンプレート編集の本格手法まで実務目線で解説します。
WPF ComboBoxの選択枠(閉じた状態)の灰色背景を変更する方法
質問概要
WPF/XAML で、ドロップダウンを開いていないときに見える ComboBox 本体(選択された値が表示されている領域)の背景を、既定(灰色)から緑など任意色に変えたい。変更対象はリスト項目ではなく、選択表示部の背景。IsEditable=True の場合は入力域の背景まで含めて統一したい。
結論(全体像)
ComboBox の見た目は ControlTemplate 内の Border/ToggleButton/TextBox などによって構成され、Background プロパティを直接設定しても内部の Border や TextBox まで色が伝搬しないため灰色が残ります。テンプレート内で参照されるブラシ資源(Brush)を差し替える、または テンプレート自体を編集することで、閉じた状態の背景を確実に変更できます。
回答・解決策(手順の俯瞰)
| 手順 | 内容 | 備考 |
|---|---|---|
| 1 | 既定テンプレートを取得 Visual Studio または Blend で対象 ComboBox を右クリック → Edit Template → Edit a Copy を実行し、既定の ControlTemplate と関連ブラシを自分のリソース辞書にコピー。 | Designer から行うと大量の XAML が自動生成されるが、必要なのは色を司るブラシ部分だけ。 |
| 2 | 背景用ブラシを書き換える 生成されたリソース内で次のキーを好きな色に変更: ComboBox.Static.Background(通常時)ComboBox.Static.Editable.Background(IsEditable=True 時)必要に応じて TextBox.Static.Background も同色に。 | 例:Color="#FF80C683" で淡い緑に。マウスオーバー/無効化など他状態も同名ブラシを追加で修正。 |
| 3 | Style を適用 編集済み Style を Window.Resources やアプリ共通リソースに置き、<ComboBox Style="{StaticResource ComboBoxStyle1}"> のように割り当て。 | 全画面へ展開するなら App.xaml の Application.Resources に登録。 |
| 4 | もっと簡易に済ませる方法 状態切り替えを細かく調整しないなら、ComboBox 内だけにブラシを上書きする最小構成でも可。 | ただしこの方法ではマウスオーバーや無効化時の配色は従来のまま。一貫性が必要なら手順 1〜3 を推奨。 |
なぜ Background を直接設定しても灰色が残るのか
ComboBox の既定テンプレートは概ね次の構造です:外枠の Border、選択内容の ContentPresenter(または 編集可能時の TextBox)、ドロップダウン用の ToggleButton、Popup 内の ItemsPresenter。
プロパティ Background は TemplateBinding で Border に伝わることもありますが、多くのテーマでは 内部で参照しているリソースキー(例:ComboBox.Static.Background)が実体の色を決めているため、コントロール直上で色を指定しても目的の Border/TextBox に届きません。したがって、テンプレート内で参照されるブラシを上書きするのが最短で確実な解決策です。
最短:コントロールローカルでブラシを上書き(テンプレート無改造)
単一の ComboBox だけ背景を変えたい、かつ状態配色は既定のままでよい場合は、次のように ComboBox.Resources で必要なブラシキーだけを上書きするのが簡単です。
<ComboBox Width="160" Margin="8" SelectedIndex="0">
<ComboBox.Resources>
<SolidColorBrush x:Key="ComboBox.Static.Background" Color="#FF80C683"/> <!-- 通常時(閉じている) -->
<SolidColorBrush x:Key="ComboBox.MouseOver.Background" Color="#FF8FD08E"/> <!-- ホバー -->
<SolidColorBrush x:Key="ComboBox.Pressed.Background" Color="#FF5EA965"/> <!-- クリック中 -->
<SolidColorBrush x:Key="ComboBox.Disabled.Background" Color="#FFE8EFE8"/> <!-- 無効 -->
<SolidColorBrush x:Key="ComboBox.Border" Color="#FF2E7D32"/> <!-- 枠線 -->
<!-- 編集可能時の入力域(TextBox) -->
<SolidColorBrush x:Key="TextBox.Static.Background" Color="#FFEFF8F0"/>
<SolidColorBrush x:Key="ComboBox.Static.Editable.Background" Color="#FFEFF8F0"/>
</ComboBox.Resources>
りんご
みかん
ぶどう
この方法は テンプレート非侵襲で安全・高速に目的を達成できます。
ただし、テーマやサードパーティーライブラリによっては参照キー名が異なる場合がある点に注意してください(後述の「既存テーマとの共存」参照)。
本命:既定テンプレートをコピーして背景を完全にコントロール
アプリ全体の一貫性や状態別の色調整(ホバー・押下・無効・フォーカス)まで含めて仕上げるなら、テンプレートをコピーして編集します。Designer が生成する XAML は長いですが、ブラシ定義と 背景を塗っている Border/TextBoxに絞れば読みやすくなります。
編集対象となる代表的なブラシキー
| キー | 意味 | 推奨例(緑系) |
|---|---|---|
ComboBox.Static.Background | 閉じた通常時の本体背景 | #FF80C683(淡緑) |
ComboBox.MouseOver.Background | ホバー時の本体背景 | #FF8FD08E(+明度) |
ComboBox.Pressed.Background | 押下/展開中の本体背景 | #FF5EA965(-明度) |
ComboBox.Disabled.Background | 無効時の本体背景 | #FFE8EFE8(低コントラスト) |
ComboBox.Border | 枠線色 | #FF2E7D32(濃緑) |
ComboBox.Static.Editable.Background | IsEditable=True の入力域 | #FFEFF8F0(ごく薄い緑) |
TextBox.Static.Background | 編集可能 ComboBox の TextBox 背景 | #FFEFF8F0(上と合わせる) |
Style(ControlTemplate)例:背景をリソース化して状態ごとに切替
以下は背景と枠線に関わる最小要素に絞った、読みやすいテンプレート例です。
「閉じた状態の背景」を ComboBox.*.Background ブラシで一元管理し、IsEditable=True 時は PART_EditableTextBox に背景を適用しています。
<Window.Resources>
<Style x:Key="GreenComboBoxStyle" TargetType="{x:Type ComboBox}">
<Style.Resources>
<SolidColorBrush x:Key="ComboBox.Static.Background" Color="#FF80C683"/>
<SolidColorBrush x:Key="ComboBox.MouseOver.Background" Color="#FF8FD08E"/>
<SolidColorBrush x:Key="ComboBox.Pressed.Background" Color="#FF5EA965"/>
<SolidColorBrush x:Key="ComboBox.Disabled.Background" Color="#FFE8EFE8"/>
<SolidColorBrush x:Key="ComboBox.Border" Color="#FF2E7D32"/>
<SolidColorBrush x:Key="ComboBox.Static.Editable.Background" Color="#FFEFF8F0"/>
<SolidColorBrush x:Key="TextBox.Static.Background" Color="#FFEFF8F0"/>
</Style.Resources>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid x:Name="Root" ClipToBounds="True">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="20"/>
</Grid.ColumnDefinitions>
<Border x:Name="BackgroundBorder"
Grid.ColumnSpan="2"
CornerRadius="2"
Background="{DynamicResource ComboBox.Static.Background}"
BorderBrush="{DynamicResource ComboBox.Border}"
BorderThickness="{TemplateBinding BorderThickness}"/>
<ContentPresenter x:Name="ContentSite"
Margin="6,2,26,2"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Content="{TemplateBinding SelectionBoxItem}"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
IsHitTestVisible="False"/>
<TextBox x:Name="PART_EditableTextBox"
Margin="6,2,26,2"
Background="{DynamicResource ComboBox.Static.Editable.Background}"
BorderThickness="0"
Visibility="Hidden"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Focusable="True"/>
<ToggleButton x:Name="DropDownToggle"
Grid.Column="1"
Focusable="False"
IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
ClickMode="Press" Background="{x:Null}" BorderBrush="{x:Null}"/>
<Path x:Name="Arrow" Grid.Column="1"
HorizontalAlignment="Center" VerticalAlignment="Center"
Data="M 0 0 L 4 4 L 8 0"
Stroke="{DynamicResource ComboBox.Border}" StrokeThickness="2"/>
<Popup x:Name="PART_Popup"
Placement="Bottom"
IsOpen="{TemplateBinding IsDropDownOpen}"
AllowsTransparency="True"
Focusable="False"
PopupAnimation="Slide">
<Border x:Name="PopupBorder"
Background="White"
BorderBrush="{DynamicResource ComboBox.Border}"
BorderThickness="1">
<ScrollViewer SnapsToDevicePixels="True">
<ItemsPresenter/>
</ScrollViewer>
</Border>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEditable" Value="True">
<Setter TargetName="ContentSite" Property="Visibility" Value="Hidden"/>
<Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Visible"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="BackgroundBorder" Property="Background" Value="{DynamicResource ComboBox.MouseOver.Background}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="BackgroundBorder" Property="Background" Value="{DynamicResource ComboBox.Disabled.Background}"/>
<Setter TargetName="Arrow" Property="Stroke" Value="#FFBFBFBF"/>
</Trigger>
<Trigger Property="IsDropDownOpen" Value="True">
<Setter TargetName="BackgroundBorder" Property="Background" Value="{DynamicResource ComboBox.Pressed.Background}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
りんご
みかん
ぶどう
色の作り方(明度の揃え方)
配色の一貫性を保つには、ベース色を 1 つ決めてから 明度(L)を上下に 5〜10% 程度調整するのが簡単です。例として #FF80C683 を基準に、ホバー時は +6%、押下時は -8% 程度(目安)とし、枠線は同系色の濃色(彩度高め)にすると視認性が上がります。無効状態は彩度を落としてコントラストを下げると「触れない」印象を与えられます。
編集可能(IsEditable=True)時の注意点
- 表示領域は TextBoxになるため、背景は
PART_EditableTextBoxに対して設定する必要があります。前掲テンプレート例ではComboBox.Static.Editable.Backgroundを適用。 - 選択範囲色やキャレット色まで統一したい場合は、
SelectionBrush、CaretBrush(TextBox 側の Setter または直接指定)も併せて調整します。 - 編集可能時に ContentPresenter を非表示にするトリガーを忘れると、TextBox と文字列が重なって見えることがあります(テンプレートの
IsEditableトリガーで切替)。
アプリ全体に適用する(App.xaml の共通リソース)
全フォームで同じテーマにしたい場合、Style を Application.Resources に移し、型付き暗黙 Style にするのがシンプルです。
<Application ...>
<Application.Resources>
<!-- 既定 Style として全 ComboBox に適用(キー無し) -->
<Style TargetType="{x:Type ComboBox}">
<!-- ここに前掲の Resource と Template をそのまま記述 -->
</Style>
</Application.Resources>
</Application>
既存の Style を壊したくない場合は、キー付きで登録し個別に Style="{StaticResource ...}" で割り当てるか、BasedOn を使って既定 Style を継承する方法もあります。
Blend での実務的コツ
- 対象 ComboBox を右クリック → Edit Template → Edit a Copy で丸ごとコピー。
- 生成された XAML の先頭付近に「ブラシの束」ができるので、まずそこだけ調整して挙動を確認。
- 状態ごとの視覚状態(
IsMouseOver,IsDropDownOpen,IsEnabled)を States パネルで切り替えながら、Border/TextBox が本当に目的のブラシを参照しているか確認。 - 不要なビジュアル(グローやアニメーション)は後から削る。XAML が 1/3 くらいまで軽くなる。
よくあるつまずきと対処
- 背景が一部だけ灰色のまま:編集可能時の TextBox(
PART_EditableTextBox)の背景を見落としている。ComboBox.Static.Editable.BackgroundやTextBox.Static.Backgroundを上書き。 - ホバーや押下で緑が消える:状態別ブラシ(
MouseOver/Pressed/Disabled)の定義漏れ。最低でも通常・ホバー・押下・無効の 4 系を用意。 - サードパーティテーマが上書きする:MahApps や MaterialDesign などのテーマは独自キーを使うことがある。自前 Style をテーマ辞書より後に読み込むか、テーマが提供するキー名に合わせて上書きする。
- 高コントラスト環境で読みにくい:高コントラスト時の分岐(
SystemParameters.HighContrast)トリガーを用い、背景と文字色をシステム色にフォールバックする。 - 暗黙 Style と明示 Style の競合:暗黙 Style をアプリ全域に適用している場合、特定画面だけ別色にしたいときはキー付き Style を明示的に割り当てる。
配色ガイドライン(アクセシビリティ)
| 状態 | 背景例 | 前景(文字) | コントラスト目安 | 備考 |
|---|---|---|---|---|
| 通常 | #FF80C683 | #FF0B2E13(濃緑〜黒) | 4.5:1 以上推奨 | 本文と枠線色の差も確保 |
| ホバー | #FF8FD08E | #FF0B2E13 | 3:1 以上 | 浮き上がり効果は明度 +5〜10% |
| 押下/展開 | #FF5EA965 | #FFFFFFFF(白) | 4.5:1 以上推奨 | 濃色化+文字白も可 |
| 無効 | #FFE8EFE8 | #FF9AA69A | 低めで可 | 操作不可の印象を明確に |
検証用:最小ページ(3 パターン並べて確認)
<Grid Margin="12">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
りんご
みかん
ぶどう
東京
大阪
福岡
プロダクションでの設計パターン
- テーマ別 ResourceDictionary を分割:例:
Colors.Green.xaml(色定義のみ)、Controls.ComboBox.xaml(テンプレートのみ)。色の変更は Colors だけで完結。 - 動的テーマ切替:
MergedDictionariesに色辞書を差し替えるだけで既存テンプレートが新色を拾うように設計。アニメーション付きの遷移はColorAnimationを適用。 - ユニットテスト的検証:ComboBox の
IsMouseOver・IsEnabled等をデバッグ時に強制切替してスクリーンショットを自動保存し、配色のレグレッションを検知。
既存テーマ/ライブラリとの共存
MahApps.Metro や MaterialDesignInXAML などのライブラリは、ComboBox のテンプレートとブラシキーを独自に持つことがあります。この場合、そのテーマが公開しているキー名(例:MahApps.Brushes.*、MaterialDesignTextBox* 等)を上書きするか、同テーマの Style を BasedOn して配色だけ置き換えるのが安全です。アプリの ResourceDictionary.MergedDictionaries の読み込み順は自前辞書を最後にして、確実に上書きされるようにしてください。
チェックリスト(デザインレビュー)
- 閉じた通常時の背景が意図した色か。
- ホバー・押下・無効で色が破綻しないか。
- 編集可能時の TextBox 背景が一致しているか。
- 文字色と背景のコントラスト比は十分か(少なくとも 4.5:1)。
- 枠線色と背景の差でフォーカスを認知しやすいか。
- 高コントラストモードでの代替配色を持っているか。
- サードパーティテーマの適用順で上書きされていないか。
背景だけを変える「最小パッチ」も有効
「状態ごとの厳密な調整は不要。とにかく閉じた時の灰色だけ緑に」というニーズなら、まずは該当 ComboBox の ComboBox.Static.Background を 1 行で上書きしてみましょう。たったこれだけでほとんどの既定テンプレートで「閉じた状態の灰色」が確実に置き換わります。違和感が出たら、次の段階として MouseOver/Pressed/Disabled を追加でオーバーライドすれば十分です。
小ネタ:色をコードから差し替える
配色を運用時に切り替えたい場合は、アプリ起動時に Application.Current.Resources のブラシを差し替える方法もシンプルです。
// C#(起動時など)
Application.Current.Resources["ComboBox.Static.Background"] =
(SolidColorBrush)new BrushConverter().ConvertFrom("#FF80C683");
Application.Current.Resources["ComboBox.MouseOver.Background"] =
(SolidColorBrush)new BrushConverter().ConvertFrom("#FF8FD08E");
この方式は XAML のテンプレート側が DynamicResource でブラシを参照している場合に有効です(本稿のテンプレート例はすべて DynamicResource)。
まとめ
WPF の ComboBox 本体(閉じた状態)の背景色を変えるには、テンプレート内で参照されるブラシを差し替えるのが最も確実です。単発なら ComboBox.Resources でのブラシ上書き、アプリ全体ならテンプレート編集+共通リソース化がベストプラクティス。
ポイントは次の 3 つ:
- 色の実体はテンプレート内のブラシ。
Background直指定では届かないことが多い。 - 状態別のブラシを用意(通常/ホバー/押下/無効)。編集可能時は TextBox 背景も揃える。
- リソース分離で運用しやすく:色とテンプレートを別辞書にし、
DynamicResource経由で配色を管理。
この手順に沿えば、「閉じた状態の灰色」を任意の緑(やブランドカラー)へ安全に置き換えられ、アプリのトーンに合わせた統一感のある UI を短時間で実現できます。
補足ポイント(再掲)
Backgroundの直設定で色が届かないのは、内部 Border/TextBox が独自のブラシを参照しているため。- 項目ごとのハイライト(ドロップダウン内)を変えたいときは
ItemContainerStyleを別途定義(本稿の主題外)。 - Blend を使うと状態ごとの色・アニメーションを視覚的に調整できるため、複雑な UI では特に有効。
実装メモ(コピー用クイックリファレンス)
| やりたいこと | 最短コード | 備考 |
|---|---|---|
| 閉じた通常時の背景だけ緑に | <ComboBox> <ComboBox.Resources> <SolidColorBrush x:Key="ComboBox.Static.Background" Color="LightGreen"/> </ComboBox.Resources> </ComboBox> | 他状態は既定のまま |
| 編集可能時の入力域も緑系に | <ComboBox IsEditable="True"> <ComboBox.Resources> <SolidColorBrush x:Key="ComboBox.Static.Editable.Background" Color="#FFEFF8F0"/> <SolidColorBrush x:Key="TextBox.Static.Background" Color="#FFEFF8F0"/> </ComboBox.Resources> </ComboBox> | TextBox 背景の揃え忘れに注意 |
| 状態ごとに完全制御 | <ComboBox Style="{StaticResource GreenComboBoxStyle}"/> | 本稿のテンプレート Style を共通資源に置く |

コメント