Есть ли способ изменить передний план средства прокрутки текстового поля в xaml без изменения локального свойства?

#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>