WPF Flowdocument“更改案例”function

我正在为我的RichTextBox实现一个“更改案例”function,例如word with Shift + F3。 所有这一切都是在lower-> upper-> title case之间切换,一旦我访问了我需要的字符串,这非常简单。

我的问题是,如何在flowdocument中更改(并首先找到它)一个字符串,而不会丢失任何可能包含在字符串中的嵌入元素(丢失格式不是问题)。 与单词相同,我需要此function2个案例:

1)鼠标选择的文本。 我试过简单

this.Selection.Text = newText; 

但那当然失去了我的嵌入元素。

2)插入位置之前的最后一个字。 任何非文本元素都是单词分隔符,但也可以是一个单词

 "Hello". 

这样它就模仿了MS WORD Shift + F3的行为。 唯一的问题是,在极少数情况下发生的是将carret移动到单词开头而不是保持其位置。 我想在EditingCommands.MoveLeftByWord.Execute(null,this)之后短暂睡眠; 会解决这个问题,但这将是一个肮脏的黑客,我试图找到一个更好的解决方案。

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