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

Rob*_*ney 10 c# wpf richtextbox flowdocument textrange

我正在构建一个应用程序,它需要允许用户从另一个插入RichTextBox当前插入位置的文本中插入文本.在运行这种技术之前,我花了很多时间搞砸了FlowDocument对象模型 - source并且target都是FlowDocuments:

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);
}
Run Code Online (Sandbox Code Playgroud)

这非常有效.

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

我认为对此的答案很可能是最终检查目标是否完全由单个块组成,如果是,则TextRange在保存之前将块设置为块内容的开头和结尾到溪边.

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

Ray*_*rns 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); 
Run Code Online (Sandbox Code Playgroud)

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

一旦你做出这个改变,你可能会发现另一个可能或可能不是你的问题:你的示例代码使用document.ContentStartdocument.ContentEnd.如果这是你的实际代码,你会发现,从任何范围document.ContentStartdocument.ContentEnd一定由全段,所以复制它总是插在插入的最后一个段落休息.如果这是一个问题,请使用类似RichTextBox.Selection(如果这是UI驱动)或用于在隐式段落标记之前TextPointer备份ContentEnd,例如:

var tr = new TextRange(document.ContentStart,
                       document.ContentEnd.GetInsertionPosition(
                                                  LogicalDirection.Backward));
Run Code Online (Sandbox Code Playgroud)