Dash Animation

| 2 comments

I seldom use WPF's animation capabilities, mostly because I believe the overuse of animations doesn't do any good to user experience, but animtions can be cool if you do it and use it appropriately, this bit of XAML snippet shown below just comes into my imagination, it doesn't serve any practical purpose, but is fun to play with:

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         
Title="Dash Animation">
    <
Viewbox Margin="30">
        <
Rectangle
           Name="ellipse"
           Width="600"
           Height="600"
           Fill="Green"
           Stroke="Red"
           StrokeThickness="120"
           StrokeDashArray="0,2"
           StrokeDashOffset="0"
           StrokeDashCap="Round">
            <
Rectangle.Triggers>
                <
EventTrigger RoutedEvent="FrameworkElement.Loaded">
                    <
BeginStoryboard>
                        <
Storyboard>
                            <
DoubleAnimation
                               To="20"
                               Duration="0:0:5"
                               RepeatBehavior="Forever"
                               By="2"
                               Storyboard.TargetProperty="StrokeDashOffset" />
                        </
Storyboard>
                    </
BeginStoryboard>
                </
EventTrigger>
            </
Rectangle.Triggers>
        </
Rectangle>
    </
Viewbox>
</
Page>

Focus Navigation Using Enter Key

| 0 comments

Moving focus between UI elements using Enter key is probably one of the controversial features of user interaction design, personally I think it has its own usage, and is a great complement to tab navigation, here is the two techniques of implementing enter navigation I learnt from WPF MSDN forum, both of the two methods need you to first hook up to interesting controls' KeyDown event, imagine you have such piece of XAML:

<Window x:Class="EnterNavigationDemo.Window1"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Title="Login" Width="300" Height="200" ResizeMode="NoResize"
    >
  <
Window.Resources>
    <
Style TargetType="{x:Type Button}">
      <
Setter Property="Width" Value="60"/>
      <
Setter Property="Margin" Value="4"/>
    </
Style>
    <
Style TargetType="{x:Type TextBox}">
      <
Setter Property="Width" Value="160"/>
      <
Setter Property="Margin" Value="4"/>
    </
Style>
    <
Style TargetType="{x:Type PasswordBox}">
      <
Setter Property="Width" Value="160"/>
      <
Setter Property="Margin" Value="4"/>
    </
Style>
    <
Style TargetType="{x:Type Label}">
      <
Setter Property="Margin" Value="4"/>
    </
Style>
  </
Window.Resources>
  <
Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Name="documentRoot">
    <
Grid.RowDefinitions>
      <
RowDefinition/>
      <
RowDefinition/>
      <
RowDefinition/>
      <
RowDefinition/>
      <
RowDefinition/>
    </
Grid.RowDefinitions>
    <
Label Target="{Binding ElementName=txtDomainName}" Content="_Domain:" Grid.Column="0" Grid.Row="0"/>
    <
TextBox Name="txtDomainName" Grid.Column="1" Grid.Row="0"/>
    <
Label Target="{Binding ElementName=txtUserName}" Content="_User:" Grid.Column="0" Grid.Row="1"/>
    <
TextBox Name="txtUser" Grid.Column="1" Grid.Row="1"/>
    <
Label Target="{Binding ElementName=txtPasswrod}" Content="_Passwrod:" Grid.Column="0" Grid.Row="2"/>
    <
PasswordBox Name="txtPasswrod" Grid.Column="1" Grid.Row="2"/>
    <
StackPanel Grid.Row="3" Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Center">
      <
Button Content="_Login" Name="loginButton" IsDefault="True"/>
      <
Button Content="_Cancel" Name="cancelButton" IsCancel="True"/>
    </
StackPanel>
  </
Grid>
</
Window>

In the code behind file, you can achieve enter navigation using the following methods:

public partial class Window1 : System.Windows.Window
{
    public Window1()
    {
        InitializeComponent();
        this.documentRoot.AddHandler(TextBox.KeyDownEvent, new KeyEventHandler(documentRoot_KeyDown));
        this.loginButton.Click += new RoutedEventHandler(loginButton_Click);
        this.cancelButton.Click += new RoutedEventHandler(cancelButton_Click);
    }

    private void cancelButton_Click(Object sender, RoutedEventArgs e)
    {
        MessageBox.Show("Cancel button is clicked");
    }

    private void loginButton_Click(Object sender, RoutedEventArgs e)
    {
        MessageBox.Show("Login button is clicked");
    }

    private void documentRoot_KeyDown(Object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Return)
        {
            UIElement focusedElement = Keyboard.FocusedElement as UIElement;
            if (focusedElement != null)
            {
                focusedElement.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
            }
            e.Handled = true;
        }
    }

}

you can also achieve this by modifying the key down event handler to add the following code:

private void documentRoot_KeyDown(Object sender, KeyEventArgs e)
{
    if (e.Key == Key.Return)
    {
        e.Handled = true;
        KeyEventArgs args = new KeyEventArgs(Keyboard.PrimaryDevice, Keyboard.PrimaryDevice.ActiveSource, 0, Key.Tab);
        args.RoutedEvent = Keyboard.KeyDownEvent;
        InputManager.Current.ProcessInput(args);
    }
}

You can see that I add two buttons on the window, my initial thought is that I want enter navigate between the three TextBoxes, but I still want to tab navigate to the buttons, and the above code finally ends up working in the way I desire.