views:

352

answers:

1

I've got a WPF view with two textboxes. I'd like to automatically move focus forward from the first textbox to the second when the user hits the down arrow on the keyboard exactly like Tab does.

It seems like I ought to be able to do this 100% declaratively, but for some reason the commands I thought would do this don't seem to do anything. Here is my first attempt that doesn't work:

<StackPanel>
    <TextBox Text="Test">
        <TextBox.InputBindings>
            <!-- I realize ComponentCommands.MoveFocusDown doesn't work...
                 This is just an example of what I've tried and the type
                 of answer I'm looking for -->
            <KeyBinding Key="Down" Command="ComponentCommands.MoveFocusDown" />
        </TextBox.InputBindings>
    </TextBox>
    <TextBox></TextBox>
</StackPanel>

Does anyone have any experience with this? Seems like I ought to be able to use either InputBindings or an EventTrigger to do this.

I'm using MVVM and this is a View concern. I could just drop in a little codebehind (being a view concern, this is reasonable), but it just feels like I'm missing something.

+4  A: 

I hope someone comes up with something more elegant that this, but this is what I have so far. It is not 100% XAML, but it is at least generic.

This example shows a window with two buttons and two text boxes. The down arrow cycles the focus between them.

I hope this helps.

<Window x:Class="WPF_Playground.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300"
    >
    <Window.CommandBindings>
        <CommandBinding Command="ComponentCommands.MoveFocusDown" Executed="CommandBinding_Executed"/>
    </Window.CommandBindings>
    <StackPanel KeyboardNavigation.DirectionalNavigation="Cycle">
        <Button>Tester</Button>
        <Button>Tester2</Button>
        <TextBox Text="Test">
            <TextBox.InputBindings>
                <KeyBinding Command="ComponentCommands.MoveFocusDown" Gesture="DOWN" />
            </TextBox.InputBindings>
        </TextBox>
        <TextBox Text="Test2">
            <TextBox.InputBindings>
                <KeyBinding Command="ComponentCommands.MoveFocusDown" Gesture="DOWN" />
            </TextBox.InputBindings>
        </TextBox>
    </StackPanel>
</Window>

The event handler (no error handling at all):

private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
    UIElement senderElement = sender as UIElement;
    UIElement focusedElement = FocusManager.GetFocusedElement(senderElement) as UIElement;
    bool result = focusedElement.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
    Debug.WriteLine(result);
}
Jerry Bullard
+1 Simply WOw! Gesture is something new for me
Trickster