0

We're trying to programmatically mimic the way the 'Up' and 'Down' arrow keys navigate around a TreeView from code-behind. (Note: Not simply selecting items, but mimicking arrow-key navigation.)

Specifically, our use-case is one of our TreeView's HierarchicalDataTemplates has a TextBox in it, which of course steals all keyboard activity when focused. But since this is a single-line TextBox, we want to basically have it ignore the 'Up' and 'Down' keys and instead pass them to the underlying TreeView to be processed there.

To do this, we subclassed the TextBox and are intercepting the 'Up' and 'Down' keys in the OnPreviewKeyDown override as follows...

protected override void OnPreviewKeyDown(System.Windows.Input.KeyEventArgs e)
{
    switch(e.Key)
    {
        case Key.Up:
        case Key.Down:

            // Swallow the key
            e.Handled = true;

            // Get the navigation direction
            var direction = (e.Key == Key.Up)
                ? FocusNavigationDirection.Up
                : FocusNavigationDirection.Down;

            // Perform the navigation
            MoveFocus(new TraversalRequest(direction));

            break;

        default:
            base.OnPreviewKeyDown(e);
            break;

    }
}

This technique works great when the TextBox is in a ListBox's DataTemplate, but does not work if it's in a TreeView's HierarchicalDataTemplate.

Again, don't confuse this with simply selecting items. We already know how to programmatically do that by binding a TreeViewItem's IsSelected property to our ViewModel or manually walking the visual tree to get to the TreeViewItem we want. I'm specifically asking about navigating around the TreeView, duplicating what the 'Up' and 'Down' keys do.

For instance, if an earlier sibling has its children expanded and you press up, it goes to the last child of that sibling (or its child's children if it is expanded, etc.) If the earlier siblings children are collapsed, then it goes directly to that sibling. There's additional rules if they are visible or enabled, etc.

We have also tried explicitly setting the focus to the TreeViewItem directly and performing MoveFocus on that, but that didn't work either. Even tried calling that logic via a dispatcher to make sure the focus had actually changed. Again, nothing.

We also tried playing with KeyboardNavigation.DirectionalNavigation, both on the TreeView itself as well as against a TreeViewItem but still, nothing.

Even if we have to do a SendKeys-type of thing, that would be helpful.

4

2 回答 2

1

One of the possible way is to use TreeListBox implementation of Avalon Control Library, or similar to this (your own, for example). As you mentioned, you can apply your technique for ListBox, so I think it would be easy for you to apply it to TreeListBox, which is derived directly from ListBox.

于 2012-05-10T05:03:22.990 回答
1

The WPF UI Automation framework probably has a way to do it. But if that doesn't pan out, this project coded something to do it:

http://wpfsendkeys.codeplex.com/

于 2012-05-10T16:31:03.467 回答