.NET MAUIでWindows向けアプリを作っていると、MenuFlyoutItemの背景色を調整したはずなのに、選択中だけ背景が透明になって読めないことがあります。原因はWinUI側のテーマリソース。Platforms/Windows/App.xamlで選択時ブラシを上書きすれば、狙った色に固定できます。
問題の背景:.NET MAUI(Windows)はWinUIのテーマリソースに強く影響される
.NET MAUIのWindowsターゲットは、実際の描画にWinUI(Windows App SDK)を使っています。つまり、見た目(背景色・文字色・ホバー色・押下色など)はWinUI側の「テーマリソース(ResourceDictionary)」で決まる部分が多いということです。
MenuFlyoutItemも例外ではなく、アプリ側で色を変えたつもりでも、WinUIが参照しているキーを上書きできていないと、特定の状態だけ「既定の色」に戻ったり、既定が透明に近い値になっていて選択中だけ背景が抜けて見えることがあります。
発生する症状:「選択中のMenuFlyoutItemだけ背景が透明で見づらい」
今回の症状は、次のような状況で起きやすいです。
- MenuFlyoutItemの背景色/文字色をカスタマイズしている
- 通常表示は問題ないのに、マウスホバーやキーボード操作で「選択中」になると背景が透明っぽくなる
- 結果として、背面のコンテンツが透けて見えて読みにくい(特にダークテーマや画像の上で顕著)
| 状態 | 見え方 | ユーザー視点の困りごと |
|---|---|---|
| 通常(Normal) | 指定した背景色・文字色で表示される | 問題なし |
| 選択中(ホバー/フォーカス/キーボード選択) | 背景が透明(もしくは極端に薄い) | 項目が見えない/選択位置が分からない |
| 押下中(Pressed) | 一瞬だけ色が変わる/透明になる | クリック感が弱い、誤操作につながる |
原因:選択状態で参照されるWinUIのブラシ(リソースキー)が別だから
MenuFlyoutItemは「通常背景」だけで描画されているわけではありません。WinUIは、ポインターが乗ったとき(PointerOver)や押下中(Pressed)など、状態ごとに別のブラシを参照します。
そのため、通常時の背景や文字色だけを調整しても、選択状態で使われるキー(PointerOver/Pressedなど)を上書きしていないと、そこだけ既定のまま残ります。既定値が透明(Transparent)または背景と同化する色だと、「選択中だけ背景が透明」に見える、というわけです。
| WinUI側でよく使われるキー | 主に効くタイミング | 今回の症状との関係 |
|---|---|---|
MenuFlyoutItemBackgroundPointerOver | マウスホバー、キーボードでの選択移動中 | ここが透明だと「選択中の背景が抜ける」 |
MenuFlyoutItemBackgroundPressed | クリック(押下)中 | 押下時に一瞬透明に見える原因になる |
解決策:Platforms/Windows/App.xamlで「選択時背景ブラシ」を明示して上書きする
最もシンプルで効果が高い対処は、Windows(WinUI)側のリソースキーを上書きして、選択状態の背景色を明示的に指定することです。これにより、選択中だけ透明になってしまう挙動を安定して潰せます。
手順
Platforms/Windows/App.xamlを開く- ルート要素配下の
<maui:MauiWinUIApplication.Resources>に、選択時の背景として使うブラシを追加する MenuFlyoutItemBackgroundPointerOverとMenuFlyoutItemBackgroundPressedを、そのブラシに差し替える
例:選択時の背景を任意色に固定する(提示コードそのまま)
まずは動作を優先して、最短で直すコード例です。選択中(PointerOver/Pressed)で使われる背景キーを、同じブラシへ寄せています。
<maui:MauiWinUIApplication.Resources>
<SolidColorBrush x:Key="MenuFlyoutItemselectedColor" Color="Orange" />
<StaticResource x:Key="MenuFlyoutItemBackgroundPointerOver"
ResourceKey="MenuFlyoutItemselectedColor" />
<StaticResource x:Key="MenuFlyoutItemBackgroundPressed"
ResourceKey="MenuFlyoutItemselectedColor" />
App.xamlに配置する位置(最小構成のイメージ)
「どこに書けばよいか」で迷う場合は、次のように MauiWinUIApplication.Resources の中に置くのがポイントです。
<?xml version="1.0" encoding="utf-8" ?>
<maui:MauiWinUIApplication
x:Class="YourApp.WinUI.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:maui="using:Microsoft.Maui">
<maui:MauiWinUIApplication.Resources>
<SolidColorBrush x:Key="MenuFlyoutItemselectedColor" Color="Orange" />
<StaticResource x:Key="MenuFlyoutItemBackgroundPointerOver"
ResourceKey="MenuFlyoutItemselectedColor" />
<StaticResource x:Key="MenuFlyoutItemBackgroundPressed"
ResourceKey="MenuFlyoutItemselectedColor" />
</maui:MauiWinUIApplication.Resources>
運用しやすくするコツ:色の“意味”でキー名を付ける
MenuFlyoutItemselectedColor のように用途が分かる名前でも問題ありませんが、チーム開発や将来の改修を考えると、「いつ使う色なのか」を名前に含めると保守性が上がります。
- 例:
MenuFlyoutItemSelectedBackgroundBrush - 例:
ContextMenuHighlightBrush
「なぜこの色なのか」「どの状態を統一しているのか」が名前から伝わると、デザイン調整が入ったときも迷子になりにくいです。
ライト/ダークに合わせて色を切り替えたい場合(任意)
オレンジ固定だとテーマによってコントラストが強すぎたり弱すぎたりすることがあります。Windowsのライト/ダークに追従したい場合は、ThemeDictionariesを使って色を分けると自然です。
<maui:MauiWinUIApplication.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="MenuFlyoutItemselectedColor" Color="#FFE7A800" />
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<SolidColorBrush x:Key="MenuFlyoutItemselectedColor" Color="#FFFFB300" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
<StaticResource x:Key="MenuFlyoutItemBackgroundPointerOver" ResourceKey="MenuFlyoutItemselectedColor" />
<StaticResource x:Key="MenuFlyoutItemBackgroundPressed" ResourceKey="MenuFlyoutItemselectedColor" />
</ResourceDictionary>
色は一例です。実際のUIに合わせて、背景とのコントラスト(読みやすさ)を優先して調整してください。
補足:開発環境では直ったのに、本番(リリース/発行済みアプリ)で透明のままになるケース
デバッグ実行では反映されていたのに、リリースビルドや発行済みアプリで見ると透明のまま、というケースがあります。結論から言うと、これは「コードが効いていない」のではなく、新しいリソースを含んだアプリがユーザー環境に届いていないのが原因であることが多いです。
特にWindowsアプリは、MSIXやストア配布などの影響で、手元のデバッグ環境とは反映のされ方が変わります。変更を確認するときは、次のチェックをセットで行うのがおすすめです。
| チェック項目 | 狙い | 具体的な確認・操作 |
|---|---|---|
| 新しいビルド/新バージョンを発行したか | 配布物に修正が入っているか | バージョン番号を更新してビルドし直す(同一バージョンのまま上書きしない) |
| 端末側に古いアプリが残っていないか | キャッシュ/古いパッケージの影響排除 | 一度アンインストールしてから再インストール、または更新の適用を確認 |
| リリース構成での確認か | デバッグ限定の挙動を排除 | Releaseで発行したパッケージをインストールして確認する |
| Platforms/Windows/App.xamlの編集箇所が正しいか | 別ファイルを触っていないか | WindowsターゲットのApp.xamlで、MauiWinUIApplication.Resources に入っているか確認 |
今回のように「本番だけ透明」の場合でも、提示コードを含む修正を入れた新しいビルド/新バージョンを発行して反映を確認することで、最終的に問題が解消するケースが多いです。
見た目の品質を上げるための追加ポイント
背景色を固定できると一気に見やすくなりますが、UIとしての完成度を上げるなら、次の観点も一緒に押さえると安心です。
文字色も「選択中に読める」ことを優先する
背景を濃くした場合、文字が既定のままだとコントラストが不足して読みにくくなることがあります。背景と同様に、選択中の文字色も調整したくなる場面があります。
考え方は同じで、WinUIが参照しているForeground系のキーを上書きします。キー名は環境やWinUIのバージョンで差がある場合があるため、まずはWindows側のテーマリソース(Generic.xamlなど)でMenuFlyoutItemが参照しているキーを確認し、該当するものを追加してください。
アクセシビリティ(コントラスト)を落とさない
- 背景色と文字色の組み合わせで、最低限「ぱっと見で読める」コントラストを確保する
- ハイコントラスト設定を使うユーザーがいる場合、テーマに追従する設計(ThemeDictionaries)も検討する
- 色だけで状態を表現せず、必要に応じてアイコンやチェック表示なども併用する
うまくいかないときの切り分け(実務で効くチェックリスト)
「上書きしたのにまだ透明に見える」「一部のメニューだけ効かない」といった場合は、次の順で潰していくと原因に早く辿り着けます。
- 確認しているのは本当にWindowsターゲットか(マルチターゲットのビルド設定で混乱しがち)
- 上書きしているキー名は正しいか(スペル違い、大小文字、似たキーの取り違え)
- 別のResourceDictionaryが後から同じキーを上書きしていないか(統合したテーマファイルがある場合に起きる)
- 選択状態がPointerOver/Pressed以外で表現されていないか(キーボード操作やタッチで状態遷移が異なることがある)
- テスト環境に古いアプリが残っていないか(特に発行済みアプリの検証で重要)
この方法が選ばれやすい理由:テンプレート改造より安全で、Windowsだけに閉じられる
MenuFlyoutItemのテンプレートを丸ごと差し替える方法もありますが、状態(Normal/PointerOver/Pressed/Disabledなど)やアクセシビリティ対応まで含めて再実装することになり、保守コストが上がりがちです。
一方で、今回のようにWinUIのリソースキーを上書きする方法は「既存の仕組みを活かしたまま、色だけを差し替える」ため、影響範囲が読みやすく、将来のアップデートでも破綻しにくいのが利点です。しかも Platforms/Windows 配下に閉じるので、他プラットフォームの見た目を巻き込まずに済みます。
まとめ:選択中の透明化は「選択状態の背景ブラシ」を上書きすれば解消できる
- MenuFlyoutItemは状態ごとに別の背景ブラシを参照する
- 選択中の背景が透明に見えるなら、
MenuFlyoutItemBackgroundPointerOverとMenuFlyoutItemBackgroundPressedの上書きが効く - 反映されない場合は、本番環境に新しいビルド/新バージョンが届いているかを先に疑う
「見た目の違和感」はユーザー体験を直撃します。Windows(WinUI)側のリソースを正しく押さえておくと、MAUIアプリでも狙い通りのUIに仕上げやすくなります。

コメント