Blog

posts tagged with styling

XAML Animated Headered TextBox Style (Part 2)

0 Comments
By Fons Sonnemans, 6-3-2017

Last week I wrote a blog item about the XAML Animated Headered TextBox Style. I got a lot of reactions on Twitter. Pieter Otten challenged me into adjusting my solution to make it conform the Material Design guidelines. In Android the header (Label) of the TextBox (Text Field) animates on Focus not when you enter a value. I tried to implement this by adjusting my style but that didn't work. I had to introduce an extra behavior to get it to work. See the result in this video.

AnimatedHeaderedTextBoxStyle demo video which works on Focus

MoveHeaderOnFocusBehavior

The MoveHeaderOnFocusBehavior is used to set the Visual States (Empty and NotEmpty) of the associated TextBox when it is loaded, gets the focus, loses the focus or when the text changes. This Behavior was build by subclassing the Behavior<T> class from the Microsoft.Xaml.Behaviors.Uwp.Managed NuGet package.

public class MoveHeaderOnFocusBehavior : Behavior<TextBox> {

    private bool _hasFocus;

    private void AssociatedObject_GotFocus(object sender, Windows.UI.Xaml.RoutedEventArgs e) {
        _hasFocus = true;
        UpdateState(true);
    }

    private void AssociatedObject_Loaded(object sender, RoutedEventArgs e) {
        UpdateState(false);
        this.AssociatedObject.Loaded -= this.AssociatedObject_Loaded;
    }

    private void AssociatedObject_LostFocus(object sender, Windows.UI.Xaml.RoutedEventArgs e) {
        _hasFocus = false;
        UpdateState(true);
    }

    private void AssociatedObject_TextChanged(object sender, TextChangedEventArgs e) {
        UpdateState(false);
    }

    protected override void OnAttached() {
        base.OnAttached();
        this.AssociatedObject.Loaded += this.AssociatedObject_Loaded;
        this.AssociatedObject.GotFocus += this.AssociatedObject_GotFocus;
        this.AssociatedObject.LostFocus += this.AssociatedObject_LostFocus;
        this.AssociatedObject.TextChanged += this.AssociatedObject_TextChanged;
    }

    protected override void OnDetaching() {
        base.OnDetaching();
        this.AssociatedObject.GotFocus -= this.AssociatedObject_GotFocus;
        this.AssociatedObject.LostFocus -= this.AssociatedObject_LostFocus;
        this.AssociatedObject.TextChanged -= this.AssociatedObject_TextChanged;
    }


    private void UpdateState(bool animate) {
        if (_hasFocus || !string.IsNullOrEmpty(this.AssociatedObject.Text)) {
            VisualStateManager.GoToState(this.AssociatedObject, "NotEmpty", animate);
        } else {
            VisualStateManager.GoToState(this.AssociatedObject, "Empty", animate);
        }
    }

}

 

Usage

I dragged and dropped the MoveHeaderOnFocusBehavior from the Assets window in Blend for Visual Studio to every TextBox of the Style 'AnimatedHeaderedTextBoxStyle'. That's all.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="using:App121"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:Interactivity="using:Microsoft.Xaml.Interactivity"
      x:Class="App121.MainPage"
      mc:Ignorable="d">

    <StackPanel Width="300"
                Margin="0,0,60,0"
                VerticalAlignment="Top"
                HorizontalAlignment="Center">

        <TextBox Header="Firstname"
                 Style="{StaticResource AnimatedHeaderedTextBoxStyle}"
                 IsSpellCheckEnabled="False"
                 InputScope="PersonalFullName">
            <Interactivity:Interaction.Behaviors>
                <local:MoveHeaderOnFocusBehavior />
            </Interactivity:Interaction.Behaviors>
        </TextBox>

        <TextBox Header="Lastname"
                 Style="{StaticResource AnimatedHeaderedTextBoxStyle}"
                 IsSpellCheckEnabled="False"
                 Margin="0,8"
                 InputScope="PersonalFullName">
            <Interactivity:Interaction.Behaviors>
                <local:MoveHeaderOnFocusBehavior />
            </Interactivity:Interaction.Behaviors>
        </TextBox>

        <TextBox Header="E-mail"
                 x:Name="textBoxEmail"
                 Style="{StaticResource AnimatedHeaderedTextBoxStyle}"
                 IsSpellCheckEnabled="False"
                 Text="fons.sonnemans@reflectionit.nl"
                 InputScope="EmailNameOrAddress">
            <Interactivity:Interaction.Behaviors>
                <local:MoveHeaderOnFocusBehavior />
            </Interactivity:Interaction.Behaviors>
        </TextBox>

        <Button Content="Next"
                Click="Button_Click"
                Margin="0,16,0,0" />

        <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
              Height="640"
              Margin="0,0,-60,0" />
    </StackPanel>
</Page>

 

The code

I have published the updated code on GitHub. I hope you like it.

I also received some Twitter reactions pointing to this great Inspirational TextBox styles for Windows Phone & Store blogpost from Deani Hansen. That solution uses Styling and subclassing the TextBox control. As always there are many solutions for the same problem.

Fons

XAML Animated Headered TextBox Style

0 Comments
By Fons Sonnemans, 28-2-2017

A while ago I saw a beautiful effect in an Android app which I was using. It had textboxes with a placeholder text. This placeholder text moved to the header when you enter the first character in the textbox. This triggered me to do the same in a Windows 10 XAML app (UWP). This is a video of the result.

AnimatedHeaderedTextBoxStyle demo video

AnimatedHeaderedTextBoxStyle

My solution is quite simple. I created a Style for a TextBox which has an extra StateGroup named 'HeaderStates'. There are two States in this group named Empty and NotEmpty. The HeaderContentPresenter is moved using TranslateX and TranslateY setters to the correct position. The states are triggered using TemplatedParent databinding to the Text property. I have used a converter which returns true or false when the text is empty or not. I have also changed the BorderThickness property of the Style. It now has only a bottom line and is not boxed any more.

<Style x:Key="AnimatedHeaderedTextBoxStyle"
        TargetType="TextBox">
    <Setter Property="MinWidth"
            Value="{ThemeResource TextControlThemeMinWidth}" />
    <Setter Property="MinHeight"
            Value="{ThemeResource TextControlThemeMinHeight}" />
    <Setter Property="Foreground"
            Value="{ThemeResource TextControlForeground}" />
    <Setter Property="Background"
            Value="{ThemeResource TextControlBackground}" />
    <Setter Property="BorderBrush"
            Value="{ThemeResource TextControlBorderBrush}" />
    <Setter Property="SelectionHighlightColor"
            Value="{ThemeResource TextControlSelectionHighlightColor}" />
    <Setter Property="BorderThickness"
            Value="0,0,0,2" />
    <Setter Property="FontFamily"
            Value="{ThemeResource ContentControlThemeFontFamily}" />
    <Setter Property="FontSize"
            Value="{ThemeResource ControlContentThemeFontSize}" />
    <Setter Property="ScrollViewer.HorizontalScrollMode"
            Value="Auto" />
    <Setter Property="ScrollViewer.VerticalScrollMode"
            Value="Auto" />
    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility"
            Value="Hidden" />
    <Setter Property="ScrollViewer.VerticalScrollBarVisibility"
            Value="Hidden" />
    <Setter Property="ScrollViewer.IsDeferredScrollingEnabled"
            Value="False" />
    <Setter Property="Padding"
            Value="{ThemeResource TextControlThemePadding}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="TextBox">
                <Grid>
                    <Grid.Resources>
                        <Style x:Name="DeleteButtonStyle"
                                TargetType="Button">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="Button">
                                        <Grid x:Name="ButtonLayoutGrid"
                                                BorderBrush="{ThemeResource TextControlButtonBorderBrush}"
                                                BorderThickness="{TemplateBinding BorderThickness}"
                                                Background="{ThemeResource TextControlButtonBackground}">
                                            <VisualStateManager.VisualStateGroups>
                                                <VisualStateGroup x:Name="CommonStates">
                                                    <VisualState x:Name="Normal" />
                                                    <VisualState x:Name="PointerOver">
                                                        <Storyboard>
                                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background"
                                                                                            Storyboard.TargetName="ButtonLayoutGrid">
                                                                <DiscreteObjectKeyFrame KeyTime="0"
                                                                                        Value="{ThemeResource TextControlButtonBackgroundPointerOver}" />
                                                            </ObjectAnimationUsingKeyFrames>
                                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush"
                                                                                            Storyboard.TargetName="ButtonLayoutGrid">
                                                                <DiscreteObjectKeyFrame KeyTime="0"
                                                                                        Value="{ThemeResource TextControlButtonBorderBrushPointerOver}" />
                                                            </ObjectAnimationUsingKeyFrames>
                                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground"
                                                                                            Storyboard.TargetName="GlyphElement">
                                                                <DiscreteObjectKeyFrame KeyTime="0"
                                                                                        Value="{ThemeResource TextControlButtonForegroundPointerOver}" />
                                                            </ObjectAnimationUsingKeyFrames>
                                                        </Storyboard>
                                                    </VisualState>
                                                    <VisualState x:Name="Pressed">
                                                        <Storyboard>
                                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background"
                                                                                            Storyboard.TargetName="ButtonLayoutGrid">
                                                                <DiscreteObjectKeyFrame KeyTime="0"
                                                                                        Value="{ThemeResource TextControlButtonBackgroundPressed}" />
                                                            </ObjectAnimationUsingKeyFrames>
                                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush"
                                                                                            Storyboard.TargetName="ButtonLayoutGrid">
                                                                <DiscreteObjectKeyFrame KeyTime="0"
                                                                                        Value="{ThemeResource TextControlButtonBorderBrushPressed}" />
                                                            </ObjectAnimationUsingKeyFrames>
                                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground"
                                                                                            Storyboard.TargetName="GlyphElement">
                                                                <DiscreteObjectKeyFrame KeyTime="0"
                                                                                        Value="{ThemeResource TextControlButtonForegroundPressed}" />
                                                            </ObjectAnimationUsingKeyFrames>
                                                        </Storyboard>
                                                    </VisualState>
                                                    <VisualState x:Name="Disabled">
                                                        <Storyboard>
                                                            <DoubleAnimation Duration="0"
                                                                                To="0"
                                                                                Storyboard.TargetProperty="Opacity"
                                                                                Storyboard.TargetName="ButtonLayoutGrid" />
                                                        </Storyboard>
                                                    </VisualState>
                                                </VisualStateGroup>
                                            </VisualStateManager.VisualStateGroups>
                                            <TextBlock x:Name="GlyphElement"
                                                        AutomationProperties.AccessibilityView="Raw"
                                                        Foreground="{ThemeResource TextControlButtonForeground}"
                                                        FontStyle="Normal"
                                                        FontSize="12"
                                                        FontFamily="{ThemeResource SymbolThemeFontFamily}"
                                                        HorizontalAlignment="Center"
                                                        Text="&#xE10A;"
                                                        VerticalAlignment="Center" />
                                        </Grid>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </Grid.Resources>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="Auto" />
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Disabled">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground"
                                                                    Storyboard.TargetName="HeaderContentPresenter">
                                        <DiscreteObjectKeyFrame KeyTime="0"
                                                                Value="{ThemeResource TextControlHeaderForegroundDisabled}" />
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background"
                                                                    Storyboard.TargetName="BorderElement">
                                        <DiscreteObjectKeyFrame KeyTime="0"
                                                                Value="{ThemeResource TextControlBackgroundDisabled}" />
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush"
                                                                    Storyboard.TargetName="BorderElement">
                                        <DiscreteObjectKeyFrame KeyTime="0"
                                                                Value="{ThemeResource TextControlBorderBrushDisabled}" />
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground"
                                                                    Storyboard.TargetName="ContentElement">
                                        <DiscreteObjectKeyFrame KeyTime="0"
                                                                Value="{ThemeResource TextControlForegroundDisabled}" />
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground"
                                                                    Storyboard.TargetName="PlaceholderTextContentPresenter">
                                        <DiscreteObjectKeyFrame KeyTime="0"
                                                                Value="{ThemeResource TextControlPlaceholderForegroundDisabled}" />
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Normal" />
                            <VisualState x:Name="PointerOver">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush"
                                                                    Storyboard.TargetName="BorderElement">
                                        <DiscreteObjectKeyFrame KeyTime="0"
                                                                Value="{ThemeResource TextControlBorderBrushPointerOver}" />
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background"
                                                                    Storyboard.TargetName="BorderElement">
                                        <DiscreteObjectKeyFrame KeyTime="0"
                                                                Value="{ThemeResource TextControlBackgroundPointerOver}" />
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground"
                                                                    Storyboard.TargetName="PlaceholderTextContentPresenter">
                                        <DiscreteObjectKeyFrame KeyTime="0"
                                                                Value="{ThemeResource TextControlPlaceholderForegroundPointerOver}" />
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground"
                                                                    Storyboard.TargetName="ContentElement">
                                        <DiscreteObjectKeyFrame KeyTime="0"
                                                                Value="{ThemeResource TextControlForegroundPointerOver}" />
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Focused">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground"
                                                                    Storyboard.TargetName="PlaceholderTextContentPresenter">
                                        <DiscreteObjectKeyFrame KeyTime="0"
                                                                Value="{ThemeResource TextControlPlaceholderForegroundFocused}" />
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background"
                                                                    Storyboard.TargetName="BorderElement">
                                        <DiscreteObjectKeyFrame KeyTime="0"
                                                                Value="{ThemeResource TextControlBackgroundFocused}" />
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush"
                                                                    Storyboard.TargetName="BorderElement">
                                        <DiscreteObjectKeyFrame KeyTime="0"
                                                                Value="{ThemeResource TextControlBorderBrushFocused}" />
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground"
                                                                    Storyboard.TargetName="ContentElement">
                                        <DiscreteObjectKeyFrame KeyTime="0"
                                                                Value="{ThemeResource TextControlForegroundFocused}" />
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="RequestedTheme"
                                                                    Storyboard.TargetName="ContentElement">
                                        <DiscreteObjectKeyFrame KeyTime="0"
                                                                Value="Light" />
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                        <VisualStateGroup x:Name="ButtonStates">
                            <VisualState x:Name="ButtonVisible">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility"
                                                                    Storyboard.TargetName="DeleteButton">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <Visibility>Visible</Visibility>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="ButtonCollapsed" />
                        </VisualStateGroup>
                        <VisualStateGroup x:Name="HeaderStates">
                            <VisualStateGroup.Transitions>
                                <VisualTransition GeneratedDuration="0:0:0.35">
                                    <VisualTransition.GeneratedEasingFunction>
                                        <CircleEase EasingMode="EaseInOut" />
                                    </VisualTransition.GeneratedEasingFunction>
                                </VisualTransition>
                            </VisualStateGroup.Transitions>
                            <VisualState x:Name="NotEmpty">
                                <VisualState.Setters>
                                    <Setter Target="HeaderContentPresenter.(UIElement.RenderTransform).(CompositeTransform.TranslateY)"
                                            Value="0" />
                                    <Setter Target="HeaderContentPresenter.(UIElement.RenderTransform).(CompositeTransform.TranslateX)"
                                            Value="0" />
                                </VisualState.Setters>
                                <VisualState.StateTriggers>
                                    <StateTrigger IsActive="{Binding Text, Converter={StaticResource IsNotEmptyConverter}, Mode=OneWay, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
                                </VisualState.StateTriggers>
                            </VisualState>
                            <VisualState x:Name="Empty">
                                <VisualState.Setters>
                                    <Setter Target="HeaderContentPresenter.(UIElement.RenderTransform).(CompositeTransform.TranslateY)"
                                            Value="31" />
                                    <Setter Target="HeaderContentPresenter.(UIElement.RenderTransform).(CompositeTransform.TranslateX)"
                                            Value="11" />
                                </VisualState.Setters>
                                <VisualState.StateTriggers>
                                    <StateTrigger IsActive="{Binding Text, Converter={StaticResource IsEmptyConverter}, Mode=OneWay, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
                                </VisualState.StateTriggers>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Border x:Name="BorderElement"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Background="{TemplateBinding Background}"
                            Grid.ColumnSpan="2"
                            Grid.Row="1"
                            Grid.RowSpan="1" />
                    <ContentPresenter x:Name="HeaderContentPresenter"
                                        Grid.ColumnSpan="2"
                                        ContentTemplate="{TemplateBinding HeaderTemplate}"
                                        Content="{TemplateBinding Header}"
                                        Foreground="{ThemeResource TextControlHeaderForeground}"
                                        FontWeight="Normal"
                                        Margin="0,0,0,8"
                                        Grid.Row="0"
                                        Visibility="Collapsed"
                                        x:DeferLoadStrategy="Lazy"
                                        RenderTransformOrigin="0.5,0.5">
                        <ContentPresenter.RenderTransform>
                            <CompositeTransform />
                        </ContentPresenter.RenderTransform>
                    </ContentPresenter>
                    <ScrollViewer x:Name="ContentElement"
                                    AutomationProperties.AccessibilityView="Raw"
                                    HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
                                    HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
                                    IsTabStop="False"
                                    IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
                                    IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
                                    IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
                                    Margin="{TemplateBinding BorderThickness}"
                                    Padding="{TemplateBinding Padding}"
                                    Grid.Row="1"
                                    VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
                                    VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
                                    ZoomMode="Disabled" />
                    <ContentControl x:Name="PlaceholderTextContentPresenter"
                                    Grid.ColumnSpan="2"
                                    Content="{TemplateBinding PlaceholderText}"
                                    Foreground="{ThemeResource TextControlPlaceholderForeground}"
                                    IsHitTestVisible="False"
                                    IsTabStop="False"
                                    Margin="{TemplateBinding BorderThickness}"
                                    Padding="{TemplateBinding Padding}"
                                    Grid.Row="1" />
                    <Button x:Name="DeleteButton"
                            AutomationProperties.AccessibilityView="Raw"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Grid.Column="1"
                            FontSize="{TemplateBinding FontSize}"
                            IsTabStop="False"
                            Margin="{ThemeResource HelperButtonThemePadding}"
                            MinWidth="34"
                            Grid.Row="1"
                            Style="{StaticResource DeleteButtonStyle}"
                            Visibility="Collapsed"
                            VerticalAlignment="Stretch" />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

The converter is very simple. It has an extra IsInvertered property to invert a True to a False.

public class EmptyStringToTrueConverter : IValueConverter {
    public bool IsInverted { get; set; }

    public object Convert(object value, Type targetType, object parameter, string language) {
        var txt = (string)value;
        return string.IsNullOrEmpty(txt) ^ IsInverted;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language) {
        return DependencyProperty.UnsetValue;
    }
}

The converteres are registered using the following XAML.

<local:EmptyStringToTrueConverter x:Key="IsNotEmptyConverter" IsInverted="True" />
<local:EmptyStringToTrueConverter x:Key="IsEmptyConverter" />

Usage

My example page which I used in the video is shown below. All TextBoxes have the Style property set to AnimatedHeaderedTextBoxStyle and off course a Header property. I have set the IsSpellCheckEnable property to False because I don't want spellchecking on names and email addresses.  

<Page x:Class="App121.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="using:App121"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel Width="300"
                    Margin="0,12"
                    VerticalAlignment="Top"
                    HorizontalAlignment="Center">

            <TextBox Header="Firstname"
                     Style="{StaticResource AnimatedHeaderedTextBoxStyle}"
                     IsSpellCheckEnabled="False"
                     InputScope="PersonalFullName"/>

            <TextBox Header="Lastname"
                     Style="{StaticResource AnimatedHeaderedTextBoxStyle}"
                     IsSpellCheckEnabled="False"
                     Margin="0,8"
                     InputScope="PersonalFullName" />

            <TextBox Header="E-mail"
                     Style="{StaticResource AnimatedHeaderedTextBoxStyle}"
                     IsSpellCheckEnabled="False"
                     InputScope="EmailNameOrAddress" />

            <Button Content="Next"
                    Margin="0,16,0,0" />
        </StackPanel>

    </Grid>
</Page>

I have placed the AnimatedHeaderedTextBoxStyle, the registration of the converters and a DeleteButtonStyle into ResourceDictionary named AnimatedHeaderedTextBoxStyle.xaml. The DeleteButtonStyle was generated by Blend when I created the Style by 'Editing a Copy...' of the Template for an existing TextBox.

Edit a Copy

In have registered the ResourceDictionary from the App.xaml which makes it available for in all pages and controls in this application.

<Application
    x:Class="App121.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App121"
    RequestedTheme="Light">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="AnimatedHeaderedTextBoxStyle.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

The easiest way to add this Resource Dictionary as a MergedDictionaries in the App.xaml is to use Blend. Open the Resources Window and right click the App.xaml file. Then select 'Link to Resource Dictionary' and check the AnimatedHeaderedTextBoxStyle.xaml file.

Link to ResourceDictionary

The code

I have published my code on GitHub. I hope you like it.

Fons

All postings/content on this blog are provided "AS IS" with no warranties, and confer no rights. All entries in this blog are my opinion and don't necessarily reflect the opinion of my employer or sponsors. The content on this site is licensed under a Creative Commons Attribution By license.