0

ここで見つけたいくつかのコードを使用して、フロー ドキュメント内のテキストの大文字と小文字を変更しようとしました。テキストは適切に変更されますが、すべての書式設定 (太字、斜体など) が失われ、ドキュメントを 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 がドキュメントの先頭にリダイレクトされているようです。

4

1 に答える 1

1

TextRange.Text を設定すると、最初に TextContainer (FlowDocument) にそのコンテンツを削除するように指示することによって、選択範囲が削除されます。そのコンテンツがたまたまスタイリング依存プロパティを持つ完全なインラインであった場合は、さようなら! したがって、スタイルのないテキストを取得するだけでなく、それを設定します

既存のインライン オブジェクトを維持したいので、FlowDocument 全体を反復処理してそれらを見つけ、そのテキスト プロパティを設定できます。

これは、段落のみをサポートし、選択範囲全体ですべてのインラインを検索するヘルパー メソッドです (常に Document.ContentStart と Document.ContentEnd を実行している場合、このロジックはより単純になります)。これを拡張して、必要に応じて (同様のパターンに従って) Lists、ListItems、および Hyperlinks の内部にインラインを含めることができます。

その後、これらの各インラインで Text プロパティを設定できるようになります。

    List<Inline> GetInlines(TextRange selection)
    {
        var inlines = new List<Inline>();

        foreach (var block in Document.Blocks.Where(x => selection.Start.CompareTo(x.ContentEnd) < 0 && selection.End.CompareTo(x.ContentStart) > 0))
        {
            var paragraph = block as Paragraph;
            if (paragraph != null)
            {
                inlines.AddRange(paragraph.Inlines.Where(x => selection.Start.CompareTo(x.ContentEnd) < 0 && selection.End.CompareTo(x.ContentStart) > 0));
            }
        }

return inlines;

編集: テキスト プロパティにアクセスするには、これらを Run または Span にキャストする必要があります。Inline を削除してこれらの型を取得することもできます (おそらく Run のみ)。

于 2016-04-26T17:44:07.700 に答える