textrange丢失textpointer参考?

时间:2016-04-26 09:06:36

标签: wpf flowdocument textrange

我一直在使用我发现here的一些代码来尝试更改流文档中的文本大小写。它会正确地更改文本,但是所有格式都会丢失(粗体,斜体等),当我将文档保存到XML文件时,所有文本都会在文档的第一次运行中结束,而所有其他的运行都是空的。

    private void ChangeCase()
    {
        TextPointer start = mergedDocument.ContentStart;
        TextPointer end = mergedDocument.ContentEnd;
        List<TextRange> textToChange = SplitToTextRanges(start, end);
        ChangeCaseToAllRanges(textToChange);
    }

    private List<TextRange> SplitToTextRanges(TextPointer start, TextPointer end)
    {
        List<TextRange> textToChange = new List<TextRange>();
        var previousPointer = start;
        for (var pointer = start; (pointer != null && pointer.CompareTo(end) <= 0); pointer = pointer.GetPositionAtOffset(1, LogicalDirection.Forward))
        {
            var contextAfter = pointer.GetPointerContext(LogicalDirection.Forward);
            var contextBefore = pointer.GetPointerContext(LogicalDirection.Backward);
            if (contextBefore != TextPointerContext.Text && contextAfter == TextPointerContext.Text)
            {
                previousPointer = pointer;
            }
            if (contextBefore == TextPointerContext.Text && contextAfter != TextPointerContext.Text && previousPointer != pointer)
            {
                textToChange.Add(new TextRange(previousPointer, pointer));
                previousPointer = null;
            }
        }
        textToChange.Add(new TextRange(previousPointer ?? end, end));
        return textToChange;
    }

    private void ChangeCaseToAllRanges(List<TextRange> textToChange)
    {
        Func<string, string> caseChanger;
        ComboBoxItem cbi = cb_Case.SelectedItem as ComboBoxItem;
        var textInfo = CultureInfo.CurrentUICulture.TextInfo;

        if (cbi == null || (string)cbi.Tag == "none")
        {
            return;
        }
        else if((string)cbi.Tag == "title")
        {
            caseChanger = (text) => textInfo.ToTitleCase(text);
        }
        else if ((string)cbi.Tag == "upper")
        {
            caseChanger = (text) => textInfo.ToUpper(text);
        }
        else if ((string)cbi.Tag == "lower")
        {
            caseChanger = (text) => textInfo.ToLower(text);
        }
        else
            return;

        foreach (var range in textToChange)
        {
            if (!range.IsEmpty && !string.IsNullOrWhiteSpace(range.Text))
            {
                System.Diagnostics.Debug.WriteLine("Casing: " + range.Text);
                System.Diagnostics.Debug.WriteLine("\tat: " + 
                    range.Start.GetOffsetToPosition(mergedDocument.ContentStart) +
                    " ," +
                    range.End.GetOffsetToPosition(mergedDocument.ContentStart));
                range.Text = caseChanger(range.Text);
            }
        }
    }

我看不出为什么这段代码无法正常工作的原因。看起来像textrange对象中的textpointers被重定向到文档的开头。

1 个答案:

答案 0 :(得分:1)

设置TextRange.Text时,它首先通过告诉TextContainer(FlowDocument)删除该内容来删除选择。如果该内容恰好是具有样式依赖属性的整个内联,那么再见!所以,它不仅会得到没有样式的文本,而且会设置它

由于您希望保留现有的内联对象,因此您可以遍历整个FlowDocument以查找它们并设置其文本属性。

这是一个辅助方法,它只支持Paragraphs并查找整个选择中的所有内联(如果你总是在做Document.ContentStart和Document.ContentEnd,这个逻辑要简单得多)。如果需要,可以扩展它以包含Lists,ListItems和Hyperlinks中的内联(通过遵循类似的模式)。

然后,您应该能够在每个内联上设置Text属性。

libs/log

编辑:您需要将这些转换为“运行”或“跨度”以访问文本属性。你甚至可以删除Inline并获取这些类型(可能只是Run)。