当选择ListBoxItem时,如何将焦点设置到ItemTemplate中的控件?

3
我有一个ListBox,使用DataTemplate呈现对象。DataTemplate包含一个TextBox。当用户选择ListBox中的项目时,我想将焦点设置到所选项目的TextBox上。
通过处理ListBox.SelectionChanged事件,我已经能够部分实现此目标,但仅在用户单击ListBox以选择项目时才有效 - 即使TextBox.Focus()被调用,如果用户使用箭头键从键盘选择项目,则不起作用
当用户使用键盘选择项目时,我该如何将焦点设置到TextBox上?
以下是ListBox的标记:
<ListBox Name="lb1" SelectionChanged="ListBox_SelectionChanged" ItemsSource="{Binding Items}" >
    <ListBox.ItemTemplate>
        <DataTemplate >
            <TextBox></TextBox>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

以下是处理代码:

private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    ListBoxItem lbi = (ListBoxItem)this.lb1.ItemContainerGenerator.ContainerFromItem(this.lb1.SelectedItem);
    Visual v = GetDescendantByType<TextBox>(lbi);
    TextBox tb = (TextBox)v;
    tb.Focus();
}
1个回答

7

一种做法是用以下代码替换你的SelectionChanged事件中的tb.Focus()

tb.Dispatcher.BeginInvoke(DispatcherPriority.Input, new ThreadStart(delegate()
        {
            tb.Focus();
        }));

这是因为在调用调度程序上的 BeginInvoke 时,指定的代码将在调度程序可用时运行-即在WPF内部处理事件后。 问题在于,当列表项获得焦点时首次按下箭头后,下一个列表项将被选中,它的文本框将获得焦点,您将无法再使用向下箭头移动选择。 您可能还需要编写一些代码来处理此情况。

不错 :) 希望你不介意我在答案中加一句话来解释为什么它有效。我必须说这感觉有点不太好,但它能完成任务。 - Greg Sansom
哇,那一行代码真是救了我的一天!非常感谢你。 - Timotei

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