问题描述
WPF:当用户在 ItemsControl 的 texbox 内按下回车键时,我想将焦点移至 ItemsControl 中下一项的文本框,或者如果用户在最后一项中,则创建一个新的文本框.
WPF: When user presses the enter key while inside a texbox in a ItemsControl, I want to move focus to a textbox in the next item in ItemsControl, or create a new one if user was in the last item.
为了更清楚:
场景 1
ItemsControl items:
[ textbox in item 1 ] <- user is here
[ textbox in item 2 ]
[ textbox in item 3 ]
回车后:
[ textbox in item 1 ]
[ textbox in item 2 ] <- user is here
[ textbox in item 3 ]
场景 2
ItemsControl 项:
ItemsControl items:
[ textbox in item 1 ]
[ textbox in item 2 ]
[ textbox in item 3 ] <- user is here
回车后:
[ textbox in item 1 ]
[ textbox in item 2 ]
[ textbox in item 3 ]
[ textbox in item 4 ] <- user is here
如果有帮助,这里是项目数据模板的代码:
If it helps, here is the code for item data template:
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="32"/>
</Grid.ColumnDefinitions>
<TextBox Text="{Binding Path=PartName, FallbackValue='----',TargetNullValue='----', NotifyOnSourceUpdated=True}" KeyDown="TextBox_KeyDown"/>
<Button Grid.Column="1" FontSize="10" x:Name="DeletePartButton" Click="DeletePartButton_Click" Height="22">Usuń</Button>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
编辑 2:我使用 ItemsControl 是因为不需要选择功能.
EDIT 2: I use ItemsControl because selecting feature is not wanted.
编辑 3:我找到了部分解决方案.它适用于将焦点移动到下一个元素,但不是新元素(这是这里最重要的功能)
EDIT 3: I have found a partial solution. It works for moving a focus to a next element, but not a new one (which is the most important functionality here)
private void PartNameTextBox_KeyDown(object sender, KeyEventArgs e)
{
var box = (TextBox)sender;
if (e.Key == Key.Enter)
{
var part = (PiecePart)box.DataContext;
int index = part.ParentPiece.Parts.IndexOf(part);
if (index == part.ParentPiece.PartCount - 1)
{
part.ParentPiece.Parts.Add(new PiecePart(GetNewPartName(part.ParentPiece)));
bool success = PartListBox.ApplyTemplate();
// try to force wpf to build a visual tree for the new item success = false :(
}
// throws out of bounds exception if a new item was added (and wasn't added to a visual tree)
var el = ((UIElement)VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(PartListBox, 0),0),1),0),0),++index),0),0));
el.Focus();
}
}
推荐答案
关于TextBox的PreviewKeyDown
private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
var txt= sender as TextBox;
var selecteditem=FindParent<ListBoxItem>(txt);
int index = ListBox.ItemContainerGenerator.IndexFromContainer(selecteditem);
if(index<ListBox.Items.Count)
{
var afterItem=(ListBoxItem)ListBox.ItemContainerGenerator.ContainerFromIndex(index+1);
TextBox tbFind = GetDescendantByType(afterItem, typeof (TextBox), "TextBox") as TextBox;
if (tbFind != null)
{
FocusHelper.Focus(tbFind);
}
}
}
}
public static Visual GetDescendantByType(Visual element, Type type, string name)
{
if (element == null) return null;
if (element.GetType() == type)
{
FrameworkElement fe = element as FrameworkElement;
if (fe != null)
{
if (fe.Name == name)
{
return fe;
}
}
}
Visual foundElement = null;
if (element is FrameworkElement)
(element as FrameworkElement).ApplyTemplate();
for (int i = 0;
i < VisualTreeHelper.GetChildrenCount(element);
i++)
{
Visual visual = VisualTreeHelper.GetChild(element, i) as Visual;
foundElement = GetDescendantByType(visual, type, name);
if (foundElement != null)
break;
}
return foundElement;
}
public static T FindParent<T>(DependencyObject child) where T : DependencyObject
{
//get parent item
DependencyObject parentObject = VisualTreeHelper.GetParent(child);
//we've reached the end of the tree
if (parentObject == null) return null;
//check if the parent matches the type we're looking for
T parent = parentObject as T;
if (parent != null)
return parent;
else
return FindParent<T>(parentObject);
}
在 TextBox 上设置焦点的另一个助手:
One more helper to set the Focus on the TextBox:
public static class FocusHelper
{
public static void Focus(UIElement element)
{
element.Dispatcher.BeginInvoke(DispatcherPriority.Input, new ThreadStart(delegate()
{
element.Focus();
}));
}
}
这篇关于WPF:在进入时将焦点移动到 ItemsControl 中的下一个项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!