Работа с FlowDocument

WPF
  1. 5 года назад

    Добрый день!
    Возникла такая ситуация: необходимо брать содержимое из, скажем, FlowDocument1 и вставлять в начало документа FlowDocument2. Казалось бы плевое дело, выделил все блоки в FlowDocument и воткнул в начало коллекции блоков в FlowDocument2.. но видимо я неверно понимаю, как эти коллекции функционируют.. потому что если и получается добиться желаемого, то только через одно место.
    собственно, хотелось чтобы выглядело все следующим образом:

    Block firstBlock = viewer.Document.Blocks.FirstBlock; // взяли первый блок и вставили все блоки перед ним, с виду вполне неплохое решение
    foreach (Block block in rtb.Document.Blocks)
          viewer.Document.Blocks.InsertBefore(firstBlock, block);

    но не тут то было.. внезапно вылетает эксепшн "Вставка элемента "BlockCollection" в дерево невозможна, так как элемент уже является дочерним объектом дерева.". хотя содержимое всех блоков разное - не пойму как они сравниваются

    Работать все соглашается при следующем решении.. и оно по-моему просто ужасное

    List<Block> bx = new List<Block>();
    foreach (Block bl in rtb.Document.Blocks)
          bx.Add(bl);
    
    FlowDocument newDocument = new FlowDocument();
    newDocument.Blocks.AddRange(bx);
    
    bx.Clear();
    foreach (Block bl in viewer.Document.Blocks)
          bx.Add(bl);
    
    newDocument.Blocks.AddRange(bx);
    viewer.Document = newDocument;

    еще не пойму, в чем проблема со следующим кодом.. из-за этого приходится блоки собирать сначала в коллекцию, потом уже из коллекции добавлять в документ

     viewer.Document.Blocks.AddRange(rtb.Document.Blocks); //exeption Семейство изменено, выполнение операции перечисления невозможно.

    В общем, подскажите, пожалуйста, как хотя бы обойтись без создания нового FlowDocument, буду очень благодарен!
    А если еще будет объяснение, почему все так нелогично (с виду) работает, будет вообще чудесно

  2. Alexandr_Erohin

    Oct 27 Администратор

    "Вставка элемента "BlockCollection" в дерево невозможна, так как элемент уже является дочерним объектом дерева."

    Определите отдельный статический метод (вместо InsertBefore) который будет получать объект Block, парсить его и записывать во FLowDocument. Подозреваю что вырывать Block из другого документа нельзя, поэтому и вылазит исключение. Вот пример такого метода:

    public static void AddBlock(Block from, FlowDocument to)
    {
                if (from != null)
                {
                    TextRange range = new TextRange(from.ContentStart, from.ContentEnd);
                    MemoryStream stream = new MemoryStream();
                    System.Windows.Markup.XamlWriter.Save(range, stream);
                    range.Save(stream, DataFormats.XamlPackage);
                    TextRange textRange2 = new TextRange(to.ContentStart, to.ContentStart);
                    textRange2.Load(stream, DataFormats.XamlPackage);
                }
     }

    А вот как его использовать (если определен в классе MainWindow):

    Block firstBlock = viewer.Document.Blocks.FirstBlock;
    
    foreach (Block block in rtb.Document.Blocks)
     {
                    MainWindow.AddBlock(block, viewer.Document);
    }
  3. Спасибо за ответ! Я правда надеялся обойтись без парсера, но думаю, это действительно лучше, чем коллеции с блоками создавать
    Можно даже чуть укоротить метод

    public static void AddBlocks(FlowDocument from, FlowDocument to)
    {
        if (from != null)
        {
            TextRange range = new TextRange(from.ContentStart, from.ContentEnd);
            using (MemoryStream stream = new MemoryStream())
            {
                System.Windows.Markup.XamlWriter.Save(range, stream);
                range.Save(stream, DataFormats.XamlPackage);
                range = new TextRange(to.ContentStart, to.ContentStart);
                range.Load(stream, DataFormats.XamlPackage);
            }
        }
    }

или зарегистрируйтесь чтобы ответить