Анимация двух вложенных элементов границы в WPF ControlTemplate

#wpf #xaml #animation #controltemplate #visualstatemanager

#wpf #xaml #Анимация #controltemplate #visualstatemanager

Вопрос:

Я пытаюсь создать новый ControlTemplate для текстового поля. В конце он должен использовать несколько пользовательских состояний, которые изменяют внешний вид элемента управления. ControlTemplate во фрагменте кода удален до костей, просто чтобы проиллюстрировать мою проблему.

Я хочу использовать два вложенных элемента границы и анимировать их границы и цвет фона в различных визуальных состояниях.

 <Style TargetType="{x:Type TextBox}">
    <Setter Property="OverridesDefaultStyle" Value="True" />
    <Setter Property="MinHeight" Value="20" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TextBoxBase}">
                <Border Name="Border" CornerRadius="2" BorderThickness="1" Margin="2">
                    <Border.Background>
                        <SolidColorBrush Color="White" />
                    </Border.Background>
                    <Border.BorderBrush>
                        <SolidColorBrush Color="Black" />
                    </Border.BorderBrush>
                    <Border Name="Inner" CornerRadius="2" Padding="2" BorderThickness="1">
                        <Border.BorderBrush>
                            <SolidColorBrush Color="Blue" />
                        </Border.BorderBrush> 
                        <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal" />
                            <VisualState x:Name="Disabled" />
                            <VisualState x:Name="ReadOnly" />
                            <VisualState x:Name="MouseOver">
                                <Storyboard>
                                    <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                        Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
                                        <EasingColorKeyFrame KeyTime="0" Value="#FFE8EDF9" />
                                    </ColorAnimationUsingKeyFrames>
                                </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <ScrollViewer Margin="0" x:Name="PART_ContentHost" />
                    </Border>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
  

Это почти базовый пример использования visualstates в шаблоне управления, который можно найти в Интернете. Когда дело доходит до события наведения курсора мыши, это не работает, и фон не меняется. Если я удалю внутреннюю границу, она будет работать так, как ожидалось.

Если кто-нибудь может помочь мне с этим шаблоном, я был бы очень признателен.

Ответ №1:

Ваша проблема заключалась в том, что вы прикрепили VisualStateManager.VisualStateGroups коллекцию к внутреннему Border элементу, поэтому, когда вы удалили внутренний Border , VisualStateGroups коллекция снова стала привязана к внешнему Border , поэтому она все еще работала . Все, что вам нужно сделать, чтобы исправить это, это переместить его во внешний Border :

 <Style TargetType="{x:Type TextBox}">
    <Setter Property="OverridesDefaultStyle" Value="True" />
    <Setter Property="MinHeight" Value="20" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TextBoxBase}">
                <Border Name="Border" CornerRadius="2" BorderThickness="1" Margin="2" Background="White" BorderBrush="Black">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal" />
                            <VisualState x:Name="Disabled" />
                            <VisualState x:Name="ReadOnly" />
                            <VisualState x:Name="MouseOver">
                                <Storyboard>
                                    <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
                                        <EasingColorKeyFrame KeyTime="0" Value="#FFE8EDF9" />
                                    </ColorAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Border Name="Inner" CornerRadius="2" Padding="2" BorderThickness="1" BorderBrush="Blue" Background="{x:Null}">
                        <ScrollViewer Margin="0" x:Name="PART_ContentHost" />
                    </Border>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
  

Комментарии:

1. опередил меня на секунды, и спасибо, что убрал эти зависимости для него, это как гвозди на доске, видя весь этот шум в чьем-то xaml … 1

2. спасибо, что убрал для него эти зависимости, это как гвозди на классной доске … ха-ха… Я точно знаю, что вы имеете в виду.

3. Чтобы завершить этот ответ, знайте, что события «захватываются» элементами управления, которые вы просматриваете (или любым другим действием, которое вы выполняете). Вероятно, происходит то, что ваша вторая граница фиксирует событие наведения курсора мыши, обрабатывает его, а затем предотвращает его настройку или пузырькование. Чтобы помочь вам с такого рода проблемами, попробуйте использовать такой инструмент, как XAMLSpy, чтобы увидеть, что на самом деле происходит во время выполнения

4. Ваш предложенный ответ творит чудеса для меня. Большое вам спасибо. В следующий раз я буду осторожен при подключении VisualStateManager.

5. На самом деле, вы переместили VisualStateGroups с внутренней на внешнюю границу, а не наоборот (как вы написали в своем ответе). И это именно то, чему оно принадлежит.