Как использовать TextRange для замены букв Run?

Я совершенно новичок в FlowDocuments и нигде не могу найти это.

Я создал TextBlock, где каждый Inline представляет собой Run, содержащий ровно одно слово. (Встроенные строки создаются в коде). Затем я использую TextRange, чтобы заменить некоторые буквы в Run. Но вместо замены символов Run TextRange, похоже, очищает Run и добавляет буквы к предыдущему Run.

(Важно сохранить исходную структуру TextBlock с исходными объектами Run, поскольку к ним привязаны события.)

Что я делаю неправильно? И что на самом деле делает TextRange.Text = 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);

        } 
    } 

person Alan Wayne    schedule 01.02.2015    source источник


Ответы (1)


Похоже, это вызвано тем, что 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";
}
person Jf Beaulac    schedule 10.04.2015