Mike Hankey Ответов: 1

Измените тему в WPF, тема не меняется


Это всего лишь черновик для POC!

The Dictionary hierarchy is;
  Colors
  Brushes
  Styles

So the ordering is important


Я пытаюсь изменить тему в WPF, я могу сделать это так;
+        private void ChangeTheme(string themeName)
+        {
+            ResourceDictionary resource = null;
+            using (FileStream fs = new FileStream("../../../Resources/ResourceDictionaries/" + themeName + ".xaml", FileMode.Open, FileAccess.Read))
+                resource = (ResourceDictionary)XamlReader.Load(fs);
+
+            Application.Current.Resources.MergedDictionaries.Clear();
+            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary()
+            { Source = new Uri("pack://application:,,,/Resources/ResourceDictionaries/dictionary1.xaml") });
+            Application.Current.Resources.MergedDictionaries.Add(resource);
+            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary()
+            { Source = new Uri("pack://application:,,,/Resources/ResourceDictionaries/Monotone.Brushes.xaml") });
+            Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary()
+            { Source = new Uri("pack://application:,,,/Resources/ResourceDictionaries/Monotone.xaml") });
+        }


Но если я добавлю больше ResourceDictionaries в проект, мне придется вернуться сюда и внести изменения в список.

Что я уже пробовал:

Поэтому я подумал, что сделаю это таким образом, но это, похоже, не работает. Тема не меняется! Новая тема загружается, старые словари переносятся в dictionaryCollection, и все добавляется обратно в приложение.Текущий.Ресурсы.MergedDictionariy но новая тема не показывается?

Я погуглил пару часов, и все, что я нашел, говорит, что это должно сработать?

private void ChangeTheme(string themeName)
{
    ResourceDictionary resource = null;
    string file = "../../../Resources/ResourceDictionaries/" + themeName + ".xaml";
    //using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
    //    resource = (ResourceDictionary)XamlReader.Load(fs);

    resource = new ResourceDictionary();
    resource.Source = new Uri(file, UriKind.Relative);

    ResourceDictionary rd = GetActualResourceDictionary();
    if (rd != null)
        Application.Current.Resources.MergedDictionaries.Remove(rd);

    // Create collection to hold old RecourceDictionaries
    System.Collections.ObjectModel.Collection<ResourceDictionary> dictionaryCollection = new
        System.Collections.ObjectModel.Collection<ResourceDictionary>();

    // Copy REsourceDictionaries left after removing the Theme
    foreach (ResourceDictionary dict in Application.Current.Resources.MergedDictionaries)
        dictionaryCollection.Add(dict);

    Application.Current.Resources.MergedDictionaries.Clear();
    Application.Current.Resources.MergedDictionaries.Add(resource);

    foreach (ResourceDictionary dict in dictionaryCollection)
        Application.Current.Resources.MergedDictionaries.Add(dict);
}

//NOTE This works but the
static ResourceDictionary GetActualResourceDictionary()
{
    // get the actual ResourceDictionary
    foreach (ResourceDictionary res in Application.Current.Resources.MergedDictionaries)
    {
        if (res.Source != null)
        {
            string source = res.Source.ToString();
            if (source.ToUpper().Contains("THEME"))
                return res;
        }
    }
    return null;
}

1 Ответов

Рейтинг:
1

Pete O'Hanlon

Вы упустили одну важную вещь из вашего примера здесь: как вы на самом деле используете свои стили внутри вашего XAML. Тема сможет изменить ресурс только в том случае, если это DynamicResource, так что любой StaticResource записи будут сохранять свой первоначальный стиль, независимо от того, что вы делаете со словарями ресурсов.


Mike Hankey

Пит, спасибо за Ваш вклад. Я полный нуб, пожалуйста, потерпите меня.

У меня есть файл colors.xaml, который определяет цвета, которые я использую.
Затем у меня есть файл brushes.xaml, который определяет кисти с использованием цветов, и все кисти объявляются динамическими.
Затем у меня есть файл styles.xaml, который определяет стиль для всех элементов управления, и они объявляются динамическими.

В моем примере выше первый список работает нормально, все цвета меняются между темными и светлыми темами.
Но код во 2-м списке не работает, и мне интересно, вызывает ли проблему временное хранилище во временном списке?

Надеюсь, я ответил на ваш вопрос.

Pete O'Hanlon

Майк, в этом разделе:
ResourceDictionary rd = GetActualResourceDictionary();
if (rd != null)
Приложение.Текущий.Ресурсы.Слившиеся с толпой революционеры.Удалить(rd);

Вы удаляете только один словарь. Вы уверены, что это то, что вы должны делать?

Mike Hankey

Пит,
Да, я удаляю только файл Color.xaml, потому что все основано на определенных цветах.
Причина, по которой я сохраняю остальное в списке temp, заключается в том, что порядок важен, поскольку все основано на цветах.

Pete O'Hanlon

Что-то еще нужно посмотреть, является ли Урикинд правильным или нет. Попробуйте изменить его на UriKind.RelativeOrAbsolute.

Mike Hankey

Я действительно пытался это сделать.

По - вашему, должно ли то, что я пробовал, сработать?
Вы бы так поступили?

Спасибо Пит

Pete O'Hanlon

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

Окно.Ресурсы.Слившиеся с толпой революционеры.Добавить(новый объект ResourceDictionary { Источник = новый URI("упаковка://применение:,,,/MikeSample;аксессуары/кисти.язык XAML", параметре urikind.RelativeOrAbsolute) });

Mike Hankey

Да, я поменял их все на стаи, я учусь довольно быстро.

Я купил WPF 4.5 Unleashed, и хотя это хорошая книга, она не вдается в подробности, но охватывает почти все.

То, что я нахожу в интернете, если я могу найти его, обычно не работает, но дает мне общее представление, и я могу в большинстве случаев понять, что нужно сделать, но все еще борюсь в других областях.

Можете ли вы порекомендовать какие-нибудь углубленные книги или tuts?

Pete O'Hanlon

Извини, Майк, я пропустил это. Если бы я начал сейчас, я бы прочитал статьи WPF здесь Джоша Смита, Карла Шиффлетта, Дэниела Воана и Саши Барбера. У них все в значительной степени покрыто.

Mike Hankey

Спасибо Пит