WPF позволяет библиотеке управления предоставлять различные ресурсные словари для разных системных тем, что позволяет приложению соответствовать выбранной визуальной теме операционной системы (Aero, Luna и т.д.).
Мне интересно, могу ли я включить несколько тематических ресурсных словарей с моим приложением и использовать некоторую существующую поддержку темы в рамках. Это должно работать для моих собственных имен тем и в идеале позволяет пользователю изменять тему и, следовательно, внешний вид приложения во время выполнения. Даже если это только настройка конфигурации, это все равно может быть интересно.
Ответ 1
Вот фрагмент кода, который я использовал в своем приложении, поддерживающем их. В этом примере у меня есть две темы (Default и Classic XP). Ресурсы темы хранятся в DefaultTheme.xaml и ClassicTheme.xaml соответственно.
Это код по умолчанию в моем App.xaml
<Application ...>
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ArtworkResources.xaml" />
<ResourceDictionary Source="DefaultTheme.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style x:Key="SwooshButton" TargetType="ButtonBase">
<!-- style setters -->
</Style>
<!-- more global styles -->
</ResourceDictionary>
</Application.Resources>
</Application>
Затем в коде App.xaml у меня есть следующий способ, позволяющий изменить тему. В основном, то, что вы делаете, это очистить Словари ресурсов, а затем перезагрузить словарь новой темой.
private Themes _currentTheme = Themes.Default;
public Themes CurrentTheme
{
get { return _currentTheme; }
set { _currentTheme = value; }
}
public void ChangeTheme(Themes theme)
{
if (theme != _currentTheme)
{
_currentTheme = theme;
switch (theme)
{
default:
case Themes.Default:
this.Resources.MergedDictionaries.Clear();
AddResourceDictionary("ArtworkResources.xaml");
AddResourceDictionary("DefaultTheme.xaml");
break;
case Themes.Classic:
this.Resources.MergedDictionaries.Clear();
AddResourceDictionary("ArtworkResources.xaml");
AddResourceDictionary("ClassicTheme.xaml");
break;
}
}
}
void AddResourceDictionary(string source)
{
ResourceDictionary resourceDictionary = Application.LoadComponent(new Uri(source, UriKind.Relative)) as ResourceDictionary;
this.Resources.MergedDictionaries.Add(resourceDictionary);
}
То, что вам также нужно учитывать при таком подходе, состоит в том, что для любых стилей, которые используют тему, потребуется динамический ресурс. Например:
<Window Background="{DynamicResource AppBackgroundColor}" />
Ответ 2
Я не знаю, как это сделать в рамках, но вы можете сделать это, если будете создавать каждый элемент управления, который может изменить себя.
Теория состоит в том, чтобы сделать стиль a DynamicResource
, а затем загрузить ResourcesDictionary
на основе конфигурации пользователей для другого стиля.
Здесь - статья, в которой есть пример.