Установка свойства локально, то есть напрямую, всегда будет переопределять настройку Style
этого свойства. Поскольку триггеры связаны со свойствами, они также переопределяются. См. Документы Microsoft: список приоритетов настройки свойств зависимостей для получения дополнительной информации.
Обычно это не проблема, поскольку вы определяете неявный Style
с намерением создать тему по умолчанию. И общее правило дизайна пользовательского интерфейса - сохранять целостность внешнего вида.
Решение 1. Триггер (и DataTrigger) - не рекомендуется
Как упоминалось ранее, Trigger
и DataTrigger
привязаны к свойству или основаны на его состоянии. Триггер разрешается, когда синтаксический анализатор пытается разрешить значение свойства (которое в данном случае будет действием триггера).
Из-за приоритета DependencyProperty
вы должны определить специализированный Style
для переопределения по умолчанию. Локальные значения остановят синтаксический анализатор XAML для поиска любого параметра Style
свойства и, следовательно, проигнорируют все триггеры, указанные для свойства c.
Специализированная Style
должна основываться на значениях по умолчанию, чтобы разрешить выборочные переопределения:
<Window>
<Window.Resources>
<!-- Implicit default Style -->
<Style TargetType="TextBox">
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Border BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}">
<ScrollViewer x:Name="PART_ContentHost"
Margin="0" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush"
Value="{Binding RelativeSource={RelativeSource Self}, Path=BorderBrushOnMouseHover}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Explicit specialized Style based on the implicit default Style -->
<Style x:Key="SpecializedStyle"
TargetType="TextBox"
BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="BorderBrush" Value="#FF1E1E1E" />
<!-- Other default overrides -->
<Setter Property="BorderBrushOnDisabled" Value="#FF470303" />
<Setter Property="BorderBrushOnFocused" Value="#FF1176BB" />
<Setter Property="BorderBrushOnMouseHover" Value="#FF1176BB" />
</Style>
</Window.Resources>
<!-- This now works -->
<local:IconTextBox Style="{StaticResource SpecializedStyle}" />
</Window>
Решение 2: VisualStateManager (рекомендуется)
Если вы предпочитаете обрабатывать визуальные эффекты без необходимости определения специальных стилей, вы должны использовать VisualStateManager
. Так как этот тип запуска основан на событиях (в отличие от состояний Trigger
и DataTrigger
), локальные установки значений свойств не будут переопределять триггер.
Именно поэтому вы можете установить свойства, такие как Background
, для каждого элемента управления по умолчанию, не нарушая визуальные эффекты - по умолчанию элементы управления реализованы с использованием VisualStateManager
для обработки визуальных состояний.
Необязательно : если вы хотите сохранить гибкость внешнего вида (темы), вы можете использовать ComponentResourceKey
. Определение ResourceKey
позволяет заменить ресурс темы путем определения нового ресурса с использованием того же x:Key
.
VisualStateManager
делает использование элементов управления и их настройку более удобной:
IconTextBox.cs (необязательно)
class IconTextBox : TextBox
{
public static ComponentResourceKey DefaultBorderBrushKey
=> new ComponentResourceKey(typeof(IconTextBox), "DefaultBorderBrush");
}
Generi c .xaml
<ResourceDictionary>
<!-- Define the original resource (optional)-->
<Color x:Key="{ComponentResourceKey {x:Type IconTextBox}, DefaultBorderBrush}">OrangeRed</Color>
<Style TargetType="IconTextBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="IconTextBox">
<Border x:Name="Border"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.5" />
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{DynamicResource {x:Static IconTextBox.DefaultBorderBrushKey}}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ScrollViewer x:Name="PART_ContentHost"
Margin="0" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
App.xaml (необязательно) Переопределите ресурс цвета по умолчанию:
<ResourceDictionary>
<!-- Override the original resource -->
<Color x:Key="{x:Static IconTextBox.DefaultBorderBrushKey}" >Blue</Color>
</ResourceDictionary>
Посетите Документы Microsoft: стили и шаблоны элементов управления , чтобы найти стиль по умолчанию для запрошенного элемента управления. Вы найдете все необходимые части шаблона, а также все доступные визуальные состояния, которые определены с помощью указанного элемента управления c. Вы можете использовать эту информацию для реализации VisualStateManager
. Например, Документы Microsoft: состояния TextBox