2009-05-10 2 views
10

WPF позволяет библиотеке управления предоставлять различные ресурсные словари для разных системных тем, что позволяет приложению соответствовать выбранной визуальной теме операционной системы (Aero, Luna и т. Д.).Можно ли использовать темы WPF для включения нескольких скинов для приложения, которое можно изменить во время выполнения?

Мне интересно, могу ли я включить несколько тематических ресурсных словарей с моим приложением и использовать некоторую существующую поддержку темы в рамках. Это должно работать для моих собственных имен тем и в идеале позволяет пользователю изменять тему и, следовательно, внешний вид приложения во время выполнения. Даже если это только настройка конфигурации, это все равно может быть интересно.

ответ

11

Вот фрагмент кода, который я использовал в своем приложении, который поддерживал тематику. В этом примере у меня есть две темы (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}" /> 
+0

Отличный ответ, я реализовал это, мне было интересно, как вы будете использовать это для изменения изображений связанных кнопок. Я задал вопрос здесь: http://stackoverflow.com/questions/39795317/how-do-i-dynamically-change-which-resource-folder-i-get-an-image-from – AidanO

3

Я не знаю, как это сделать в рамках, но вы можете сделать это, если будете создавать каждый элемент управления, который может изменить себя.

Теория состоит в том, чтобы сделать стиль DynamicResource, а затем загрузить ResourcesDictionary на основе конфигурации пользователей для разных стилей.

Here - статья, которая имеет пример.