我有一个列表框,其中每个项目都使用文本框表示。问题是我希望能够在移动到xaml窗口中的下一个元素之前在列表框中的所有项之间进行选项卡。
当前(和正常的WPF行为)是当我进入列表框时,第一个元素突出显示,如果我再次选中,则焦点移动到该项目内的文本框中。如果我再次选中,则焦点移动到窗口中的下一个元素(不通过ListBox中的任何其他项目)。
我想要的行为如下:当我进入列表框时,第一个文本框自动获得焦点(不突出显示整个项目)*。如果我再次选中,则列表框中的下一个文本框将获得焦点。当我在列表框的最后一个文本框中选中时,焦点移动到下一个控件。
*我已经如何做到这一点,我只是在这里发布,以解释整个过程。
我一直在寻找解决方案而且我找不到任何东西。
答案 0 :(得分:67)
这可以通过设置以下两个属性在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。
答案 1 :(得分:0)
修改
评论之后,具体来说:
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将确保仅在选项卡上处理您的处理程序,并且不会激活默认行为。