Я создаю приложение, которое должно позволить пользователю вставлять текст от одного RichTextBox
в текущей позиции курсора в другом. Я провел много времени, валяя дурака с FlowDocument
объектная модель перед натыканием на эту технику - source
и target
оба 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
море загрязнения темных тайн мне. Я могу стать экспертом в нем, если я имею к (на Dostoevsky: "Человек является животным, которое может привыкнуть к чему-либо".), но если кто-то уже понял это и может сказать мне, как сделать это, это сделало бы мою жизнь намного легче.
Ваша непосредственная проблема заключается в том, что вы используете 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.Выделение
(если это управляется пользовательским интерфейсом) или используйте TextPointer
для резервного копирования ContentEnd
до неявного знака абзаца, например:
var tr = new TextRange(document.ContentStart,
document.ContentEnd.GetInsertionPosition(
LogicalDirection.Backward));