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);
}