C# WPF FlowDocument-绝对字符位置

C# WPF FlowDocument-绝对字符位置,c#,.net,wpf,richtextbox,flowdocument,C#,.net,Wpf,Richtextbox,Flowdocument,我有一个WPF RichTextBox,我在其中输入一些文本,然后解析整个文本进行处理。在这个解析过程中,我有每个单词的开始和结束的绝对字符位置 我想使用这些字符位置将格式应用于某些单词。但是,我发现FlowDocument使用TextPointer实例来标记文档中的位置 我发现我可以通过使用开始指针和结束指针来创建TextRange。一旦我有了TextRange,我就可以轻松地对其中的文本应用格式。我一直在使用GetPositionAtOffset为我的字符偏移量获取文本指针,但怀疑它的偏移量

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

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

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


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

我遇到了完全类似的问题,我发现RichTextBox中有一个错误,因为它不计算“新行字符-\r\n”,所以随着行号的增加,您会发现行号计数导致偏移量位置错误,我通过从偏移量中偏移行号解决了我的问题。

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

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

我采用以下方法在FlowDocument中导航运行(灵感来源于):

//获取起始指针
TextPointer navigator=flowDocument.ContentStart;
//虽然我们还没有到文件的末尾
while(navigator.CompareTo(flowDocument.ContentEnd)<0)
{
//获取文本指针上下文
TextPointerContext context=navigator.GetPointerContext(LogicalDirection.Backward);
//运行时获取父级
Run=navigator.Parent作为Run;
//如果文本元素在运行中开始
if(context==TextPointerContext.ElementStart&&run!=null)
{
//获取运行的文本
字符串runText=run.Text;
//ToDo:解析运行文本
}
//获取下一个文本指针
navigator=navigator.GetNextContextPosition(LogicalDirection.Forward);
}

我也遇到了这个问题,最后使用了以下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个字符。
/// 
///富文本框。
///偏移量。
///给定字符偏移量处的文本指针
公共静态文本指针GetTextPointerAtOffset(此RichTextBox RichTextBox,int offset)
{
var navigator=richTextBox.Document.ContentStart;
int-cnt=0;
while(navigator.CompareTo(richTextBox.Document.ContentEnd)<0)
{
开关(navigator.GetPointerContext(LogicalDirection.Forward))
{
case TextPointerContext.element开始:
打破
case text pointer context.element结束:
if(navigator.GetAdjacentElement(LogicalDirection.Forward)是段落)
cnt+=2;
打破
案例TextPointerContext.EmbeddedElement:
//TODO:看看这里该做什么?
cnt++;
打破
案例文本指针上下文。文本:
int runLength=navigator.gettextunlength(LogicalDirection.Forward);
if(runLength>0&&runLength+cnt偏移)
打破
继续;
}
cnt++;
打破
}
如果(cnt>偏移)
打破
navigator=navigator.GetPositionAtOffset(1,LogicalDirection.Forward);
}//中途结束。
返回导航器;
}

Hi Akash,谢谢您的回复。我的经验是,它正在计算我的新行字符数,但注意到完全空白的行“”会导致FlowDocument比我的偏移量提前2个字符(每次换行后累积)。Alan+1,我有一个确切的问题——进行自定义解析时,高光偏移错误:-)
/// <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;
}