WPF中的焦点数据模板
我正在寻找的行为是,在ListView中选择一个项目会导致聚焦第一个可聚焦的visualchild 问题:ItemsController中的数据模板化数据没有获得初始焦点。 在下面的示例中,有4个字符串,然后通过Datatemplate填充到文本框中 例如:WPF中的焦点数据模板,wpf,xaml,focus,datatemplate,Wpf,Xaml,Focus,Datatemplate,我正在寻找的行为是,在ListView中选择一个项目会导致聚焦第一个可聚焦的visualchild 问题:ItemsController中的数据模板化数据没有获得初始焦点。 在下面的示例中,有4个字符串,然后通过Datatemplate填充到文本框中 例如: <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:sys="clr-namespace:System;as
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<ListView>
<ListView.Resources>
<DataTemplate DataType="{x:Type sys:String}" >
<TextBox Width="100" Text="{Binding Mode=OneWay}"/>
</DataTemplate>
</ListView.Resources>
<ListView.ItemsSource>
<x:Array Type="{x:Type sys:String}">
<sys:String>test</sys:String>
<sys:String>test</sys:String>
<sys:String>test</sys:String>
<sys:String>test</sys:String>
</x:Array>
</ListView.ItemsSource>
</ListView>
</Grid>
</Window>
毫无意义地说:没有成功。
有人知道我如何在不遍历c#中的可视化树的情况下得到我想要的吗?
应该可以做到这一点,不是吗?在C#中使用绑定语法是行不通的,因为在XAML中绑定就是这样描述的。创建
System.Windows.Data.Binding
的一个新实例,并将其属性设置为与在XAML中设置的属性相同的属性,可能会起作用,但我不确定为了使其正常工作,您可以绑定到哪个ElementName
我能想到的唯一其他选择是为SelectionChanged
事件添加一个处理程序,并手动设置焦点,但这听起来不像是您想要的解决方案
经进一步检查,我认为不可能有一个有约束力的解决方案FocusManager.FocusedElement
是一个IInputElement
,它没有任何与绑定相关的成员。我认为您需要遍历视觉树,以便找到第一个可聚焦的对象。像这样的方法应该会奏效:
// Event handler for the ListBox.SelectionChanged event
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListBox listBox = sender as ListBox;
ItemContainerGenerator = generator.listBox.ItemContainerGenerator;
ListBoxItem selectedItem =
(ListBoxItem)generator.ContainerFromIndex(listBox.SelectedIndex);
IInputElement firstFocusable = FindFirstFocusableElement(selectedItem);
firstFocusable.Focus();
}
private IInputElement FindFirstFocusableElement(DependencyObject obj)
{
IInputElement firstFocusable = null;
int count = VisualTreeHelper.GetChildrenCount(obj);
for(int i = 0; i < count && null == firstFocusable; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
IInputElement inputElement = child as IInputElement;
if(null != inputElement && inputElement.Focusable)
{
firstFocusable = inputElement;
}
else
{
firstFocusable = FindFirstFocusableElement(child);
}
}
return firstFocusable;
}
//ListBox.SelectionChanged事件的事件处理程序
私有无效列表框\u SelectionChanged(对象发送方,SelectionChangedEventArgs e)
{
ListBox ListBox=发送方作为ListBox;
ItemContainerGenerator=generator.listBox.ItemContainerGenerator;
ListBoxItemSelectedItem=
(listBox项)generator.ContainerFromIndex(listBox.SelectedIndex);
IIInputElement firstFocusable=FindFirstFocusableElement(selectedItem);
firstFocusable.Focus();
}
私有IIInputElement FindFirstFocusableElement(DependencyObject obj)
{
IIInputElement firstFocusable=null;
int count=VisualTreeHelper.GetChildrenCount(obj);
对于(int i=0;i
在C#中使用绑定语法是行不通的,因为在XAML中绑定就是这样描述的。创建System.Windows.Data.Binding
的一个新实例,并将其属性设置为与在XAML中设置的属性相同的属性,可能会起作用,但我不确定为了使其正常工作,您可以绑定到哪个ElementName
我能想到的唯一其他选择是为SelectionChanged
事件添加一个处理程序,并手动设置焦点,但这听起来不像是您想要的解决方案
经进一步检查,我认为不可能有一个有约束力的解决方案FocusManager.FocusedElement
是一个IInputElement
,它没有任何与绑定相关的成员。我认为您需要遍历视觉树,以便找到第一个可聚焦的对象。像这样的方法应该会奏效:
// Event handler for the ListBox.SelectionChanged event
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListBox listBox = sender as ListBox;
ItemContainerGenerator = generator.listBox.ItemContainerGenerator;
ListBoxItem selectedItem =
(ListBoxItem)generator.ContainerFromIndex(listBox.SelectedIndex);
IInputElement firstFocusable = FindFirstFocusableElement(selectedItem);
firstFocusable.Focus();
}
private IInputElement FindFirstFocusableElement(DependencyObject obj)
{
IInputElement firstFocusable = null;
int count = VisualTreeHelper.GetChildrenCount(obj);
for(int i = 0; i < count && null == firstFocusable; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
IInputElement inputElement = child as IInputElement;
if(null != inputElement && inputElement.Focusable)
{
firstFocusable = inputElement;
}
else
{
firstFocusable = FindFirstFocusableElement(child);
}
}
return firstFocusable;
}
//ListBox.SelectionChanged事件的事件处理程序
私有无效列表框\u SelectionChanged(对象发送方,SelectionChangedEventArgs e)
{
ListBox ListBox=发送方作为ListBox;
ItemContainerGenerator=generator.listBox.ItemContainerGenerator;
ListBoxItemSelectedItem=
(listBox项)generator.ContainerFromIndex(listBox.SelectedIndex);
IIInputElement firstFocusable=FindFirstFocusableElement(selectedItem);
firstFocusable.Focus();
}
私有IIInputElement FindFirstFocusableElement(DependencyObject obj)
{
IIInputElement firstFocusable=null;
int count=VisualTreeHelper.GetChildrenCount(obj);
对于(int i=0;i
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>
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>
即使我想在c语言中手动执行,我也需要从Datatemplate中获取对文本框的引用,如果运气不好,里面会有多个级联datatemplates,因此我需要搜索它。。。必须能够将焦点放在第一个输入上。奇怪的是,像这样基本的东西并不像WPF的其他部分那么优雅。我仍然希望通过.NET4.0获得一个简单的基于XAML的答案。我希望你能理解为什么我不会把你的帖子标记为答案,即使我可能会使用这种解决方案的变体。我理解。几天前,我正在研究一个潜在的解决方案(FocusManager.FocusedElement是大多数控件的附加属性),但是我仍然无法得到任何东西来工作。即使我想在c#中手动完成,我也需要从Datatemplate中获取对文本框的引用,如果运气不好的话,里面会有多个级联的datatemplates,所以我需要