我有DataTemplate
,其中包含TextBox
。我将此模板设置为选择上的列表框项目。专注于DataTemplate中的TextBox
我无法将焦点设置为模板中的文本框。我试图调用MyTemplate.FindName,但它以无效的操作异常结束:此操作仅对应用此模板的元素有效。
我该如何访问它?
我有DataTemplate
,其中包含TextBox
。我将此模板设置为选择上的列表框项目。专注于DataTemplate中的TextBox
我无法将焦点设置为模板中的文本框。我试图调用MyTemplate.FindName,但它以无效的操作异常结束:此操作仅对应用此模板的元素有效。
我该如何访问它?
既然你知道你想要关注的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
在我们输入方法时尚未完全初始化。
我知道这是老了,但我今天碰到这个问题跑,并最终想出了这个解决:
由于TextBox
当选择一个项目只被加载,那就是当你想您可以简单地处理TextBox.Load
事件并致电Focus()
。
有两种方法可以实现这一点。
1.用AutoFocusTextBox
替换DataTemplate
中的TextBox
。
public class AutoFocusTextBox : TextBox
{
public AutoFocusTextBox()
{
Loaded += delegate { Focus(); };
}
}
不要忘记你需要引用其中AutoFocusTextBox在您的.xaml文件中定义的命名空间。
2.在定义了DataTemplate
的文件的代码隐藏处添加处理程序。
SomeResourceDictionary.xaml
<TextBox Text="{Binding Something, Mode=TwoWay}" Style={StaticResource ...
Loaded="FocusTextBoxOnLoad" />
SomeResourceDictionary.xaml.cs
private void FocusTextBoxOnLoad(object sender, RoutedEventArgs e)
{
var textbox = sender as TextBox;
if(textbox == null) return;
textbox.Focus();
}
无论使用哪种方法,你可以随时添加其他行为的处理程序,如选择所有文本。
周杰伦的第二个建议是整齐的 - 并且可以使用UIElement
而不是TextBox
,使任何控制可以很容易地成为默认被更广义的:
private void FocusControlOnLoad(object sender, RoutedEventArgs e)
{
var uiElement = sender as UiElement;
if(uiElement == null) return;
uiElement.Focus();
}
确定。所以我认为我有最好的解决方案。反正它适合我。我有一个简单的数据模板,我想把焦点放在文本框上。 FocusManager
将焦点移交给文本框。
<DataTemplate x:Key="MyDataTemplate" DataType="ListBoxItem">
<Grid>
<WrapPanel Orientation="Horizontal" FocusManager.FocusedElement="{Binding ElementName=tbText}">
<CheckBox IsChecked="{Binding Path=Completed}" Margin="5" />
<Button Style="{StaticResource ResourceKey=DeleteButtonTemplate}" Margin="5" Click="btnDeleteItem_Click" />
<TextBox Name="tbText"
Text="{Binding Path=Text}"
Width="200"
TextWrapping="Wrap"
AcceptsReturn="True"
Margin="5"
Focusable="True"/>
<DatePicker Text="{Binding Path=Date}" Margin="5"/>
</WrapPanel>
</Grid>
</DataTemplate>
不错,干净,也适合我,我喜欢它 – veljkoz 2014-06-01 10:08:19
FindResource返回一个对象,所以一定要把它转换成一个FrameworkTemplate。 – Michael 2011-11-22 23:33:04