首页 > 解决方案 > 在作为 ListBoxItem 内容的 UserControl 上的 TextBox 上设置焦点

问题描述

我有一个Button在 aUserControl上添加一个项目到 a ListBoxon that UserControl。我们称该控件为父控件。sListBoxItem包含另一个. UserControl我们就叫那个孩子吧。该按钮将一个项目添加到ItemSource列表框(MVVM 样式)。

我可以毫无问题地将其滚动到视图中。我可以将焦点设置为ListBoxItem,但我想要的是将焦点TextBox设置UserControlListBoxItem. 我似乎无法弄清楚。下面的代码将焦点设置为ListBoxItem,而不是它的UserControl子级或它上的任何控件。

Private Sub bnAdd(sender As Object, e As RoutedEventArgs)
   VM.AddDetail()
   MyList.ScrollIntoView(MyList.Items(MyList.Items.Count - 1))
   Dim ListBoxItem As ListBoxItem = MyList.ItemContainerGenerator.ContainerFromItem(MyList.SelectedItem)
   ListBoxItem.Focus()
End Sub

在我的孩子UserControl身上,我在 XAML 中使用了这个:

FocusManager.FocusedElement="{Binding ElementName=txtMyBox}"

标签: wpfxamlmvvmfocuslistboxitem

解决方案


这里有一个相关的问题,大多数方法都使用挂钩焦点事件来实现焦点变化。我想提出另一种基于遍历可视化树的解决方案。不幸的是,我只能为您提供 C# 代码,但您可以使用该概念将其应用到您的 Visual Basic 代码中。

据我所知,您正在使用代码隐藏将您的项目滚动到视图中。我会以此为基础。您的列表框有列表框项,我猜您使用数据模板将UserControls 显示为子项。在这些用户控件中,您已通过属性在 XAML 中或在代码隐藏中TextBox分配了一个名称。现在,您需要一个辅助方法来遍历可视化树并搜索文本框。x:NameName

private IEnumerable<TextBox> FindTextBox(DependencyObject dependencyObject)
{
   // No other child controls, break
   if (dependencyObject == null)
      yield break;

   // Search children of the current control
   for (var i = 0; i < VisualTreeHelper.GetChildrenCount(dependencyObject); i++)
   {
      var child = VisualTreeHelper.GetChild(dependencyObject, i);

      // Check if the current item is a text box
      if (child is TextBox textBox)
         yield return textBox;

      // If we did not find a text box, search the children of this child recursively
      foreach (var childOfChild in FindTextBox(child))
         yield return childOfChild;
   }
}

然后我们添加一个使用 Linq 过滤给定名称的可枚举文本框的方法。

private TextBox FindTextBox(DependencyObject dependencyObject, string name)
{
   // Filter the list of text boxes for the right one with the specified name
   return FindTextBox(dependencyObject).SingleOrDefault(child => child.Name.Equals(name));
}

在您的bnAdd处理程序中,您可以使用ListBoxItem, 搜索文本框子项并将其聚焦。

var textBox = FindTextBox(listBoxItem, "MyTextBox");
textBox.Focus();

推荐阅读