Как расширить вместо переопределения стилей WPF
Я хочу использовать пользовательскую тему в своем приложении, и, насколько я знаю, я могу это сделать, используя словарь ресурсов и ссылаясь на него в приложении.код XAML. Стили будут переопределять значения по умолчанию следующим образом:
<Style TargetType="{x:Type Label">
<Setter Property="Foreground" Value="Green" />
</Style>
теперь, как я думаю, стиль Метки по умолчанию переопределен с теми же значениями, но все мои шрифты метки зеленые. Проблема начинается, когда я хочу, чтобы стиль одного ярлыка где-то снова. Когда я хочу изменить какое-то другое свойство в моей сетке, как это
<Grid.Resources>
<Style TargetType="{x:Type Label">
<Setter Property="FontSize" Value="28" />
</Style>
</Grid.Resources>
все метки внутри моей сетки теряют цвет переднего плана и снова имеют значение по умолчанию (разве я не переопределил значения по умолчанию на предыдущем шаге?). После некоторых попыток я узнал, что для этого мне нужно добавить другое свойство в Style
декларация BasedOn={StaticResource {x:Type Label}}"
и это работает. Это странно для меня, потому что теперь мне придется повторять один и тот же код BasedOn во всем приложении, и это не так, как работает стиль - это должно быть сделано автоматически! Например, в HTML + CSS стили наследуются и объединяются и в WPF их заменяют...
обратите внимание, что когда я не использую какие-либо элементы управления стилями, они по-прежнему выглядят из somehwere (Системные темы?). Как я могу сказать им искать значения по умолчанию где-то еще, чтобы без дополнительного кода на стилях они думали, что они должны быть зелеными по умолчанию?
есть ли способ автоматизировать настройку свойства BasedOn? Или, может быть, лучше сделать это чрезмерно?
2 ответов
У меня была та же проблема. Я использовал ответ Зака и улучшил его, как следующее, Поэтому, если вы не укажете стиль, переопределенное значение по умолчанию все еще учитывается. Это в основном то, что вы сделали бы, но только один раз в 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>
WPF имеет разные уровни стилей, которые применяются в порядке global > local. Набор стилей непосредственно в элементе управления переопределит набор стилей глобально, как в вашем примере. Я пытался найти список всех различных мест, которые элемент управления ищет для своих стилей, но я не могу найти его на данный момент. Насколько я знаю, вам нужно будет использовать свойство 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>