Home > Software engineering >  WPF animation from code behind not working
WPF animation from code behind not working

Time:06-15

I am fiddling with watermark textboxes. I created a style where in template I have a TextBlock whose Text property is bound to Tag and when the TextBox gets focused I push the watermark up with animation. I've managed to implement this behavior in XAML (and it works just fine), here's the code:

<Style x:Key="WatermarkTextBox" TargetType="{x:Type TextBox}">
<!-- Generic styling -->
<Setter Property="BorderThickness" Value="1 1 1 1" />
<Setter Property="BorderBrush" Value="#ced4da" />
<Setter Property="Padding" Value="6 6 6 6" />
<Setter Property="FontSize" Value="16" />
<!-- Template -->
<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="{x:Type TextBox}">
            <Grid>
                <!-- Textbox area -->
                <Border
                    BorderThickness="{TemplateBinding BorderThickness}"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    CornerRadius="6"
                    Padding="{TemplateBinding Padding}"
                    >
                    <ScrollViewer 
                        x:Name="PART_ContentHost"
                        VerticalAlignment="Center"
                        />
                </Border>
                <!-- Watermark -->
                <Border 
                    x:Name="watermark"
                    Padding="4 0 4 0"
                    Background="#ffffff"
                    VerticalAlignment="Center"
                    HorizontalAlignment="Left"
                    Margin="8 0 0 0"
                    >
                    <Border.RenderTransform>
                        <TranslateTransform X="0" Y="0" />
                    </Border.RenderTransform>
                    <!-- Watermark text -->
                    <TextBlock
                        Text="{TemplateBinding Tag}"
                        Foreground="#212529"
                        FontSize="17"
                        />
                </Border>
            </Grid>

            <!-- Triggers -->
            <ControlTemplate.Triggers>
                <!-- Watermark animation -->
                <Trigger Property="IsFocused" Value="True">
                    <!-- Push watermark on top -->
                    <Trigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation 
                                    Storyboard.TargetName="watermark"
                                    Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.Y)"
                                    From="0" 
                                    To="-24"
                                    Duration="0:0:0.1"
                                    />
                            </Storyboard>
                        </BeginStoryboard>
                    </Trigger.EnterActions>
                    <!-- Return watermark to original position -->
                    <Trigger.ExitActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation 
                                    Storyboard.TargetName="watermark"
                                    Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.Y)"
                                    From="-24" 
                                    To="0"
                                    Duration="0:0:0"
                                    />
                            </Storyboard>
                        </BeginStoryboard>
                    </Trigger.ExitActions>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Setter.Value>
</Setter>

However, I also want to achieve this animation from code behind. I tried using following code on "GotFocus" event, but the animation doesn't get played.

private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
    TextBox txb = sender as TextBox;

    Border watermark = (Border)txb.Template.FindName("watermark", txb);
    DoubleAnimation moveAnimation = new DoubleAnimation(0, -24, new Duration(TimeSpan.FromSeconds(0.1)));
    watermark.BeginAnimation(TranslateTransform.YProperty, moveAnimation);
}

How can I translate the above animation from XAML to code behind?

CodePudding user response:

Your animation target is obviously wrong. Border does not have a TranslateTransform.YProperty property.

You must chose the correct animation target, in your case a TranslateTransform of the Border.

I recommend to extend TextBox to encapsulate the event handling and to add a Watermark property for more convenience. If make the property of type object and the host a ContentPresenter (or ContentControl) you can support any content as placeholder e.g., an Image.

private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
  TextBox txb = sender as TextBox;

  Border watermark = (Border)txb.Template.FindName("watermark", txb);
  var animationTarget = (TranslateTransform)watermark.RenderTransform;
  var moveAnimation = new DoubleAnimation(0, -24, new Duration(TimeSpan.FromSeconds(0.1)));
  animationTarget.BeginAnimation(TranslateTransform.YProperty, moveAnimation);
}
  • Related