2016-04-26 8 views
0

フロードキュメントのテキストの大文字と小文字を変更しようとすると、私は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

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

既存のインラインオブジェクトを保持したいので、FlowDocument全体を繰り返し検索し、テキストプロパティを設定できます。

ここでは、段落のみをサポートし、選択範囲全体のすべてのインラインを見つけるヘルパーメソッドです(このロジックは、Document.ContentStartとDocument.ContentEndを常に実行していると非常に簡単です)。これを拡張して、必要に応じて(同様のパターンに従って)List、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; 

編集:テキストプロパティにアクセスするには、これらをランまたはスパンにキャストします。インラインを削除してこれらのタイプを取得することもできます(おそらく実行のみ)。

+0

それがあります。ありがとう! –

関連する問題