c# - 如何创建 XPS 文档?

标签 c# .net xps xpsdocument

我想创建一个用于存储和打印的 XPS 文档。

在我的程序中创建 XPS 文档(例如,使用内部包含一些数据的简单网格)并传递它的最简单方法是什么?

最佳答案

这并不容易。但这是可以完成的。我的博客上有一些(遗憾的是,仍然有错误)示例代码和信息,用于在内存中创建文档。

这是我为测试而编写的一些代码,它封装了所有内容(它将 FixedPages 的集合写入内存中的 XPS 文档)。它包含用于将文档序列化为字节数组的代码,但您可以跳过该部分并只返回文档:

public static byte[] ToXpsDocument(IEnumerable<FixedPage> pages)
{
    // XPS DOCUMENTS MUST BE CREATED ON STA THREADS!!!
    // Note, this is test code, so I don't care about disposing my memory streams
    // You'll have to pay more attention to their lifespan.  You might have to 
    // serialize the xps document and remove the package from the package store 
    // before disposing the stream in order to prevent throwing exceptions
    byte[] retval = null;
    Thread t = new Thread(new ThreadStart(() =>
    {
        // A memory stream backs our document
        MemoryStream ms = new MemoryStream(2048);
        // a package contains all parts of the document
        Package p = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite);
        // the package store manages packages
        Uri u = new Uri("pack://TemporaryPackageUri.xps");
        PackageStore.AddPackage(u, p);
        // the document uses our package for storage
        XpsDocument doc = new XpsDocument(p, CompressionOption.NotCompressed, u.AbsoluteUri);
        // An xps document is one or more FixedDocuments containing FixedPages
        FixedDocument fDoc = new FixedDocument();
        PageContent pc;
        foreach (var fp in pages)
        {
            // this part of the framework is weak and hopefully will be fixed in 4.0
            pc = new PageContent();
            ((IAddChild)pc).AddChild(fp);
            fDoc.Pages.Add(pc);
        }
        // we use the writer to write the fixed document to the xps document
        XpsDocumentWriter writer;
        writer = XpsDocument.CreateXpsDocumentWriter(doc);
        // The paginator controls page breaks during the writing process
        // its important since xps document content does not flow 
        writer.Write(fDoc.DocumentPaginator);
        // 
        p.Flush();

        // this part serializes the doc to a stream so we can get the bytes
        ms = new MemoryStream();
        var writer = new XpsSerializerFactory().CreateSerializerWriter(ms);
        writer.Write(doc.GetFixedDocumentSequence());

        retval = ms.ToArray();
    }));
    // Instantiating WPF controls on a MTA thread throws exceptions
    t.SetApartmentState(ApartmentState.STA);
    // adjust as needed
    t.Priority = ThreadPriority.AboveNormal;
    t.IsBackground = false;
    t.Start();
    //~five seconds to finish or we bail
    int milli = 0;
    while (buffer == null && milli++ < 5000)
        Thread.Sleep(1);
    //Ditch the thread
    if(t.IsAlive)
        t.Abort();
    // If we time out, we return null.
    return retval;
}

注意蹩脚的线程代码。您不能在 MTA 线程上执行此操作;如果您在 STA 线程上,您也可以摆脱它。

关于c# - 如何创建 XPS 文档?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/352540/

相关文章:

c# - 方法 ‘Skip’ 仅支持 LINQ to Entities 中的排序输入。必须在方法 ‘OrderBy’ 之前调用方法 ‘Skip’

c# - ASP.NET 页面不应在提交时回发整个页面

.net - 非 UI 线程可以显示在屏幕上吗?

c# - 现有 XPS 文档中的数据绑定(bind)

WPF:流程文档转 PDF

c# - 我只需要处理特定选定表的列名

c# - 通用存储库和多种 PK 类型

c# - 如何用不同的颜色为 RichTextBox 中的不同单词着色?

c# - System.Double[*] 是什么意思