【问题标题】:RichTextBox current scroll positionRichTextBox 当前滚动位置
【发布时间】:2021-09-03 08:02:45
【问题描述】:

如果是 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();
    }
}

【问题讨论】:

  • 我认为,当 许多更改 应用于 FlowDocument 使用 当前垂直滚动位置 是错误的方式。更合理的是在新的格式化文本上设置插入符号(或使用选择)并滚动以在视图中心定位插入符号/选择。

标签: c# wpf richtextbox


【解决方案1】:

考虑下面的代码。

定义:

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 变为无效,则应在调用ScrollToVerticalOffset() 之前计算新的TextPointer 值。

【讨论】:

    猜你喜欢
    • 2011-04-08
    • 1970-01-01
    • 2014-11-03
    • 2010-12-22
    • 2012-03-18
    • 2013-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多