Подтвердить что ты не робот

Как продлить вместо переопределения стилей WPF

Я хочу использовать пользовательскую тему в своем приложении, и насколько я знаю, я могу это сделать, используя словарь ресурсов и ссылаясь на него в App.xaml. Стили будут переопределять значения по умолчанию следующим образом:

<Style TargetType="{x:Type Label">
    <Setter Property="Foreground" Value="Green" />
</Style>

Теперь, насколько я понимаю, стиль меток по умолчанию переопределяется с одинаковыми значениями, но все мои ярлыки ярлыков зеленые. Проблема начинается, когда я хочу снова скомпоновать одну метку. Когда я хочу изменить какое-то другое свойство в моей Grid, как это,

<Grid.Resources>
    <Style TargetType="{x:Type Label">
        <Setter Property="FontSize" Value="28" />
    </Style>
</Grid.Resources>

Все метки внутри моей сетки теряют цвет переднего плана и снова имеют по умолчанию (не переопределяли ли значения по умолчанию на предыдущем шаге?). После некоторых попыток выяснилось, что для этого я должен добавить другое свойство в Style declare BasedOn={StaticResource {x:Type Label}}", и он работает. Для меня это странно, потому что теперь мне придется повторять один код BasedOn в целом приложении, и это не так, как работает стилизация - это нужно делать автоматически! Например, в стилях HTML + CSS наследуются и объединяются, а в WPF они заменяются...

Обратите внимание, что когда я не использую элементы управления стилями, все еще получаю их взгляд от некоторых (системные темы?). Как я могу сказать им искать значения по умолчанию в другом месте, поэтому без какого-либо дополнительного кода в стилях они будут думать, что по умолчанию они должны быть зелеными?

Есть ли способ автоматизировать настройку свойства BasedOn? Или, может быть, лучше сделать это с большим трудом?

4b9b3361

Ответ 1

У меня была та же проблема. Я использовал Zack answer и улучшил его, как показано ниже, поэтому, если вы не укажете стиль, переопределенный умолчаний по-прежнему принимается во внимание. Это в основном то, что вы бы сделали, но только один раз в ResourceDictionary.

<Window x:Class="TestWpf.RandomStuffWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Random Stuff Window">
  <Window.Resources>
    <ResourceDictionary>
      <!-- Default Label style definition -->
      <Style TargetType="{x:Type Label}">
        <Setter Property="Foreground" Value="Green" />
      </Style>
      <!-- Extending default style -->
      <Style TargetType="{x:Type Label}" 
             x:Key="LargeGreenForegroundLabel" 
             BasedOn="{StaticResource {x:Type Label}}">
        <Setter Property="FontSize" Value="28" />
      </Style>
    </ResourceDictionary>
  </Window.Resources>
  <StackPanel>
    <Button Click="Button_Click">Click</Button>
    <Label Content="GreenForegroundLabel" /> <!-- Uses default style -->
    <Label Style="{StaticResource LargeGreenForegroundLabel}" 
           Content="LargeGreenForegroundLabel" />
  </StackPanel>
</Window>

Ответ 2

Wpf имеет разные уровни стилей, которые применяются в порядке глобального > локального. Стиль, установленный непосредственно на элементе управления, переопределит набор стиля по всему миру, как в вашем примере. Я пытался найти список всех разных мест, в которых элемент управления ищет свои стили, но я не могу найти его на данный момент. Насколько мне известно, вам придется использовать свойство BasedOn для наследования стиля и не полностью переопределять свойства этого стиля с помощью стиля, который вы устанавливаете локально.

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

<Window x:Class="TestWpf.RandomStuffWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Random Stuff Window">
  <Window.Resources>
    <ResourceDictionary>
      <Style TargetType="{x:Type Label}" 
             x:Key="GreenForegroundLabel">
        <Setter Property="Foreground" Value="Green" />
      </Style>
      <Style TargetType="{x:Type Label}" 
             x:Key="LargeGreenForegroundLabel" 
             BasedOn="{StaticResource GreenForegroundLabel}">
        <Setter Property="FontSize" Value="28" />
      </Style>
    </ResourceDictionary>
  </Window.Resources>
  <StackPanel>
    <Button Click="Button_Click">Click</Button>
    <Label Style="{StaticResource GreenForegroundLabel}" 
           Content="GreenForegroundLabel" />
    <Label Style="{StaticResource LargeGreenForegroundLabel}" 
           Content="LargeGreenForegroundLabel" />
  </StackPanel>
</Window>