アプリケーションに動的テーマ切り替えを追加するように要求されましたが、これを行う方法がわかりません。
現在の状況は次のとおりです。アプリケーションには、明示的な(暗黙的ではない)スタイルのマージされたリソースディクショナリがあります。StaticResource
アプリケーションのビューは、マークアップ拡張機能を介してこれらのスタイルを参照します。暗黙的なスタイルを使用しない理由は、一般的なタイプのコントロールを複数回検索するためです。たとえば、ある場所のボタンは別の場所のボタンとは異なって見えます。
したがって、私たちがやりたいのは、これらの名前付きスタイルを新しい名前付きスタイルのセットに置き換えるテーマを作成することです。
アプローチ1
最初の試みは、テーマごとにリソース辞書を作成することでした。一般的な辞書からスタイルの1つを削除し、それらを各テーマ辞書に配置して、次のように各コピーに異なる外観を与えました。
<!-- RedTheme.xaml -->
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
mc:Ignorable="d"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008">
<Style x:Key="HeaderContentStyle" TargetType="ContentControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Grid Margin="0" Background="Red">
<ContentPresenter Content="{TemplateBinding Content}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
<!-- BlueTheme.xaml -->
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
mc:Ignorable="d"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008">
<Style x:Key="HeaderContentStyle" TargetType="ContentControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Grid Margin="0" Background="Blue">
<ContentPresenter Content="{TemplateBinding Content}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
次に、XAMLからリソースディクショナリの1つを動的にロードし、それをアプリケーションのマージされたディクショナリに挿入するコードを追加しました。
// In App.xaml.cs
var themeUri = new Uri(
"OurApp;component/Themes/RedTheme.xaml", UriKind.Relative);
var resourceInfo = GetResourceStream(themeUri);
using (var stream = resourceInfo.Stream)
{
using (var reader = new StreamReader(stream))
{
var xamlText = reader.ReadToEnd();
var dict = XamlReader.Load(xamlText) as ResourceDictionary;
Resources.MergedDictionaries.Add(dict);
}
}
これはある程度機能しました。起動時に「テーマ」を読み込んだ場合、そのテーマのスタイルが表示されていました。しかし、うまくいかなかったのは、起動後に他のテーマに切り替えようとしたことでした。マージされたディクショナリに他のテーマテーマディクショナリを追加しても、UIは変更されませんでした。また、古いテーマ辞書をクリアして新しいテーマ辞書を追加することもしませんでした。これらのいずれも実行せずに、ルートビジュアルを削除して再度追加しました。
アプローチ2
その後、SilverlightToolkitパターンのテーマを使用してみました。これは、明示的なスタイルではなく暗黙的なスタイルを切り替えることを目的としているため、機能しなかったと思います。テーマから派生したクラスを作成し、そのリソースディクショナリURIを設定して、そのテーマをルートビジュアルに追加しました。ただし、メインのUIクラスを作成したときに、UIによって参照される明示的なスタイルが見つからなかったため、実行時例外が発生しました。 ContentControl
そこで、テーマリソースディクショナリの1つをアプリケーションのマージされたディクショナリにロードしてみました。これにより、メインUIクラスを作成し、Style
オブジェクト内に配置することができました。ただし、Style
リソースディクショナリ内の明示的なスタイルは、アプリケーションのマージされたディクショナリ内で定義されたスタイルをオーバーライドできませんでした。したがって、何も変化していないように見えました。
現在のアプローチ
そこで今、私は3番目のアプローチを検討しています。これには、次のようなものを使用した添付プロパティが含まれますTheming.Style="StyleName"
。次に、アプリケーションの他の場所で、テーマ名とスタイル名のオーバーライドの間の関連付けが維持されます。テーマが変更されるたびに、テーマに適したスタイルが適用されます。
ジレンマ
すでにホイールが存在する場合は、ホイールを再発明したくありません。明示的なスタイルを含むテーマを切り替えることができるSilverlightに組み込まれているものはすでにありますか?私がやりたいことをさせてくれるサードパーティのライブラリはありますか?