2012-04-30 4 views
0

Shift + F3を使用しているようなRichTextBoxの "変更ケース"機能を実装しています。それが行うのは、lower-> upper-> titleの場合の切り替えです。これは、必要な文字列にアクセスすると非常に簡単です。WPF Flowdocument "ケースの変更"機能

私の質問は、文字列内に含まれている可能性のある埋め込み要素(フォーマットを失うことは問題ありません)を失うことなく、flowdocumentの文字列をどのように変更するか(最初に見つけてください)です。 単語と同じですが、2つのケースでこの機能が必要です:

1)マウスで選択したテキスト。私は単純に試しました

this.Selection.Text = newText; 

しかし、もちろん埋め込まれた要素が失われました。

2)キャレット位置の最後の単語。任意の非テキスト要素は、単語の区切りである、しかし1つのワードが

"He<weird formatting begin>ll<weird formatting end>o". 

答えて

0

SOLUTION

それはMS WORDシフト+ F3の挙動を模倣するこの方法することができます。ごく少数のケースで問題が発生するのは、カレットがその位置を保持する代わりに、単語の先頭に移動することだけです。私は、EditingCommands.MoveLeftByWord.Execute(null、this);という短い睡眠があると思います。これを修正するだろうが、これは汚れたハックであり、私はより良いソリューションを見つけようとしている。

private void ChangeCase() 
    { 
     try 
     { 
      TextPointer start; 
      TextPointer end; 
      FindSelectedRange(out start, out end); 
      List<TextRange> textToChange = SplitToTextRanges(start, end); 
      ChangeCaseToAllRanges(textToChange); 
     } 
     catch (Exception ex) 
     { 
      mLog.Error("Change case error", ex); 
     } 


    } 

    private void FindSelectedRange(out TextPointer start, out TextPointer end) 
    { 
     if (!this.Selection.IsEmpty) 
     { 
      start = this.Selection.Start; 
      end = this.Selection.End; 
     } 
     else 
     { 
      end = this.CaretPosition; 
      EditingCommands.MoveLeftByWord.Execute(null, this); 
      start = this.CaretPosition; 
      this.CaretPosition = end; 

     } 
    } 

    private static List<TextRange> SplitToTextRanges(TextPointer start, TextPointer end) 
    { 
     List<TextRange> textToChange = new List<TextRange>(); 
     var previousPointer = start; 
     for (var pointer = start; 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) 
    { 
     var textInfo = (mCasingCulture ?? CultureInfo.CurrentUICulture).TextInfo; 
     var allText = String.Join(" ", textToChange.Select(x => x.Text).Where(x => !string.IsNullOrWhiteSpace(x))); 
     Func<string, string> caseChanger = GetConvertorToNextState(textInfo, allText); 
     foreach (var range in textToChange) 
     { 
      if (!range.IsEmpty && !string.IsNullOrWhiteSpace(range.Text)) 
      { 
       range.Text = caseChanger(range.Text); 
      } 
     } 
    } 

    private static Func<string, string> GetConvertorToNextState(TextInfo textInfo, string allText) 
    { 
     Func<string, string> caseChanger; 
     if (textInfo.ToLower(allText) == allText) 
     { 
      caseChanger = (text) => textInfo.ToTitleCase(text); 
     } 
     else if (textInfo.ToTitleCase(textInfo.ToLower(allText)) == allText) 
     { 
      caseChanger = (text) => textInfo.ToUpper(text); 
     } 
     else 
     { 
      caseChanger = (text) => textInfo.ToLower(text); 
     } 
     return caseChanger; 
    } 
関連する問題