7

反正有动画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>

我尝试过的故事板是:

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

它们都不起作用。任何想法?甚至可能吗?

4

3 回答 3

11

好吧,感谢所有试图帮助我的人,我找到了答案。似乎当我们将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>

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

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

这对我有用。


是一个工作示例。

于 2013-08-25T02:06:36.960 回答
9

这比我想象的更成问题。这是我的原始答案:


这绝对是可能的——这就是 ColorAnimationXXX 类的用途。

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

因此,在您的情况下,相关代码将是:

<VisualState Name="...">
   <Storyboard>
      <ColorAnimation To="Green" 
                      Storyboard.TargetName="tbBrush" 
                      Storyboard.TargetProperty="Color"/>
    </Storyboard>
</VisualState>

和:

<TextBox.Foreground>
  <SolidColorBrush x:Name="tbBrush" Color="#FF666666"/>
</TextBox.Foreground>

从理论上讲,这一切都很好,直到我意识到它在某种风格上不起作用。而Background样式中 Grid 的属性很容易设置动画,例如:

Storyboard.TargetProperty="(Grid.Background).(SolidColorBrush.Color)"

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

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

除了它不起作用的事实之外,在内部设置 Foreground 属性似乎也不正确,因为外部消费者希望控制该属性的值。因此,鉴于 TextBox 的 Foreground 不会遵循样式中的任何内容,我得出的结论是,最好使用 TextBox 样式中的嵌套 TextBox 来实现该功能。外部样式包含状态管理器和大部分布局,然后内部 TextBox 有自己的样式和控件模板,旨在显示文本位。外部样式能够设置内部 TextBox 的 Foreground 属性,内部将遵循该属性,并且至关重要的是外部样式可以在状态管理器中设置此值。

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

我很想听听其他人对这种方法的评论,以及它是否有任何我没有考虑过的问题。根据我解决问题和窥探生成的应用程序的尝试,这是我目前能看到的最简单的解决方案。

于 2013-08-24T22:07:45.293 回答
2

您可以绑定Storyboard.Target到 TemplatedParent:

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

不幸的是,我只能在样式中设置普通前景画笔并直接在 TextBox 元素上设置时才能使用它:

<TextBox Foreground="{StaticResource NormalBrush}" Style="{StaticResource RegularTextBox}" />

如果在样式中设置,触发 MouseOver 状态会抛出“无法在不可变对象实例上设置动画'(0).(1)'”。 编辑:如果在初始化后再次设置 TextBox 前景,也会发生这种情况。

于 2013-08-25T01:45:05.570 回答