Можно ли использовать темы WPF для включения нескольких тем оформления для приложения, которое можно изменить во время выполнения? - PullRequest
10 голосов
/ 10 мая 2009

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

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

Ответы [ 2 ]

12 голосов
/ 10 мая 2009

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

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

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

Здесь - статья с примером.

...