在WPF中设置TextBox.Foreground的动画

jav*_*iry 5 wpf animation textbox storyboard wpf-4.0

反正有动画TextBox.ForegroundProperty吗?

<Color x:Key="NormalColor">#FF666666</Color>
<SolidColorBrush x:Key="NormalBrush" Color="{StaticResource NormalColor}" />

<Color x:Key="MouseOverColor">#FF666666</Color>
<SolidColorBrush x:Key="MouseOverBrush" Color="{StaticResource MouseOverColor}" />

<ControlTemplate x:Key="RegularTextBoxTemplate" TargetType="{x:Type TextBox}">
    <Grid>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
                <VisualStateGroup.Transitions>
                    <VisualTransition GeneratedDuration="0:0:0.1"/>
                </VisualStateGroup.Transitions>
                <VisualState x:Name="Normal"/>
                <VisualState x:Name="MouseOver">
                    <Storyboard>
                        <!-- storyboard to animating foreground here... -->
                    </Storyboard>
                </VisualState>
            </VisualStateGroup >
        </VisualStateManager>
        <ScrollViewer x:Name="PART_ContentHost" 
                      BorderThickness="0"
                      IsTabStop="False"
                      Background="{x:Null}"/>
    </Grid>
</ControlTemplate>

<Style x:Key="RegularTextBox" TargetType="{x:Type TextBox}">
    <Setter Property="Foreground" Value="{StaticResource NormalBrush}"/>
    <Setter Property="Template" Value="{StaticResource RegularTextBoxTemplate}"/>
</Style>
Run Code Online (Sandbox Code Playgroud)

我试过的故事板是:

<ColorAnimationUsingKeyFrames Storyboard.TargetName="PART_ContentHost"
                  Storyboard.TargetProperty="(Foreground).(SolidColorBrush.Color)">
    <EasingColorKeyFrame KeyTime="0" Value="{StaticResource MouseOverColor}" />
</ColorAnimationUsingKeyFrames>

<ColorAnimationUsingKeyFrames Storyboard.TargetName="PART_ContentHost"
              Storyboard.TargetProperty="(Control.Foreground).(SolidColorBrush.Color)">
    <EasingColorKeyFrame KeyTime="0" Value="{StaticResource MouseOverColor}" />
</ColorAnimationUsingKeyFrames>

<ColorAnimationUsingKeyFrames Storyboard.TargetName="PART_ContentHost"
          Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)">
    <EasingColorKeyFrame KeyTime="0" Value="{StaticResource MouseOverColor}" />
</ColorAnimationUsingKeyFrames>

<ColorAnimationUsingKeyFrames
                  Storyboard.TargetProperty="(Foreground).(SolidColorBrush.Color)">
    <EasingColorKeyFrame KeyTime="0" Value="{StaticResource MouseOverColor}" />
</ColorAnimationUsingKeyFrames>

<ColorAnimationUsingKeyFrames
              Storyboard.TargetProperty="(TextBox.Foreground).(SolidColorBrush.Color)">
    <EasingColorKeyFrame KeyTime="0" Value="{StaticResource MouseOverColor}" />
</ColorAnimationUsingKeyFrames>

<ColorAnimationUsingKeyFrames
              Storyboard.TargetProperty="(Control.Foreground).(SolidColorBrush.Color)">
    <EasingColorKeyFrame KeyTime="0" Value="{StaticResource MouseOverColor}" />
</ColorAnimationUsingKeyFrames>

<ColorAnimationUsingKeyFrames
          Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)">
    <EasingColorKeyFrame KeyTime="0" Value="{StaticResource MouseOverColor}" />
</ColorAnimationUsingKeyFrames>
Run Code Online (Sandbox Code Playgroud)

他们都没有工作.任何的想法?它甚至可能吗?

Ste*_*ett 9

这比我想象的更成问题.这是我原来的答案:


这绝对是可能的 - 这就是ColorAnimationXXX类的用途.

您的代码与此处的代码示例非常相似,后者使用ColorAnimation为颜色设置动画.示例中的属性采用了一个Brush(就像TextBox.Foreground),它在XAML中定义并给出一个名称,以便动画可以轻松引用它.

所以在你的情况下,相关的代码将是:

<VisualState Name="...">
   <Storyboard>
      <ColorAnimation To="Green" 
                      Storyboard.TargetName="tbBrush" 
                      Storyboard.TargetProperty="Color"/>
    </Storyboard>
</VisualState>
Run Code Online (Sandbox Code Playgroud)

和:

<TextBox.Foreground>
  <SolidColorBrush x:Name="tbBrush" Color="#FF666666"/>
</TextBox.Foreground>
Run Code Online (Sandbox Code Playgroud)

从理论上讲,这一切都非常好,直到我意识到它不是一种风格.而Background风格中Grid 的属性很容易动画,例如:

Storyboard.TargetProperty="(Grid.Background).(SolidColorBrush.Color)"
Run Code Online (Sandbox Code Playgroud)

找到要对文本的前景产生影响的动画属性要困难得多.最初我试过TextElement.Foreground,看起来很直观,我能够在Grid和ScrollViewer级别设置这个属性,我期望它对下面的所有子对象产生影响 - 包括它在底层的任何对象,包含文本TextBox.我的假设是TextBox内容将在内部设置为TextBlock,它将遵循其上设置的Foreground附加属性的值.我的假设似乎不正确,并且PART_ContentHost ScrollViewer的内容由TextBox中的控制逻辑设置为较低级别的对象,该对象不遵守顶级TextBox与其自身之间的对象树中的任何Foreground依赖属性.

那么问题是如何在被设置样式的TextBox的样式中设置TextBox的Foreground属性.为了测试,我尝试使用TwoWay TemplatedParent绑定来设置它.我认为我将PropertyPath设置为SolidColorBrush的颜色,但它仍然无法正常工作,因为此时Color属性显然是不可变的.我相信这个问题在这里有记录.

除了它不起作用之外,在内部设置Foreground属性似乎并不正确,因为外部消费者期望控制该属性的值.因此,鉴于TextBox的前景不会遵循某个样式中的任何内容,我得出结论,该功能最好使用TextBox样式中的嵌套TextBox实现.外部样式包含状态管理器和大部分布局,然后内部TextBox具有自己的样式和控件模板,其设计仅用于显示文本位.外部样式能够设置内部TextBox的Foreground属性,内部的TextBox将遵循,而外部属性可以在状态管理器中设置此值.

<ControlTemplate x:Key="RegularTextBoxTemplate" TargetType="{x:Type TextBox}"> 
    <Grid>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
                <VisualStateGroup.Transitions>
                    <VisualTransition GeneratedDuration="0:0:0.1"/>
                </VisualStateGroup.Transitions>
                <VisualState x:Name="Normal"/>
                <VisualState x:Name="MouseOver">
                    <Storyboard>
                        <ColorAnimation To="HotPink"
                            Storyboard.TargetName="InternalTextBox"
                            Storyboard.TargetProperty="(TextBox.Foreground).(SolidColorBrush.Color)"/>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <TextBox Foreground="Black" Text="{TemplateBinding Text}" x:Name="InternalTextBox">
            <TextBox.Style>
                <Style TargetType="{x:Type TextBox}">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type TextBox}">
                                <Grid Background="{x:Null}">
                                    <ScrollViewer x:Name="PART_ContentHost"
                                        BorderThickness="0"
                                        IsTabStop="False"
                                        Background="{x:Null}" />
                                </Grid>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </TextBox.Style>
        </TextBox>
    </Grid>
</ControlTemplate>

<Style x:Key="RegularTextBox" TargetType="{x:Type TextBox}">
    <Setter Property="Template" Value="{StaticResource RegularTextBoxTemplate}"/>
</Style>
Run Code Online (Sandbox Code Playgroud)

我有兴趣听听其他人对这种方法的评论,以及我是否有任何问题,我没有考虑过.基于我尝试解决问题并窥探最终的应用程序,这是我目前可以看到的最简单的解决方案.


jav*_*iry 8

好吧,感谢所有想帮助我的人,我找到了答案.当我们将TextBox.Foreground属性设置为资源时,故事板无法为其设置动画.所以,风格应该是这样的:

<Style x:Key="RegularTextBox" TargetType="{x:Type TextBox}">
    <Setter Property="Foreground">
        <Setter.Value>
            <SolidColorBrush Color="{DynamicResource NormalColor}"/>
        </Setter.Value>
    </Setter>
    <Setter Property="Template" Value="{StaticResource RegularTextBoxTemplate}"/>
</Style>
Run Code Online (Sandbox Code Playgroud)

这是我遇到的唯一问题.但需要记住一个注意事项.当我们想要在故事板中定位模板化父级时,不必绑定它.我们只需要离开它:

<!-- It's not necessary to set Storyboard.TargetName in storyboard -->
<!-- It will automatically target the TemplatedParent -->
<ColorAnimationUsingKeyFrames
              Storyboard.TargetProperty="(TextBox.Foreground).(SolidColorBrush.Color)">
    <EasingColorKeyFrame KeyTime="0" Value="{DynamicResource MouseOverColor}" />
</ColorAnimationUsingKeyFrames>
Run Code Online (Sandbox Code Playgroud)

这适合我.


是一个有效的例子.

  • 我不知道你是如何成功完成这项工作的.对我来说,它仍然导致不可变的Color异常. (2认同)