Search code examples
wpflistflowdocument

Copy list to Flowdocument messes up 1st listitem


I'm writing an extension that allows a user to merge multiple notes into a single note and provides some features like adding periods onto the end of the original notes. I'm writing the code that copies the parts of one flowdocument to another and inserts the periods as it goes.

I am having problems copying lists to the new document. For some reason the first listitem always ends up in the paragraph PREceeding the list instead of in the list.

My code:

foreach (Block b in tempDoc.Blocks)
                {
                    thisBlock++;
                    if (b is List)
                    {
                        pkhCommon.WPF.Helpers.AddBlock(b, mergedDocument);
                    }
                    else
                    {
                        Paragraph p = b as Paragraph;
                        foreach (Inline inl in p.Inlines)
                        {
                            if (!(inl is LineBreak))
                                pkhCommon.WPF.Helpers.AddInline(inl, mergedDocument);
                        }
                        if (thisElement != lastElement || thisBlock != lastBlock)
                            if ((bool)cb_AddPeriods.IsChecked)
                                pkhCommon.WPF.Helpers.AddInline(new Run(". "), mergedDocument);
                            else
                                pkhCommon.WPF.Helpers.AddInline(new Run(" "), mergedDocument);
                    }
                }

Below is the function to merge the blocks. The AddIline function works the same way.

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

I can't understand why the flowdocument is deciding to put the listitem into the PREceeding paragraph.


Solution

  • Adding a block to the FlowDocument's block collection should put it at the end.
    This works for for me.

    Document.Blocks.Add(blockToAdd);
    

    You are doing the save/load to clone the block right? Can you just try adding it this way at the end instead of inserting in the text range?

    var blockToAdd = XamlReader.Load(stream) as Block;
    Document.Blocks.Add(blockToAdd);
    

    Part of your issue is that after saving, the stream position is at the end of the stream, so there is nothing to Load. There is probably a better way to fix this but I am out of time to help. Setting position to 0 feels wrong. This has no parse exception.

            var from = new System.Windows.Documents.List(new ListItem(new Paragraph(new Run("Blah"))));
            using (var stream = new MemoryStream())
            {
                System.Windows.Markup.XamlWriter.Save(from, stream);
                stream.Position = 0;
                Block b = System.Windows.Markup.XamlReader.Load(stream) as Block;
            }