やりたいこと
画面に配置するコントロール類は変えずに、条件によってコントトール類の見た目を変えたい。
イメージとしては、同じアプリでも
- お客様Aで動くアプリの画面では、背景は黒で、ボタンは赤色
- お客様Bで動くアプリの画面では、背景は白で、ボタンは青色
というようなことをしたい。
やり方
リソースディクショナリを切り替えるという方法で、実現できる。
(リソースディクショナリの作り方 → こちら)
サンプル
リソースディクショナリを2つ作る
ここでは、「Dictionary1.xaml」と「Dictionary2.xaml」の2つを作っている。
中身は下記の通り。GridとButtonのstyleを定義している。
(違いは、GridとButtonのBackgroundの色のみ)
<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>
<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を指定している。
<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>
リソースディクショナリの切り替えをする部分
App.xamlのコードビハインドに、ディクショナリの切り替えをする処理を記述する。
ここに書けば、ほかのxamlで書いたWindowにも反映されるっぽい。
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にするかで、下記のように画面が変わる。
問題
このやり方で実現できるのだが、画面を作成時、デザイナーを開いてxamlコードをみると、下図のように、波線でエラーが出てしまう。(エラー(警告?)は出ているが、ビルドは通る。)
実行時にしかリソースディクショナリが紐づけられないからだと思われる。
実行時に同じ個所を見ると、実行の際にディクショナリが紐づけられたためか、波線の警告は出ていない。
動きはするが、デザイン時にどういう画面表示になるか見ることができず、不便。
ざっと調べてはみたが、これといった解決方法を見つけられず。→折を見て、調べてみる。
別のプロジェクトにリソースディクショナリのxamlがある場合
下記を参照。
https://qiita.com/NumAniCloud/items/3d64199aee8876d53f67
参考
WPF アプリケーションの国際化 (Windows/.NET/WPF)
http://umezawa.dyndns.info/wordpress/?p=5131