如何将一个FlowDocument中的行内内容插入到另一个FlowDocument中?

10

我正在构建一个应用程序,需要允许用户在另一个RichTextBox的当前插入点处插入来自另一个文本框的文本内容。我花了很多时间在FlowDocument的对象模型上纠结,直到找到这个技巧——sourcetarget都是FlowDocument

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);
}

这个功能运行得非常好。

我现在唯一遇到的问题是它总是将源代码作为新段落插入。它会在插入源代码时打断当前运行(或任何其他东西),然后结束段落。如果源代码只是一行文本,而不是(比如)一整段文本,那么这样做就不合适了。

我认为解决方法可能是检查目标是否完全由一个块组成,如果是,则在保存到流之前将设置为指向块内容的开头和结尾。

FlowDocument 的整个世界对我来说都是一个充满神秘的海洋。如果必须要的话,我可以成为它的专家(如同多斯托耶夫斯基所说:“人是可以适应任何事情的动物。”),但如果有人已经解决了这个问题并且可以告诉我如何做到这一点,那么我的生活将变得轻松得多。

1个回答

14

你面临的直接问题是你正在使用 TextFormat.Xaml 而不是 TextFormat.XamlPackage

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

所以简单的解决方法就是改变 Load 和 Save 呼叫:

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.ContentStart 和 document.ContentEnd。如果这是您的实际代码,您将发现从 document.ContentStart 到 document.ContentEnd 的任何范围都必然由完整段落组成,因此复制它将始终在插入末尾插入段落换行符。 如果这是个问题,请使用类似 RichTextBox.Selection(如果这是UI驱动)的内容,或者使用 TextPointer 将 ContentEnd 向前移动到隐式段落标记之前,例如:
var tr = new TextRange(document.ContentStart,
                       document.ContentEnd.GetInsertionPosition(
                                                  LogicalDirection.Backward));

我还需要一段时间才能真正去检查这个是否正确,但看起来你已经经历了我现在所处的情况,我很感激你提供的信息。 - Robert Rossney

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接