如何通过具有TextBoxes作为TreeViewItems的ListView进行TAB键导航?

8

我有一个ListView,我想按Tab键并在我的TreeViewItems中迭代(最好只是我的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>

我看到的情况是,第一次按Tab键时,整个第一个TreeViewItem被选中,再按Tab键时,第一个TextBox被选中。最后,第三个TAB键跳出TreeView到下一个控件,尽管在“tabbing”到下一个控件之前还有更多的TextBox需要捕获。
感谢您的阅读。
编辑: 问题在此处得到解答: 如何在ListView中通过TAB键切换文本框
3个回答

6

这是我似乎在某个部分缺失的,现在如果你在选择时将焦点添加到 TextBox 中,它就完美了。 - H.B.

2
也许我漏掉了什么,但我找不到任何简单的方法来做到这一点。以下是您可以执行的大致步骤:
<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>

我在这里做的事情:

  • 重写选项卡行为,以触发命令选择另一个项目
  • 添加事件处理程序到选定事件,以便将焦点放在文本框上
  • 给文本框命名,以便能够找到并聚焦

代码:

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;
}

这是非常简略的,使用任何部分都有风险。(我认为聚焦也可以通过其他方式实现,而不必引入选择

Command类只是一个通用的ICommand实现,它接受一个在接口的Execute方法中执行的lambda表达式


谢谢H.B.,实际上我最终没有使用它,因为当你有很多文本框时,如果你想要离开ListView,它会变得很烦人。而且我不知道SHIFT + TAB可以再次选择TreeViewItem,然后您可以使用上下箭头进行迭代,并仍然可以选择按Tab键跳出TreeView到下一个控件。 - M.C.
@Mohamed Cheri:是的,被卡在标签页中并不是很方便。我希望这对你仍有所帮助。 - H.B.

0
在 GridViewColumn 和 Cell 模板上设置 IsTabStop="False"。现在,它只会在 Tab 更改时选择 Data Template 中的 TextBox。
尝试这个:
<ListView DataContext="List" IsTabStop="False" >
        <ListView.View>
            <GridView>
                <GridViewColumn  Header="Name" />
                <GridViewColumn Header="Selector">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate  >
                            <TextBox Text="{Binding Name}" />
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
            </GridView>
        </ListView.View>
    </ListView>

<GridViewColumn IsTabStop="False" Header="选择器" Width="175" > <GridViewColumn.CellTemplate IsTabStop="False" > 不是有效的 XAML。你是不是想说? - M.C.
这样不行,列不支持这样的属性,而且焦点仍然离开整个控件而不是转到下一个项目。 - H.B.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接