清除块时WPF FlowDocument序列化错误

时间:2014-06-24 17:04:45

标签: wpf richtextbox flowdocument

我有一个自定义WPF类子类化RickTextBox,因此我可以为自定义数据对象添加内联显示。偶尔,我需要清除所有内容并从类列表中重建文档。但是,当我这样做时,我得到一个奇怪的错误:

doc.Blocks.Clear();  // <-- Error at this line
--------------------------------------------------------------
Additional information: Cannot serialize a generic type System.Collections.ObjectModel.ObservableCollection [System.Collections.ObjectModel.ObservableCollection ...

我真的不知道造成这种情况的原因。我没有做任何明确的序列化,因此WPF中的某些内容正在尝试。有人知道发生了什么吗?

仅供参考,这是我的对象的自定义内联显示(不用担心,代码隐藏工作最终将迁移到XAML)。我已将问题缩小到CellVMs,这是IEnumerable<IEnumerable<ReportTableCellViewModel>>

public class ReportTableRun : InlineUIContainer
    {
        public ReportTableRun() : this(null)
        {
        }

        public ReportTableRun(ReportTableViewModel table, DataTemplate cellTemplate=null) : base()
        {
            mTable = table;

            DynamicGrid grid = new DynamicGrid();
            grid.DefaultRowHeight = new GridLength(50);
            grid.DefaultColumnWidth = new GridLength(50);

            Binding bind0 = new Binding("CellVMs");
            bind0.Mode = BindingMode.OneWay;
            bind0.Source = mTable;
            BindingOperations.SetBinding(grid, DynamicGrid.ItemsSourceProperty, bind0);

            Binding bind3 = new Binding("RowSharedGroupNames");
            bind3.Mode = BindingMode.OneWay;
            bind3.Source = mTable;
            BindingOperations.SetBinding(grid, DynamicGrid.RowSharedSizeGroupNamesProperty, bind3);

            Binding bind4 = new Binding("ColumnSharedGroupNames");
            bind4.Mode = BindingMode.OneWay;
            bind4.Source = mTable;
            BindingOperations.SetBinding(grid, DynamicGrid.ColumnSharedSizeGroupNamesProperty, bind4);

            grid.ItemTemplate = cellTemplate;

            this.Child = grid;
        }

        private ReportTableViewModel mTable;
    }

这是重建文档的代码。

private void BuildDocument()
        {
            FlowDocument doc = Document;

            IEnumerable<IReportComponentViewModel> components = ReportTemplateViewModel.ComponentVMs;
            List<Paragraph> parList = new List<Paragraph>();
            Paragraph par = new Paragraph();
            parList.Add(par);
            foreach(IReportComponentViewModel c in components)
            {
                if (c is ReportTableViewModel)
                    par.Inlines.Add(new ReportTableRun(c as ReportTableViewModel, ReportTableCellTemplate));
            }

            doc.Blocks.Clear();
            foreach(Paragraph p in parList)
                doc.Blocks.Add(p);

        }

1 个答案:

答案 0 :(得分:0)

我遇到了同样的问题,无法清除BlockCollection,因为在两个地方使用FlowDocument:打印和预览。 Run和其他原子元素必须单独使用(使用一个父元素)。

因此,它通过在第二次添加之前复制内联元素来解决:

    Inline CopyInline(Inline iln)
    {
        string strType;
        Inline ilnRes;
        strType = (string)SpIntConst.GetLastElement(iln.GetType().ToString().Split('.'));
        switch (strType)
        {
            case "Run":
                ilnRes = new Run(((Run)iln).Text) { Style = iln.Style };
                break;
            case "Bold":
                Inline newInl;
                Bold boldSend;
                boldSend = iln as Bold;
                newInl = CopyInline(boldSend.Inlines.ElementAt(0));
                ilnRes = new Bold(newInl);
                break;
            case "InlineUIContainer":
                ilnRes = new InlineUIContainer(_gGraph.GraphImage);
                break;
            default:
                ilnRes = null;
                break;
        }
        return ilnRes;
    }
    Paragraph CopyParagraph(Paragraph par)
    {
        Paragraph parRes = new Paragraph();
        foreach (Inline iln in par.Inlines)
            parRes.Inlines.Add(CopyInline(iln));
        return parRes;
    }
    TableCell CopyTableCell(TableCell tblCell)
    {
        TableCell tblCellRes = new TableCell() { Style = tblCell.Style };
        return tblCellRes;
    }
    TableRow CopyTableRow(TableRow tr)
    {
        TableRow trRes = new TableRow();
        foreach (TableCell tblCell in tr.Cells)
            trRes.Cells.Add(CopyTableCell(tblCell));
        return trRes;
    }
    TableRowGroup CopyTableRowGroup(TableRowGroup trg)
    {
        TableRowGroup trgRes = new TableRowGroup();
        foreach (TableRow tr in trg.Rows)
            trgRes.Rows.Add(CopyTableRow(tr));
        return trgRes;
    }
    Table CopyTable(Table tbl)
    {
        Table tblRes = new Table();
        for (int i = 0; i < tbl.Columns.Count; i++)
            tblRes.Columns.Add(new TableColumn() { Width = tbl.Columns[i].Width });
        foreach (TableRowGroup trg in tbl.RowGroups)
            tblRes.RowGroups.Add(CopyTableRowGroup(trg));
        return tblRes;
    }
    Block CopyBlock(Block bl)
    {
        string type;
        Block blRes;
        type = (string)SpIntConst.GetLastElement(bl.GetType().ToString().Split('.'));
        switch (type)
        {
            case "Paragraph":
                Paragraph par = bl as Paragraph;
                blRes = CopyParagraph(par);
                break;
            case "Table":
                Table tbl = bl as Table;
                blRes = CopyTable(tbl);
                break;
            default:
                blRes = null;
                break;
        }
        return blRes;
    }
    FlowDocument CopyDoc(FlowDocument fd)
    {
        FlowDocument fdRes = new FlowDocument()
        {
            PageWidth = fd.PageWidth,
            PageHeight = fd.PageHeight,
            PagePadding = fd.PagePadding
        };
        foreach (Block bl in fd.Blocks)
            fdRes.Blocks.Add(CopyBlock(bl));
        return fdRes;
    }
    private void btnPreview_Click(object sender, RoutedEventArgs e)
    {
        SetParams();
        PrintPreview pp = new PrintPreview(CopyDoc(_doc), _mw.CurrHelpPath);
        ...
    }