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

时间:2011-01-13 06:26:46

标签: wpf focus datatemplate listboxitem

我有一个ListBox,它使用DataTemplate显示对象。 DataTemplate包含一个TextBox。当用户选择ListBox中的项目时,我想将焦点设置为所选项目的TextBox。

我已经能够通过处理ListBox.SelectionChanged来部分实现这一点,但它仅在用户单击ListBox以选择项目时才有效 - 如果用户选中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 个答案:

答案 0 :(得分:6)

执行此操作的一种方法是将tb.Focus()事件处理程序中的SelectionChanged替换为:

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

这是有效的,因为调度程序上调用BeginInvoke会导致指定代码在调度程序可用时运行 - 即在WPF内部完成事件处理之后。

问题在于,当您在列表项具有焦点时首次按下箭头后,下一个列表项将被选中,其文本框将变为焦点,您将无法使用向下箭头再次移动选择。您可能也想编写一些代码来处理这种情况。