Переключение темы выполнения с явными стилями в Silverlight 4 - PullRequest
4 голосов
/ 22 сентября 2010

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

Вот текущая ситуация: наше приложение имеет объединенный словарь ресурсов с явными (неявными) стилями. Представления в нашем приложении ссылаются на эти стили через расширение разметки StaticResource. Причина, по которой мы не используем неявные стили, состоит в том, что у нас несколько типов общих элементов управления; например, кнопки в одном месте выглядят иначе, чем кнопки в другом.

Итак, мы хотим создать темы, которые заменят эти именованные стили новым набором именованных стилей.

Подход 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 и вставил его в объединенные словари приложения:

// 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);
    }
}

Это сработало в некоторой степени. Если я загрузил «theme» во время запуска, отобразился стиль этой темы. Однако, то, что не работало, пыталось переключиться на другую тему после запуска. Добавление словаря другой темы к объединенным словарям не привело к изменению пользовательского интерфейса. Ни один из них не очистил старый словарь тем и не добавил новый. Ни один из них не сделал ничего, после чего удалил корневой визуал и добавил его снова.

Подход 2

После этого я попытался использовать шаблон тем Silverlight Toolkit. Полагаю, это не сработало, потому что предназначено для переключения неявных стилей вместо явных . Я создал свой производный от Theme класс, установил URI его словаря ресурсов и добавил эту тему в корневой визуальный элемент ContentControl. Затем, однако, когда я создал свой основной класс пользовательского интерфейса, явный стиль, на который ссылается пользовательский интерфейс, не был найден, поэтому возникло исключение времени выполнения.

Итак, я попытался загрузить один из словарей ресурсов темы в объединенные словари приложения. Это позволило создать основной класс пользовательского интерфейса и поместить его в объект Style. Однако явные стили внутри словаря ресурсов Style не смогли переопределить стили, определенные внутри объединенных словарей приложения. Следовательно, ничего не изменилось.

Текущий подход

Так что теперь я рассматриваю третий подход. Это будет связано с прикрепленным свойством, используемым примерно так: Theming.Style="StyleName". Затем в другом месте приложения будет поддерживаться связь между именами тем и переопределениями имен стилей. Всякий раз, когда тема меняется, применяются правильные стили для темы.

Дилемма

Я бы не стал изобретать колесо, если оно уже есть. В Silverlight уже есть что-то, что позволяет переключать темы, содержащие явные стили? Есть ли сторонние библиотеки, которые позволили бы мне делать то, что я хочу?

1 Ответ

4 голосов
/ 22 октября 2010

Я больше не в компании, поэтому я не могу публиковать конкретный код, который мы в итоге использовали, но мы использовали подход с присоединенным свойством.Мы заменили присваивание свойству Style для объектов, которые необходимо динамически обработать, с прикрепленным свойством Theming.Style, для которого установлено то же значение.Затем в наших словарях ресурсов мы создали стили с префиксом имени темы, например, когда у нас когда-то был стиль «StandardButton», мы создавали бы дополнительные стили с именами «Blue | StandardButton» и «Clean | StandardButton».Наш механизм создания тем мог бы искать эти стили для каждой темы всякий раз, когда мы переключали темы, и применять их к элементам с прикрепленными свойствами.

Надеемся, что это полезный подход для других, но предпочтительно есть библиотекатам, который уже решает эту проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...