【发布时间】:2017-06-28 19:28:42
【问题描述】:
我有一个使用多行文本框作为其 DataTemplate 的 ListView。
默认情况下,在多行文本框中,启用向上和向下箭头导航。如果您的 TextBox 有两行,插入符号位于第一行并且您按下向下箭头,它会将插入符号放在第二行的相同相对位置。
我还在 ListView 中的 TextBox 之间添加了光标导航。如果您在 TextBox 的第一行并按向上箭头,则会将焦点设置到 ListView 中的前一个 TextBox。同样,如果您在最后一行并按下,它会转到下一个 TextBox。但是因为这必须手动完成,所以我不得不编写自己的逻辑来保持相对位置。但它很复杂,也有一些问题。
private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
var tb = (sender as TextBox);
var textBeforeCursor = tb.Text.Substring(0, tb.SelectionStart);
var textAfterCursor = tb.Text.Substring(tb.SelectionStart);
if (e.Key == Key.Up && !textBeforeCursor.Contains("\r\n"))
{
var caretIndex = GetTextBoxCaretIndex();
listView.SelectedIndex--;
var lastLineRegex = new Regex("(.*)(\r\n.*$)", RegexOptions.Singleline);
var previousString = listView.SelectedItem as string;
var lines = lastLineRegex.Match(previousString);
var offset = lines.Groups[1].Length;
FocusTextBox(caretIndex + offset + 2);
}
if (e.Key == Key.Down && !textAfterCursor.Contains("\r\n"))
{
var caretIndex = GetTextBoxCaretIndex();
var lastLineRegex = new Regex("(.*)(\r\n.*$)", RegexOptions.Singleline);
var previousString = listView.SelectedItem as string;
var lines = lastLineRegex.Match(previousString);
var offset = lines.Groups[1].Length;
listView.SelectedIndex++;
Console.WriteLine($"CaretIndex: {caretIndex}, Offset: {offset}");
FocusTextBox(caretIndex - offset - 2);
}
}
private int GetTextBoxCaretIndex()
{
var item = listView.ItemContainerGenerator.ContainerFromItem(listView.SelectedItem) as ListViewItem;
var textBox = GetVisualChildOfType<TextBox>(item);
return textBox.CaretIndex;
}
private void FocusTextBox(int caretIndex = 0)
{
var item = listView.ItemContainerGenerator.ContainerFromItem(listView.SelectedItem) as ListViewItem;
var textBox = GetVisualChildOfType<TextBox>(item);
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
textBox.CaretIndex = Math.Min(caretIndex, textBox.Text.Length);
textBox.SelectionStart = textBox.CaretIndex;
textBox.Focus();
}));
}
这种逻辑很有效,但在某些情况下会破坏行间的默认插入符号导航。
Here's a .gif of one example case
插入符号位于顶部文本框的底行,超过 8 个字符。我按下,它转到第二个文本框,第一行有插入符号,超过 8 个字符;预期的行为。
然后我再次按下,它转到第二行,但在第一个字符而不是第 8 行。我的代码在这种情况下没有执行,所以默认逻辑发生了一些不寻常的事情。
我什至不知道从哪里开始。通过测试它似乎 TextBox 对每一行的插入符号位置有一些内部状态,但通过查看 TextBox 文档,我没有看到任何关于此的属性。
您可以查看一个精简的示例项目和完整的代码来演示问题on GitHub。
任何有关默认插入符号导航如何工作的帮助或信息都会有所帮助。感谢您的宝贵时间。
【问题讨论】: