#wpf #triggers #textbox #foreground #visualstates
#wpf #триггеры #текстовое поле #передний план #visualstates
Вопрос:
Есть ли способ изменить Foreground
пользовательский TextBox
интерфейс в xaml с помощью триггеров или визуальных состояний без изменения локального основного свойства переднего плана?
Вот стиль xaml общего пользовательского текстового поля со случайно выбранными цветами:
<Style TargetType="{x:Type local:CustomTextBox}">
<Setter Property="Background" Value="White"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CustomTextBox}">
<Border x:Name="PART_Border"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="1">
<ScrollViewer x:Name="PART_ContentHost"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden"
Focusable="False"/>
</Border>
<ControlTemplate.Triggers>
<!-- Can be IsMouseOver, IsFocused, etc... -->
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="PART_Border"
Property="Background" Value="Green"/>
<Setter TargetName="PART_Border"
Property="BorderBrush" Value="DarkGreen"/>
<!-- The only method I know that works is this one
that changes the local property -->
<Setter Property="Foreground" Value="Yellow"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Я пытался использовать эти строки в триггере, но все терпят неудачу (ничего не делают):
<Setter TargetName="PART_ContentHost" Property="Foreground" Value="Yellow"/>
<Setter TargetName="PART_ContentHost" Property="TextBlock.Foreground" Value="Yellow"/>
<Setter TargetName="PART_ContentHost" Property="TextElement.Foreground" Value="Yellow"/>
<Setter TargetName="PART_Border" Property="TextBlock.Foreground" Value="Yellow"/>
<Setter TargetName="PART_Border" Property="TextElement.Foreground" Value="Yellow"/>
В кнопках цвет переднего плана можно изменить, изменив TextBlock.Foreground
родительский элемент (например TextBlock.Foreground
, of PART_Border
), но это не работает с текстовыми полями.
Изменение локального свойства, как это делает эта строка…
<Setter Property="Foreground" Value="Yellow"/>
… проблема в том, что если я позже изменю основное свойство переднего плана (например, с черного на серый), триггер больше не сможет изменить его на желтый, например, с помощью этого:
<local:CustomTextBox ... Foreground="Gray"/>
Визуальные состояния не могут взаимодействовать даже с основным свойством переднего плана.
Итак, есть ли другой способ, которого я не знаю, для достижения этого в xaml, или это ограничение wpf?
Ответ №1:
Что, если вы полностью переопределите ControlTemplate
?
<TextBox Text="Hiho" Foreground="Red">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Background" Value="White"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<TextBox Name="TheContent" Text="{TemplateBinding Text}"/>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="TheContent" Property="Foreground" Value="Yellow"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TextBox.Style>
</TextBox>
Ответ №2:
Вы могли бы анимировать свойство с помощью Storyboard
. Это вступит в силу для локальных значений:
<Window ...>
<Window.Resources>
<Style TargetType="{x:Type local:CustomTextBox}">
<Setter Property="Background" Value="White"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CustomTextBox}">
<Border x:Name="PART_Border"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="1">
<ScrollViewer x:Name="PART_ContentHost"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden"
Focusable="False"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="PART_Border" Property="Background" Value="Green"/>
<Setter TargetName="PART_Border" Property="BorderBrush" Value="DarkGreen"/>
<Trigger.EnterActions>
<BeginStoryboard x:Name="sb">
<Storyboard>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Brushes.Yellow}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="sb" />
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel>
<local:CustomTextBox Margin="10" Text="sample text" Foreground="Red" />
</StackPanel>
</Window>