代码之家  ›  专栏  ›  技术社区  ›  Carlos G.

列表元素WPF之间的选项卡

  •  24
  • Carlos G.  · 技术社区  · 15 年前

    我有一个列表框,其中每个项目都用文本框表示。问题是,在移到XAML窗口的下一个元素之前,我希望能够在列表框中的所有项之间进行制表。

    当前的(和正常的WPF行为)是,当我选项卡进入列表框时,第一个元素被突出显示,如果我再次选项卡,那么焦点将移到该项内的文本框中。如果我再次制表,焦点移动到窗口中的下一个元素(而不经过列表框中的任何其他项)。

    我想要的行为如下:当我进入列表框时,第一个文本框自动获得焦点(不突出显示整个项目)*。如果我再次制表,则列表框中的下一个文本框将获得焦点。当我在列表框的最后一个文本框处制表时,焦点移动到下一个控件。

    *我已经知道怎么做了,我只是把它贴在这里来解释整个过程。

    我一直在寻找解决方案,但找不到任何东西。

    2 回复  |  直到 6 年前
        1
  •  67
  •   Jones James    6 年前

    这可以在XAML中通过设置以下两个属性来完成。

        <Style TargetType="ListBox" >
            <Setter Property="KeyboardNavigation.TabNavigation" Value="Continue" />
        </Style>
    
        <Style TargetType="ListBoxItem">
            <Setter Property="IsTabStop" Value="False" />
        </Style>
    

    有关完整解释,请参阅 Derek Wilson's Blog post .

        2
  •  0
  •   Fabrício Matté    15 年前

    编辑

    评论之后,具体来说:

    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
    }
    

    设置 e.Handled 若为true,将确保只在按Tab键时处理处理处理程序,并且不会激活默认行为。