如何使用TextRange替换Run的字母?

时间:2015-02-01 11:48:13

标签: c# wpf textblock flowdocument

我是FlowDocuments的新手,似乎无法在任何地方找到它。

我创建了一个TextBlock,其中每个Inline都是一个只包含一个单词的Run。 (内联是在代码中创建的)。然后我使用TextRange替换Run中的一些字母。但是,不是替换Run的字符, TextRange似乎清空了Run并将字母附加到上一个Run。

(重要的是保留原始的TextBlock结构和原始的Run对象,因为我有事件绑定到它们。)

我做错了什么?什么是TextRange.Text =文本实际上在做什么?

感谢任何帮助。

实施例

  ---Before textrange--
<Run>
6||perrla
</Run>
<Run>
1||                       **NOTE THIS IS A SPACE IN THE RUN
</Run>
<Run>
5||nc/at
</Run>

--After textrange --- 
<Run>           **NOTE THE EMPTY RUN
</Run>
<Run>
5|| test    **NOTE HOW TEST IS APPENDED TO THE SPACE OF THE PREVIOUS RUN
</Run>
<Run>
5||nc/at
</Run>

产生上述结果的代码:

            string text = nw.Replace("\0", string.Empty);

            TextPointer s = StartInlineElement.GetInsertionPosition(LogicalDirection.Forward);
            TextPointer start = s.GetPositionAtOffset(StartIndex);
            TextPointer end = start.GetPositionAtOffset(Text.Length);

            var y = start.GetAdjacentElement(LogicalDirection.Backward);
            if (y != null)
            {
                do
                {
                    GetXaml((TextElement)y);
                    y = (y as Run).PreviousInline;
                } while (y != null);
            }

            THIS IS WRONG -- IT EMPTIES THE RUN AND APPENDS TO THE RUN
            BEFORE IT.
            TextRange tr = new TextRange(start, end);
            tr.Text = text;

            y = start.GetAdjacentElement(LogicalDirection.Forward);
            if (y != null)
            {
                do
                {
                    GetXaml((TextElement)y);
                    y = (y as Run).PreviousInline;
                } while (y != null);
            }
        }

GetXaml来自Microsoft(https://msdn.microsoft.com/en-us/library/system.windows.documents.textpointercontext(v=vs.110).aspx),我简单地将其修改为:

     void GetXaml(TextElement element)
    {
        // Position a "navigator" pointer before the opening tag of the element.
        TextPointer navigator = element.ElementStart;

        while (navigator.CompareTo(element.ElementEnd) < 0)
        {
            switch (navigator.GetPointerContext(LogicalDirection.Forward))
            {
                case TextPointerContext.ElementStart:
                    // Output opening tag of a TextElement
                    Console.WriteLine(String.Format("<{0}>", navigator.GetAdjacentElement(LogicalDirection.Forward).GetType().Name));
                    break;
                case TextPointerContext.ElementEnd:
                    // Output closing tag of a TextElement
                    Console.WriteLine(String.Format("</{0}>", navigator.GetAdjacentElement(LogicalDirection.Forward).GetType().Name));
                    break;
                case TextPointerContext.EmbeddedElement:
                    // Output simple tag for embedded element
                    Console.WriteLine(String.Format("<{0}>", navigator.GetAdjacentElement(LogicalDirection.Forward).GetType().Name));
                    break;
                case TextPointerContext.Text:
                    // Output the text content of this text run
                    Console.WriteLine(String.Format("{0}||{1}", navigator.GetTextRunLength(LogicalDirection.Forward),
                        navigator.GetTextInRun(LogicalDirection.Forward)));
                    break;
            }

            // Advance the naviagtor to the next context position.
            navigator = navigator.GetNextContextPosition(LogicalDirection.Forward);

        } 
    } 

1 个答案:

答案 0 :(得分:0)

似乎这是因为TextRange.Start将始终具有LogicalDirection或Backward。所以它将文本放在上一个元素中。

也许我针对特定情况的修复可以帮助您解决自己的问题:

if (this.Selection.Start.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart &&
    this.Selection.End.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd &&
    this.Selection.Start.Parent == this.Selection.End.Parent && this.Selection.Start.Parent is Run)
{
     ((Run)this.Selection.Start.Parent).Text = "NewText";
}