我一直在使用我发现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被重定向到文档的开头。
答案 0 :(得分:1)
设置TextRange.Text时,它首先通过告诉TextContainer(FlowDocument)删除该内容来删除选择。如果该内容恰好是具有样式依赖属性的整个内联,那么再见!所以,它不仅会得到没有样式的文本,而且会设置它
由于您希望保留现有的内联对象,因此您可以遍历整个FlowDocument以查找它们并设置其文本属性。
这是一个辅助方法,它只支持Paragraphs并查找整个选择中的所有内联(如果你总是在做Document.ContentStart和Document.ContentEnd,这个逻辑要简单得多)。如果需要,可以扩展它以包含Lists,ListItems和Hyperlinks中的内联(通过遵循类似的模式)。
然后,您应该能够在每个内联上设置Text属性。
libs/log
编辑:您需要将这些转换为“运行”或“跨度”以访问文本属性。你甚至可以删除Inline并获取这些类型(可能只是Run)。