Переопределить переопределенную тему WPF - PullRequest
11 голосов
/ 04 марта 2010

Я пишу приложение WPF для WinXP, и я переопределил тему по умолчанию с темой Vista следующим образом:

protected override void OnStartup(StartupEventArgs e)
{
  base.OnStartup(e);

  var themerd = new ResourceDictionary();
  themerd.Source = new Uri(@"PresentationFramework.Aero;V3.0.0.0;31bf3856ad364e35;component\themes/aero.normalcolor.xaml", UriKind.Relative);

  Resources.MergedDictionaries.Add(themerd);
}

И в основном это работает нормально.Когда я использую элемент управления, например кнопку:

<Button />

Стиль выглядит хорошо, но если я использую кнопку с другим стилем, подобным этому:

<Button>
  <Button.Style>
    <Style TargetType="Button">
      <Setter Property="Width" Value="80" />
    </Style>
  </Button.Style>
</Button>

Стиль будет переопределятьуказанный стиль темы со стандартным стилем WinXP вместо построения поверх него.Это чрезвычайно ограничивает меня.Есть ли способ избежать этой проблемы?

1 Ответ

10 голосов
/ 04 марта 2010

Почему это происходит

Значение по умолчанию BasedOn = для стиля создается с использованием только словаря ресурсов текущей темы. Техника переопределения темы, которую вы показываете, на самом деле не меняет используемый словарь темы: она просто добавляет ресурсы из словаря ресурсов темы в словарь ресурсов приложения. Поскольку текущая тема не изменилась, по умолчанию BasedOn также не изменилось.

Как ее решить

Вариант 1: локально переопределить тему, перехватывая вызовы uxtheme.dll! GetCurrentThemeName на уровне Win32. Это довольно сложно, но работает для всех ваших стилей без изменений в вашем XAML.

Вариант 2: Установить BasedOn с помощью пользовательского MarkupExtension. Это будет выглядеть так:

<Style TargetType="Button" BasedOn="{DefaultAeroStyle Button}"> ...

Ваш пользовательский MarkupExtension будет загружать словарь тем Aero при первом использовании и сохранять его в статическом поле. Его конструктор будет принимать тип, а его ProvideValue будет искать тип в словаре, чтобы найти стиль.

Вариант 3: Установить BasedOn для промежуточного именованного стиля. Это будет выглядеть так:

<Application ...>
  <Application.Resources>
    <ResourceDictionary>
      <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="... theme path ..." />
      </ResourceDictionary.MergedDictionaries>

      <Style x:Key="ThemeButtonStyle" TargetType="Button" BasedOn="{StaticResource {x:Type Button}}" />
      <Style x:Key="ThemeListBoxStyle" TargetType="ListBox" BasedOn="{StaticResource {x:Type ListBox}}" />
      ...
    </ResourceDictionary>
  </Application.Resources>
</Application>

Теперь в вашем словаре нижнего уровня вы можете сказать:

<Style TargetType="Button" BasedOn="{StaticResource ThemeButtonStyle}" />

Вариант 4: установить BasedOn, используя статическое свойство и расширение разметки x: Static

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