tags:

views:

716

answers:

2

I have a listbox that in which every item is represented using a textbox. The thing is that I want to be able to tab between all the items in the listbox before moving to the next element in the xaml window.

The current (and normal WPF behavior) is that when I tab into the listbox, the first element is highlighted, if I tab again, then the focus moves into the textbox inside that item. If I tab once again, focus moves to the next element in the window (without going through any of the other items in the ListBox).

The behavior I want is the following: When I tab into the listbox, the first textbox obtains focus automatically (without highlighting the whole Item)*. If I tab again then the next textbox in the listbox gets focus. When I tab at the last textbox in the listbox, then focus moves to the next control.

*I already how to do this, I'm only posting it here in order to explain the complete process.

I've been looking for the solution and I've been unable to find something.

+1  A: 

EDIT

After the comment, to be specific:

private void ListBox_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Tab)
    {
        ListBox lb = sender as ListBox;

        if(lb == null) return;

        if(lb.SelectedIndex < lb.Items.Count - 1)
        {
            GiveItemFocus(lb, lb.SelectedIndex + 1, typeof(TextBox));
            e.Handled = true;
        }
    }
}

private void GiveItemFocus(ListBox lb, int index, Type descentdantType)
{
    if(lb.Items.Count >= index || index < 0)
    {
        throw new ArgumentException();
    }

    ListBoxItem lbi = (ListBoxItem) lb.ItemContainerGenerator.ContainerFromIndex(index);

    lb.UnselectAll();

    lbi.IsSelected = true;

    UIElement descendant = (UIElement) FindVisualDescendant(lbi, o => o.GetType() == descentdantType);

    descendant.Focus();
}

private static DependencyObject FindVisualDescendant(DependencyObject dependencyObject, Predicate<bool> condition)
{
    //implementation not provided, commonly used utility
}

Setting e.Handled to true will ensure only your handler is processed on a tab press, and the default behaviour will not be activated.

kek444
The problem is, how do I move focus between items in a list. If I use the MoveFocus method that UIElement class defines, then focus is moved to the next element in the window, not the next item in the listbox. My question is how can I programmatically move the focus between item elements, not how can I trigger that movement
Kiranu
Edited the answer to provide a more complete answer.
kek444
I have only one further problem. Now it goes perfectly except that if I tab into the listbox again, then the first item to receive focus is the last item in the listbox. Im trying to work in a solution, but could you help me again?
Kiranu
It is probably because the selected item remains the last one. You should add an OnGotFocus method which selects the first item, and reuse the GiveItemFocus method there.
kek444
A: 

This can be done in xaml, by setting the following two properties.

    <Style TargetType="ListView" >
        <Setter Property="KeyboardNavigation.TabNavigation" Value="Continue" />
    </Style>

    <Style TargetType="ListViewItem">
        <Setter Property="IsTabStop" Value="False" />
    </Style>

For full explanation see Derek Wilson's Blog post. http://www.worldolio.com/derek/wordpress/?p=109

James