RichTextBox 当前滚动位置

RichTextBox current scroll position

如果是 RichTextBox(行号或 TextPointer),我希望能够获取当前的垂直滚动位置。

在我的场景中,我有一个反汇编程序,用户选择行和选项以将汇编行重新格式化为字节、单词、文本等。这很好用。它还会导致如此多的更改,以至于 FlowDocument 被重新创建,并且在重新创建文本后默认滚动到顶部。我更改了我的代码,以便它获取当前选择的行号并在文本更改时滚动到该行。问题在于它将行放在顶部。我希望它根本不滚动。我有可以滚动到任何行号的代码,或者它可以从 TextPointer 获取行号并滚动到该行号。如果我可以在更改文本之前获取滚动值,我可以重新滚动到该值,这样文本就不会跳转。

var line = FindLineNumber(ref RichTextListing.RichText, RichTextListing.RichText.Selection.Start);
View.Flow = doc;
ScrollToLine(ref RichTextListing.RichText, line);

private TextPointer GetTextPosition(ref RichTextBox rtb, int line)
{
    var p = rtb.Document.ContentStart;
    var findStart = p.GetLineStartPosition(0);
    if (findStart == null)
    {
        return p;
    }
    var lineNum = 0;
    while (lineNum < line)
    {
        findStart = findStart.GetLineStartPosition(1, out _);
        lineNum++;
    }

    return findStart;
}

private int FindLineNumber(ref RichTextBox rtb, TextPointer p)
{
    var findStart = p?.GetLineStartPosition(0);
    if (findStart == null) return 0;
    var startLinePosition = rtb.Document.ContentStart.GetLineStartPosition(0);
    if (startLinePosition == null) return 0;

    var foundLineNumber = 0;
    while (true)
    {
        if (startLinePosition.CompareTo(findStart) >= 0)
        {
            break;
        }

        startLinePosition = startLinePosition.GetLineStartPosition(1, out var result);
        if (result == 0)
        {
            break;
        }

        foundLineNumber++;
    }

    return foundLineNumber;
}

private void ScrollToLine(ref RichTextBox rtb, int line)
{
    var pos = GetTextPosition(ref rtb, line);
    if (pos == null) return;
    if (pos.Parent is FrameworkContentElement e)
    {
        e.BringIntoView();
    }
}

考虑以下代码。

定义:

private TextPointer ChangesStartPosition { get; set; }

在文档中进行更改之前设置 ChangesStartPosition 属性:

// `rtb` in the code below is the RichTextBox
ChangesStartPosition = rtb.Selection.IsEmpty ? rtb.CaretPosition : rtb.Selection.Start;

在文档中执行更改后,使用以下代码使插入符号在 RichTextBox 中居中:

var rect = ChangesStartPosition.GetCharacterRect(LogicalDirection.Forward);
rtb.ScrollToVerticalOffset(rtb.VerticalOffset + rect.Top - rtb.ActualHeight / 2d);
rtb.CaretPosition = ChangesStartPosition;

如果ChangesStartPosition属性引用的文档的一部分发生变化,ChangesStartPosition失效,那么调用前需要计算一个新的TextPointerScrollToVerticalOffset().