Tag Archives: behavior

User-Friendly Input Pages

When it comes to data entry pages on mobile devices the key is to make it as simple as possible for the user. These kind of devices are all about the user experience and while I think we can all agree that data entry is far from sexy, it’s unavoidable. I was recently working on the login screen for an app (which will remain secret for now, but I’ll reveal all when it’s published) and realized as I was creating it that that were two common things that I wanted to do in this scenario:

  1. “Tab” from one input field to the next by pressing the Enter key.
  2. Submit the form contents when I got to the last field.

Submit Buttons

When you are implementing a data entry form of some kind, even if it’s as simple as a login page, you should always make sure that the user can see the submit button. When the SIP is displayed (in any orientation) a lot of the page is obscured, making it hard for your user to find a button on the page. As well as ensuring that the content is contained within a ScrollViewer to enable users to scroll around your content, you should put the submit button in the application bar so that the user can easily tap it, even when the SIP is displayed.

Item 1 enables the user to move from one input field to the next without having to manually tap on the input controls, which can get really annoying for the user, especially when the SIP is displayed. Item 2 is definitely a “nice-to-have” because if the data entry page is designed properly, there’s a submit button on the application bar, which the user can tap without having to dismiss the SIP. However, if the user is already used to pressing the Enter key to “tab” between fields, it just makes their life easier if the final Enter key press actually does a submit.

I’ve seen solutions for this already, which I’ve used in the past, specifically the KeyboardTabHelperBehavior by @pauliom, but it wasn’t quite what I wanted.

“Tabbing” Between Fields

So, I set about creating my own behavior and tackled the issue of the “tabbing” aspect first. The key here is to handle the Enter key press, and then find another TextBox or PasswordBox control to set focus to.

The scaffolding of the behavior looks like this:

public class EnterKeyHandler : Behavior<Control>
{
    protected override void OnAttached()
    {
        base.OnAttached();

        if (null != this.AssociatedObject)
        {
            this.AssociatedObject.KeyDown += this.Control_KeyDown;
        }
    }

    /// <summary>
    /// Called when the behavior is being detached from its AssociatedObject, but before it has actually occurred.
    /// </summary>
    /// <remarks>Override this to unhook functionality from the AssociatedObject.</remarks>
    protected override void OnDetaching()
    {
        base.OnDetaching();

        if (null != this.AssociatedObject)
        {
            this.AssociatedObject.KeyDown -= this.Control_KeyDown;
        }
    }

    private void Control_KeyDown(object sender, KeyEventArgs args)
    {
        if ((Key.Enter == args.Key) ||
            (0x0A == args.PlatformKeyCode))
        {
            this.FocusNextTextOrPasswordBox();
        }
    }
}

PlatformKeyCode

Handling the value 0x0A for the args.PlatformKeyCode adds support for the Enter key on the host keyboard when running in the emulator.

The work horse for the first part of the behavior is the FocusNextTextOrPasswordBox method, which uses the LinqToVisualTree helper by @ColinEberhardt to find the next TextBox or PasswordBox after the AssociatedObject. If it doesn’t find one, it finds the first TextBox or PasswordBox before itself, i.e. it loops round to the start again. If it finds either a TextBox or PasswordBox, it sets focus to it, which ensures that the SIP remains visible and any changes to InputScope will be taken into account. The method looks like this:

    private void FocusNextTextOrPasswordBox()
    {
        // Find the next TextBox or PasswordBox.
        var target = this.AssociatedObject
            .ElementsAfterSelf()
            .Where((d) => d is TextBox || d is PasswordBox)
            .FirstOrDefault() as Control;
        if (null == target)
        {
            // Nothing after this one, so try predecessors so that we loop round.
            target = this.AssociatedObject
                .ElementsBeforeSelf()
                .Where((d) => d is TextBox || d is PasswordBox)
                .FirstOrDefault() as Control;
        }

        if (null != target)
        {
            target.Focus();
        }
    }

Executing a Command

The next stage is to execute my submit command when I get to the end of the input, so I needed an enumeration to identify the different modes of operation and a dependency property to expose it. I called these EnterKeyAction and EnterKeyActionProperty respectively.

The Control_KeyDown method shown above becomes the following:

    private void Control_KeyDown(object sender, KeyEventArgs args)
    {
        if ((Key.Enter == args.Key) ||
            (0x0A == args.PlatformKeyCode))
        {
            if (this.EnterKeyAction == EnterKeyAction.MoveNext)
            {
                this.FocusNextTextOrPasswordBox();
            }
            else
            {
                this.ExecuteAssociatedCommand();
            }
        }
    }

The next thing I needed to do was to enable the developer to specify the command that the behavior should execute. My first attempt was to simply expose an ICommand dependency property to enable binding to the view model, but unfortunately that didn’t work, presumably because the behavior doesn’t have the concept of a data context meaning that there’s nothing for it to bind to. So, I dug out my ninja reflection skills and changed to a CommandStringProperty that is used to find the command to execute, which is where the ExecuteAssociatedCommand method comes in:

    private void ExecuteAssociatedCommand()
    {
        // Locate the named command in the associated objects data context, and then
        // execute that command.
        var commandName = this.CommandString;
        if (!string.IsNullOrEmpty(commandName))
        {
            var context = this.AssociatedObject.DataContext;
            if (null != context)
            {
                var info = (from p in context.GetType().GetProperties()
                            where
                                p.CanRead &&
                                p.Name == commandName &&
                                typeof(ICommand).IsAssignableFrom(p.PropertyType)
                            select p).SingleOrDefault();
                if (null != info)
                {
                    var command = info.GetGetMethod().Invoke(context, new object[0])
                        as ICommand;
                    if (null != command)
                    {
                        command.Execute(null);
                    }
                }
            }
        }
    }

This method finds the data context of the AssociatedObject on the assumption that it’s set to the view model, and then uses reflection to find the properties that have read access, whose name matches the specified CommandString, and that implement the ICommand interface. If it finds a match, it gets the value of the property, and then executes it. Job done!

Because the key scenario here is simple form submission, I’m not expecting there to be any command parameter, and in the absence of a working binding solution, I figured that was two good reasons not to expose it.

EnterKeyHandler in Action

You’ll need to add a reference to the System.Windows.Interactivity.dll assembly from the Expression Blend SDK and include the source code in your project, which you can download from the Windows Phone 7 from the Trenches repository at BitBucket. The EnterKeyHandler behavior is in the Behaviors folder, and the LinqToVisualTree class is in the Extensions folder. Then it’s all about the XAML:

<StackPanel x:Name="LayoutRoot" Background="Transparent">
    <TextBlock Style="{StaticResource PhoneTextSubtleStyle}"
               Text="user name or email address" />
    <TextBox Text="{Binding EmailAddress, Mode=TwoWay}">
        <int:Interaction.Behaviors>
            <b:EnterKeyHandler />
        </int:Interaction.Behaviors>
    </TextBox>
    <TextBlock Style="{StaticResource PhoneTextSubtleStyle}"
               Text="password" />
    <PasswordBox Password="{Binding Password, Mode=TwoWay}">
        <int:Interaction.Behaviors>
            <b:EnterKeyHandler EnterKeyAction="ExecuteCommand"
                               CommandString="SignInCommand" />
        </int:Interaction.Behaviors>
    </PasswordBox>
</StackPanel>


This XAML has a simple TextBox for the user name and a PasswordBox for the password. The first uses the default behavior of moving to the next input field, and the second uses the ExecuteCommand action to execute the SignInCommand. The data context for the UI is my view model, which exposes the SignInCommand property. I also have an application bar button that is hooked up to the same command.