DocumentViewer到RichTextBox绑定错误

时间:2012-03-10 14:56:53

标签: wpf binding richtextbox flowdocument documentviewer

我有一个RichTextBox和DocumentViewer的应用程序(放在TabControl中),我想做一些像“热预览”的东西。我已将DocumentViewer.Document属性绑定到RichTextBox.Document

结合:

<DocumentViewer Document="{Binding Document, Converter={StaticResource FlowDocumentToPaginatorConverter}, ElementName=mainRTB, Mode=OneWay}" />

这是转换器代码:

 public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            FlowDocument d = value as FlowDocument;
            DocumentPaginator pagin = ((IDocumentPaginatorSource)d).DocumentPaginator;
            FixedDocumentSequence result = null;
            Size s = new Size(793.700787402, 1122.519685039);
            pagin.PageSize = s;

            using (MemoryStream ms = new MemoryStream())
            {
                TextRange tr = new TextRange(d.ContentStart, d.ContentEnd);
                tr.Save(ms, DataFormats.XamlPackage);
                Package p = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite);
                Uri uri = new Uri(@"memorystream://doc.xps");
                PackageStore.AddPackage(uri, p);
                XpsDocument xpsDoc = new XpsDocument(p);
                xpsDoc.Uri = uri;
                XpsDocument.CreateXpsDocumentWriter(xpsDoc).Write(pagin);
                result = xpsDoc.GetFixedDocumentSequence();
            }
            return result;
        }

当我启动此应用程序时,一切正常,直到我使用DocumentViewer切换到选项卡。应用程序崩溃,我得到这样的例外:

  

无法在只写模式下执行读操作。

我做错了什么?是否可以进行此绑定?

1 个答案:

答案 0 :(得分:4)

错误信息确实令人困惑,并且原因并不是很明显。基本上你要过早关闭MemoryStream XpsDocument并且当DocumentViewer尝试读取文档时它不能,因为它是只写模式(因为流已关闭)。< / p>

解决方案是在完成查看文档后<= 1>},直到完成后才能立即关闭{/ 1}}。为此,我写了一个MemoryStream,返回XpsDocumentConverter

另外,由于您无法转换并显示单个XpsReference,因此您在XpsDocument中使用相同PackageStore的多个软件包时,您将不会遇到下一个问题。我在下面的实现中已经处理了这个问题。

Uri

public static XpsDocumentReference CreateXpsDocument(FlowDocument document) { // Do not close the memory stream as it still being used, it will be closed // later when the XpsDocumentReference is Disposed. MemoryStream ms = new MemoryStream(); // We store the package in the PackageStore Uri uri = new Uri(String.Format("pack://temp_{0}.xps/", Guid.NewGuid().ToString("N"))); Package pkg = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite); PackageStore.AddPackage(uri, pkg); XpsDocument xpsDocument = new XpsDocument(pkg, CompressionOption.Normal, uri.AbsoluteUri); // Need to force render the FlowDocument before pagination. // HACK: This is done by *briefly* showing the document. DocumentHelper.ForceRenderFlowDocument(document); XpsSerializationManager rsm = new XpsSerializationManager(new XpsPackagingPolicy(xpsDocument), false); DocumentPaginator paginator = new FixedDocumentPaginator(document, A4PageDefinition.Default); rsm.SaveAsXaml(paginator); return new XpsDocumentReference(ms, xpsDocument); } public class XpsDocumentReference : IDisposable { private MemoryStream MemoryStream; public XpsDocument XpsDocument { get; private set; } public FixedDocument FixedDocument { get; private set; } public XpsDocumentReference(MemoryStream ms, XpsDocument xpsDocument) { MemoryStream = ms; XpsDocument = xpsDocument; DocumentReference reference = xpsDocument.GetFixedDocumentSequence().References.FirstOrDefault(); if (reference != null) FixedDocument = reference.GetDocument(false); } public void Dispose() { Package pkg = PackageStore.GetPackage(XpsDocument.Uri); if (pkg != null) { pkg.Close(); PackageStore.RemovePackage(XpsDocument.Uri); } if (MemoryStream != null) { MemoryStream.Dispose(); MemoryStream = null; } } } 实施XpsReference所以请记得在其上调用IDisposable

此外,一旦解决了上述错误,您可能遇到的下一个问题就是内容无法按预期呈现。这是因为您需要克隆Dispose()并且未经过完整测量并安排布局传递。读 Printing BlockUIContainer to XpsDocument/FixedDocument关于如何解决这个问题。