Получить строку и столбец WPF TextBox - PullRequest
1 голос
/ 29 апреля 2020

Я искал, и решения здесь работают для получения позиции строки и столбца курсора в текстовом поле 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}";
    }

1 Ответ

1 голос
/ 29 апреля 2020

Очень странное поведение. Даже просматривая исходный код. NET, я не мог точно понять, почему это происходит. Я потратил некоторое время на написание своего исследования и представил его как ошибку в. NET framework.

Вот ссылка на отчет об ошибке: System. Windows .Controls .TextBox.GetCharacterIndexFromLineIndex возвращает все более и более неправильные значения для больших номеров строк

Но я приведу краткое изложение того, что я нашел:

Мой опыт немного отличался от вашего. В моих тестах все работает нормально, пока я не доберусь до строки 8,512. Начиная с этой строки GetCharacterIndexFromLineIndex, похоже, начинает возвращать начальный индекс следующей строки вместо запрашиваемого. То есть вместо того, чтобы дать мне начало 8,512, он дал мне начало 8513.

Тестируя с большим количеством строк, я обнаружил, что в строке 25,536 GetCharacterIndexFromLineIndex начинает пропускать two строк, вместо этого возвращая начало строки 25,538. Число пропусков строк увеличивается до 3 в строке 42 560, а затем до 4 в строке 59 584.

Это показывает шаблон: каждые 17 024 строки количество пропущенных строк увеличивается на 1. Шаблон начинается в строке 8 512, потому что это 17 024/2 (половина).

Я не могу объяснить, почему это происходит точно, но вышеприведенное предоставляет некоторую хорошую документацию по поведению. И ниже, я собрал некоторый код, чтобы обойти эту проблему.

Вы можете обойти это до drgree:

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).

...