如何将内联内容从一个FlowDocument插入另一个?

时间:2010-03-03 21:07:03

标签: c# wpf richtextbox flowdocument textrange

我正在构建一个应用程序,它需要允许用户在另一个插入当前插入位置的RichTextBox处插入文本。在运行此技术之前,我花了很多时间来讨论FlowDocument的对象模型 - sourcetarget都是FlowDocument S:

using (MemoryStream ms = new MemoryStream())
{
    TextRange tr = new TextRange(source.ContentStart, source.ContentEnd);                    
    tr.Save(ms, DataFormats.Xaml);
    ms.Seek(0, SeekOrigin.Begin);
    tr = new TextRange(target.CaretPosition, target.CaretPosition);
    tr.Load(ms, DataFormats.Xaml);
}

这非常有效。

我现在遇到的唯一问题是它总是将源插入一个新段落。它打破插入符号的当前运行(或其他),插入源,并结束段落。如果源实际上一个段落(或多个段落),那是合适的,但如果它只是(比方说)一行文本则不合适。

我认为对此的答案可能最终是检查目标以确定它是否完全由单个块组成,如果是,则将TextRange设置为指向开头并且块保存到流中之前的内容结束。

FlowDocument的整个世界对我来说是一片黑暗神秘的海洋。如果必须的话,我可以成为它的专家(根据陀思妥耶夫斯基:“人是可以适应任何事物的动物。”),但如果有人已经想出这个并且可以告诉我该怎么做它会让我生活更容易。

1 个答案:

答案 0 :(得分:13)

您当前的问题是您使用的是TextFormat.Xaml而不是TextFormat.XamlPackage

控制在合并文档时是否合并行的属性是Section.HasTrailingParagraphBreakOnPaste属性。加载或保存XamlPackage文本格式时,此属性仅有效。使用Xaml文本格式时,Save()期间会忽略该属性,Load()期间会忽略该属性。

所以简单的解决方法是简单地更改加载和保存调用:

tr.Save(ms, DataFormats.XamlPackage); 
ms.Seek(0, SeekOrigin.Begin); 
tr = new TextRange(target.CaretPosition, target.CaretPosition); 
tr.Load(ms, DataFormats.XamlPackage); 

请注意,这也解决了您最终会遇到的另一个问题:使用DataFormats.Xaml时,嵌入式位图将无法正确复制,因为无处放置图像位。使用DataFormats.XamlPackage构建了整个包,因此位图和其他包项都可以正常使用。

进行此更改后,您可能会发现另一个可能或可能不适合您的事实:您的示例代码使用document.ContentStartdocument.ContentEnd。如果这是您的实际代码,您会发现从document.ContentStartdocument.ContentEnd的任何范围必然包含完整的段落,因此复制它将始终在插入结束时插入段落。如果这是一个问题,请使用RichTextBox.Selection(如果这是UI驱动的)或使用TextPointerContentEnd备份到隐式段落标记之前,例如:

var tr = new TextRange(document.ContentStart,
                       document.ContentEnd.GetInsertionPosition(
                                                  LogicalDirection.Backward));