もくじ
https://tera1707.com/entry/2022/02/06/144447
やりたいこと
以前の記事で、アプリ起動時にResourceDictionaryを切り替えるということをした。
今回は、アプリがすでに起動してウインドウが出ている最中に、ResourceDictionaryを切り替えて、見た目を変更するということをしたい。
やり方
やること自体は↑の以前の記事と一緒なのだが、それをウインドウの中から呼んでやる。
つまり、↑の記事のコードで行っていた、Appクラスで行った下記の処理を、ウインドウの中で行ってやる。
サンプルコード
App.xaml.cs
スタートアップのコード。
ここで、ResourceDictionaryを切り替える処理を持つ。
using System.Windows; namespace ResourceDicJikken; public partial class App : Application { private ResourceDictionary? dict; private void Application_Startup(object sender, StartupEventArgs e) { dict = new ResourceDictionary(); Application.Current.Resources.MergedDictionaries.Add(dict); } public void ChangeTheme(bool themeSwitch) { dict!.Source = new Uri($"pack://application:,,,/ResourceDictionary/Dictionary{(themeSwitch ? 1 : 2)}.xaml"); } }
MainWindow.xaml.cs
ウインドウ側のコード。
ここで、Appクラスが持っているResourceDictionary切り替えのためのメソッドを呼ぶ。
using System.Windows; namespace ResourceDicJikken { public partial class MainWindow : Window { bool themeSwitch = false; public MainWindow() { InitializeComponent(); } private void Button_Click(object sender, RoutedEventArgs e) { ((App)Application.Current).ChangeTheme(themeSwitch); themeSwitch = !themeSwitch; } } }
Dictionary1.xaml、2.xaml
切替をする2つのResourceDictionaryのファイル。
それぞれ背景の色だけ異なる色を定義している。
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Style TargetType="Button"> <Setter Property="Background" Value="Purple"/> </Style> </ResourceDictionary>
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Style TargetType="Button"> <Setter Property="Background" Value="Yellow"/> </Style> </ResourceDictionary>
地味にハマるポイント
ResourceDictionaryを切り替える処理には、
public void ChangeTheme(bool themeSwitch) { dict!.Source = new Uri($"pack://application:,,,/ResourceDictionary/Dictionary{(themeSwitch ? 1 : 2)}.xaml"); }
と書いているのだが、このアドレス?ファイルのパス?みたいな部分、どう書くのコレ?となる。
ココの部分の書き方は、msの↓のdocに書いてあった。
VS2022のソリューションエクスプローラーで今回のslnの構成を見ると、こうなっている。
で、msのdocによると、
となっていて、今回の構成だと、「ResourceDictionary」というサブフォルダに入れているので、結果、
pack://application:,,,/ResourceDictionary/Dictionary1.xaml
という指定の仕方になる。
参考
Pack URIs in WPF
https://learn.microsoft.com/en-us/dotnet/desktop/wpf/app-development/pack-uris-in-wpf?view=netframeworkdesktop-4.8#local-assembly-resource-file
>「Local Assembly Resource File」 の部分。
Pack URIみたいな似たようなものをWinUIについて調べたときの記事。
WPFとWinUI3ではまた書き方が違うらしい。