LoginSignup
3
6

More than 3 years have passed since last update.

[WPF/xaml]条件により使うResourceDictionaryを切り替えて、画面の見た目を変える

Last updated at Posted at 2019-06-12

やりたいこと

画面に配置するコントロール類は変えずに、条件によってコントトール類の見た目を変えたい。
イメージとしては、同じアプリでも

  • お客様Aで動くアプリの画面では、背景は黒で、ボタンは赤色
  • お客様Bで動くアプリの画面では、背景は白で、ボタンは青色

というようなことをしたい。

やり方

リソースディクショナリを切り替えるという方法で、実現できる。
(リソースディクショナリの作り方 → こちら)

サンプル

リソースディクショナリを2つ作る

ここでは、「Dictionary1.xaml」と「Dictionary2.xaml」の2つを作っている。
image.png

中身は下記の通り。GridとButtonのstyleを定義している。
(違いは、GridとButtonのBackgroundの色のみ)

Dictionary1.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:WpfApp20">
    <Style x:Key="MyButtonStyle" TargetType="Button">
        <Setter Property="Background" Value="Red"/>
    </Style>
    <Style x:Key="MyGridStyle" TargetType="Grid">
        <Setter Property="Background" Value="Black"/>
    </Style>
</ResourceDictionary>
Dictionary2.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:WpfApp20">
    <Style x:Key="MyButtonStyle" TargetType="Button">
        <Setter Property="Background" Value="Blue"/>
    </Style>
    <Style x:Key="MyGridStyle" TargetType="Grid">
        <Setter Property="Background" Value="White"/>
    </Style>
</ResourceDictionary>

Dictionaryを使うメイン画面

GridとButtonのStyleに、Keyを使ってリソースディクショナリに記述したstyleを指定している。

MainWindow.xaml
<Window x:Class="WpfApp20.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp20"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="200">

    <Grid Style="{StaticResource MyGridStyle}">
        <Button Content="ボタン" Margin="20" Style="{StaticResource MyButtonStyle}"/>
    </Grid>
</Window>

※リソースエディタ上ではこのように見えてる。
image.png

リソースディクショナリの切り替えをする部分

App.xamlのコードビハインドに、ディクショナリの切り替えをする処理を記述する。
ここに書けば、ほかのxamlで書いたWindowにも反映されるっぽい。

App.xaml.cs
using System;
using System.Windows;

namespace WpfApp20
{
    /// <summary>
    /// App.xaml の相互作用ロジック
    /// </summary>
    public partial class App : Application
    {
        public App()
        {
            // 条件により、読み込むDictionary.xamlを変える
            string dicPath = (true) ? "Dictionary1.xaml" : "Dictionary2.xaml";

            ResourceDictionary dic = new ResourceDictionary();
            dic.Source = new Uri(dicPath, UriKind.Relative);
            this.Resources.MergedDictionaries.Add(dic);
        }
    }
}

※App.xamlは、プロジェクト作成時のまま変更なし。

動作

これで完成。
App.xaml.csの「string dicPath = (true) ? "Dictionary1.xaml" : "Dictionary2.xaml";」の部分の条件をtrueにするかfalseにするかで、下記のように画面が変わる。

image.pngimage.png

問題

このやり方で実現できるのだが、画面を作成時、デザイナーを開いてxamlコードをみると、下図のように、波線でエラーが出てしまう。(エラー(警告?)は出ているが、ビルドは通る。)
image.png

実行時にしかリソースディクショナリが紐づけられないからだと思われる。
実行時に同じ個所を見ると、実行の際にディクショナリが紐づけられたためか、波線の警告は出ていない。

動きはするが、デザイン時にどういう画面表示になるか見ることができず、不便。
ざっと調べてはみたが、これといった解決方法を見つけられず。→折を見て、調べてみる。

別のプロジェクトにリソースディクショナリのxamlがある場合

下記を参照。
https://qiita.com/NumAniCloud/items/3d64199aee8876d53f67

参考

WPF アプリケーションの国際化 (Windows/.NET/WPF)
http://umezawa.dyndns.info/wordpress/?p=5131

3
6
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
6