Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to TAB through a ListView with TextBoxes as TreeViewItems?

So i basically have this ListView and i would like to press Tab and iterate through my TreeViewItems (preferrably only my TextBoxes)

<ListView>
    <ListView.View>
        <GridView>
            <GridViewColumn  Header="number"  />
            <GridViewColumn Header="Selector">
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <TextBox Text="{Binding SelectorName}"/>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
        </GridView>
    </ListView.View>
</ListView>

The scenario that i am seeing is after pressing the tab for the first time the whole first TreeViewItem is selected and pressing Tab again the first TextBox is selected .Finally the third TAB gets out of the TreeView to the next Control although there are more TextBoxes that i would like to catch before "tabing" to to the next Control. Thankx

Edit : The Question was answered here : How to TAB through TextBoxes in a ListView

like image 243
M.C. Avatar asked Aug 11 '11 01:08

M.C.


2 Answers

Have a look at the KeyboardNavigation.TabNavigation Attached Property

like image 57
LPL Avatar answered Nov 18 '22 01:11

LPL


Maybe i am missing something but i cannot find any simple method to do this, here would be an outline of what you could do:

<ListView.InputBindings>
    <KeyBinding Key="Tab" Command="{Binding GoToNextItem}"
            CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ListView}}" />
    <KeyBinding Modifiers="Shift" Key="Tab" Command="{Binding GoToPreviousItem}"
            CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ListView}}" />
</ListView.InputBindings>
<ListView.ItemContainerStyle>
    <Style TargetType="{x:Type ListViewItem}">
        <EventSetter Event="Selected" Handler="ItemSelected" />
    </Style>
</ListView.ItemContainerStyle>
<ListView.View>
    <GridView>
        <GridViewColumn  Header="number"  />
        <GridViewColumn Header="Selector">
            <GridViewColumn.CellTemplate>
                <DataTemplate>
                    <TextBox Name="_tb" Text="{Binding SelectorName}"/>
                </DataTemplate>
            </GridViewColumn.CellTemplate>
        </GridViewColumn>
    </GridView>
</ListView.View>

Things i did here:

  • Override tab behavior to fire commands to select another item
  • Add event handler to selected event to focus the TextBox
  • Name TextBox so it can be found and focused

Code:

private readonly ICommand _GoToNextItem = new Command((p) =>
    {
        var lv = p as ListView;
        if (lv.SelectedIndex == -1 || lv.SelectedIndex == lv.Items.Count - 1)
        {
            lv.SelectedIndex = 0;
        }
        else
        {
            lv.SelectedIndex++;
        }
    });
public ICommand GoToNextItem { get { return _GoToNextItem; } }

private readonly ICommand _GoToPreviousItem = new Command((p) =>
{
    var lv = p as ListView;
    if (lv.SelectedIndex <= 0)
    {
        lv.SelectedIndex = lv.Items.Count - 1;
    }
    else
    {
        lv.SelectedIndex--;
    }
});
public ICommand GoToPreviousItem { get { return _GoToPreviousItem; } }
private void ItemSelected(object sender, RoutedEventArgs e)
{
    var item = sender as ListBoxItem;
    (FindNamedChild(item, "_tb") as TextBox).Focus();
}

public static object FindNamedChild(DependencyObject container, string name)
{
    if (container is FrameworkElement)
    {
        if ((container as FrameworkElement).Name == name) return container;
    }
    var ccount = VisualTreeHelper.GetChildrenCount(container);
    for (int i = 0; i < ccount; i++)
    {
        var child = VisualTreeHelper.GetChild(container, i);
        var target = FindNamedChild(child, name);
        if (target != null)
        {
            return target;
        }
    }
    return null;
}

This is very sketchy, use any part of this at your own risk. (The focusing also could have been done differently without bringing the selection into this i think)

(The Command class is just a generic implementation of ICommand which takes a lambda which is executed in the interface's Execute method)

like image 35
H.B. Avatar answered Nov 18 '22 01:11

H.B.