获取 WPF 文本框的行和列位置

Get WPF TextBox Row and Column Position

我一直在搜索,此处的解决方案适用于获取光标在 WPF 文本框中的行和列位置,直到行号大于 16,311。之后,该列为负值。

    private void SetTextFileCursorPosition()
    {
        var caretIndex = TextFile.CaretIndex;
        var row = TextFile.GetLineIndexFromCharacterIndex(caretIndex);
        var col = caretIndex - TextFile.GetCharacterIndexFromLineIndex(row);
        CursorPosition = $"{col + 1}, {row + 1}";
    }

非常奇怪的行为。即使翻阅 .NET 源代码,我也无法完全弄清楚为什么会这样。我花了一些时间撰写我的研究并将其作为 .NET 框架中的错误提交。

这是错误报告的 link: System.Windows.Controls.TextBox.GetCharacterIndexFromLineIndex returns increasingly incorrect values for larger line numbers

但我会总结一下我的发现:

我的经历和你的有点不同。在我的测试中,一切正常,直到我到达第 8,512 行。从该行开始 GetCharacterIndexFromLineIndex 似乎开始返回 next 行的起始索引,而不是所请求的行。意思是,不是给我 8,512 的开始,而是给我 8,513 的开始。

测试更多行后,我发现在第 25,536 行,GetCharacterIndexFromLineIndex 开始跳过 两个 行,而不是返回第 25,538 行的开头。跳行数在第 42,560 行增加到 3,然后在第 59,584 行增加到 4。

这揭示了一个规律:每 17,024 行,跳过的行数增加 1。规律从第 8,512 行开始,因为它是 17,024 / 2(一半)。

我无法解释为什么会发生这种情况,但上面提供了一些关于该行为的很好的文档。在下面,我整理了一些代码来解决这个问题。

您可以解决这个问题:

var caretIndex = TextFile.CaretIndex;
var line = TextFile.GetLineIndexFromCharacterIndex(caretIndex);
var colStart = TextFile.GetCharacterIndexFromLineIndex(line);
var pos = caretIndex - colStart;

int posAdj = pos;
int lineAdj = line;

while (posAdj < 0)
{
    posAdj = TextFile.GetLineLength(lineAdj) + posAdj;
    lineAdj--;
}

CursorPosition = $"{posAdj + 1}, {line + 1}"; //NOT lineAdj

上面添加了前面几行的长度,直到达到正值,有效地添加了跳过的行。无论文本有多长,这都应该有效,甚至在他们(希望)修补错误后应该继续工作(从那时起 pos 永远不应该是 < 0)。