我有DataTemplate
一个TextBox
.我将此模板设置为选择中的列表框项.
我无法将焦点设置到模板中的文本框中.我试图调用MyTemplate.FindName,但最终会出现无效操作异常:此操作仅对应用了此模板的元素有效.
我该如何访问它?
我知道这已经过时了,但我今天遇到了这个问题,最后提出了这个决议:
由于TextBox
仅在选择项目时加载,并且您希望设置焦点时,您可以简单地处理TextBox.Load
事件和调用Focus()
.
有两种方法可以实现这一目标.
1.更换TextBox
在DataTemplate
用AutoFocusTextBox
.
public class AutoFocusTextBox : TextBox { public AutoFocusTextBox() { Loaded += delegate { Focus(); }; } }
不要忘记您需要引用在.xaml文件中定义AutoFocusTextBox的命名空间.
2.在DataTemplate
定义文件的代码隐藏中添加处理程序.
SomeResourceDictionary.xaml
SomeResourceDictionary.xaml.cs
private void FocusTextBoxOnLoad(object sender, RoutedEventArgs e) { var textbox = sender as TextBox; if(textbox == null) return; textbox.Focus(); }
使用任一选项,您始终可以在处理程序中添加其他行为,例如选择所有文本.
由于您知道TextBox
要关注的名称,因此相对容易.我们的想法是抓住模板,因为它适用于ListBoxItem
自身.
您要做的第一件事是获取所选项目:
var item = listBox1.ItemContainerGenerator.ContainerFromItem(listBox1.SelectedItem) as ListBoxItem;
然后你可以将它传递给这个小帮助函数,该函数根据其名称聚焦控件:
public void FocusItem(ListBoxItem item, string name) { if (!item.IsLoaded) { // wait for the item to load so we can find the control to focus RoutedEventHandler onload = null; onload = delegate { item.Loaded -= onload; FocusItem(item, name); }; item.Loaded += onload; return; } try { var myTemplate = FindResource("MyTemplateKey") as FrameworkTemplate; // or however you get your template right now var ctl = myTemplate.FindName(name, item) as FrameworkElement; ctl.Focus(); } catch { // focus something else if the template/item wasn't found? } }
我想棘手的一点是确保你等待物品加载.我不得不添加该代码,因为我是从ItemContainerGenerator.StatusChanged
事件中调用此代码,有时在ListBoxItem
我们输入方法时尚未完全初始化.
好.所以我认为我有最好的解决方案.无论如何它对我有用.我有一个简单的数据模板,我想把焦点放在文本框中.将FocusManager
手离开集中到文本框中.