【问题标题】:WPF FlowDocument - Absolute Character PositionWPF FlowDocument - 绝对字符位置
【发布时间】:2014-10-12 01:02:51
【问题描述】:

我有一个 WPF RichTextBox,我正在输入一些文本,然后解析整个文本以进行处理。在这个解析过程中,我得到了每个单词开头和结尾的绝对字符位置。

我想使用这些字符位置来对某些单词应用格式。但是,我发现 FlowDocument 使用 TextPointer 实例来标记文档中的位置。

我发现我可以通过使用开始和结束指针构造 TextRange 来创建它。拥有 TextRange 后,我可以轻松地将格式应用于其中的文本。我一直在使用 GetPositionAtOffset 来获取我的字符偏移量的 TextPointer,但怀疑它的偏移量与我的不同,因为所选文本的位置与我预期的略有不同。

我的问题是,如何准确地将绝对字符位置转换为 TextPointer?

【问题讨论】:

  • +1,我有这个确切的问题 - 进行自定义解析并且高光偏移错误:-)

标签: c# .net wpf richtextbox flowdocument


【解决方案1】:

我也遇到了这个问题,最终得到了下面的 RichTextBox 扩展方法。在我的上下文中,它完美无缺!

/// <summary>
/// Gets the text pointer at the given character offset.
/// Each line break will count as 2 chars.
/// </summary>
/// <param name="richTextBox">The rich text box.</param>
/// <param name="offset">The offset.</param>
/// <returns>The TextPointer at the given character offset</returns>
public static TextPointer GetTextPointerAtOffset(this RichTextBox richTextBox, int offset)
{
    var navigator = richTextBox.Document.ContentStart;
    int cnt = 0;

    while (navigator.CompareTo(richTextBox.Document.ContentEnd) < 0)
    {
        switch (navigator.GetPointerContext(LogicalDirection.Forward))
        {
            case TextPointerContext.ElementStart:
                break;
            case TextPointerContext.ElementEnd:
                if (navigator.GetAdjacentElement(LogicalDirection.Forward) is Paragraph)
                    cnt += 2;
                break;
            case TextPointerContext.EmbeddedElement:
                // TODO: Find out what to do here?
                cnt++;
                break;
            case TextPointerContext.Text:
                int runLength = navigator.GetTextRunLength(LogicalDirection.Forward);

                if (runLength > 0 && runLength + cnt < offset)
                {
                    cnt += runLength;
                    navigator = navigator.GetPositionAtOffset(runLength);
                    if (cnt > offset)
                        break;
                    continue;
                }
                cnt++;
                break;
        }

        if (cnt > offset)
            break;

        navigator = navigator.GetPositionAtOffset(1, LogicalDirection.Forward);

    } // End while.

    return navigator;
}

【讨论】:

    【解决方案2】:

    我没有找到将绝对字符位置转换为 TextPosition 实例的可靠方法。

    我的替代解决方案是修改原始解析以处理单个运行,而不是捕获 RichTextBox 的整个文本。使用与特定 Run 实例相关的角色位置对我来说是可靠的。我认为将我的思维方式更多地转向 WPF 的思维方式会有所帮助。

    我采用以下方法在 FlowDocument 中导航运行(灵感来自 http://blogs.msdn.com/prajakta/archive/2006/10/12/customize-richtextbox-to-allow-only-plain-text-input.aspx):

    // Get starting pointer
    TextPointer navigator = flowDocument.ContentStart;
    
    // While we are not at end of document
    while (navigator.CompareTo(flowDocument.ContentEnd) < 0)
    {
        // Get text pointer context
        TextPointerContext context = navigator.GetPointerContext(LogicalDirection.Backward);
    
        // Get parent as run
        Run run = navigator.Parent as Run;
    
        // If start of text element within run
        if (context == TextPointerContext.ElementStart && run != null)
        {
            // Get text of run
            string runText = run.Text;
    
            // ToDo: Parse run text
        }
    
        // Get next text pointer
        navigator = navigator.GetNextContextPosition(LogicalDirection.Forward);
    }
    

    【讨论】:

      【解决方案3】:

      我有完全相同的问题,我发现 RichTextBox 中有一个错误,因为它不计算“换行符 - \r\n”,所以随着你的行号增加,你会发现你的偏移量被定位行号计数错误,我通过从偏移量中偏移行号解决了我的问题。

      【讨论】:

      • 您好 Akash,感谢您的回复。我的经验是它正在计算我的换行符,但注意到完全空白行“”导致FlowDocument 比我的偏移量早 2 个字符(在每个换行符之后累积)。艾伦
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-27
      • 2011-03-29
      • 1970-01-01
      • 2010-09-25
      • 2011-04-09
      • 1970-01-01
      相关资源
      最近更新 更多