C# 如何创建XPS文档?

C# 如何创建XPS文档?,c#,.net,xps,xpsdocument,C#,.net,Xps,Xpsdocument,我想创建一个用于存储和打印的XPS文档 在我的程序中创建XPS文档(例如,使用一个包含一些数据的简单网格)并传递它的最简单方法是什么?它实际上就是XML。如果您对使用XML文件感到满意,那么使用XPS文档应该没有问题。这里有一个简单的教程,我在过去使用过,让我开始: 这件事可不容易。但这是可以做到的。我的博客上有一些(遗憾的是,仍然有bug)示例代码和信息,用于在内存中创建文档 下面是我为测试编写的一些代码,这些代码封装了所有内容(它将一组固定页面写入内存中的XPS文档)。它包括将文档序列化为字

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


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

它实际上就是XML。如果您对使用XML文件感到满意,那么使用XPS文档应该没有问题。这里有一个简单的教程,我在过去使用过,让我开始:


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

下面是我为测试编写的一些代码,这些代码封装了所有内容(它将一组固定页面写入内存中的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;
}
publicstaticbyte[]ToXpsDocument(IEnumerable页面)
{
//XPS文档必须在STA线程上创建!!!
//注意,这是测试代码,所以我不关心如何处理内存流
//你将不得不更加关注他们的寿命。你可能不得不这么做
//序列化xps文档并从包存储中删除包
//在处理流之前,防止抛出异常
字节[]retval=null;
线程t=新线程(新线程开始(()=>
{
//一个内存流备份我们的文档
MemoryStream ms=新的MemoryStream(2048);
//包包含文档的所有部分
Package p=Package.Open(ms,FileMode.Create,FileAccess.ReadWrite);
//包存储管理包
Uri u=新的Uri(“pack://TemporaryPackageUri.xps");
PackageStore.AddPackage(u,p);
//该文档使用我们的包进行存储
XpsDocument doc=新XpsDocument(p,CompressionOption.NotCompressed,u.AbsoluteUri);
//xps文档是一个或多个包含固定页面的固定文档
FixedDocument fDoc=新的FixedDocument();
页面内容pc;
foreach(页面中的变量fp)
{
//框架的这一部分很薄弱,有望在4.0中得到修复
pc=新页面内容();
(IAddChild)pc.AddChild(fp);
fDoc.页面添加(pc);
}
//我们使用writer将固定文档写入xps文档
XpsDocumentWriter;
writer=XpsDocument.CreateXpsDocumentWriter(doc);
//分页器控制写入过程中的分页符
//它很重要,因为xps文档内容不流动
writer.Write(fDoc.DocumentPaginator);
// 
p、 冲洗();
//这一部分将文档序列化为流,以便我们可以获取字节
ms=新内存流();
var writer=new XpsSerializerFactory().CreateSerializerWriter(ms);
writer.Write(doc.GetFixedDocumentSequence());
retval=ms.ToArray();
}));
//在MTA线程上实例化WPF控件会引发异常
t、 SetApartmentState(ApartmentState.STA);
//根据需要进行调整
t、 优先级=线程优先级。高于正常值;
t、 IsBackground=false;
t、 Start();
//~5秒后完成,否则我们保释
int milli=0;
while(buffer==null&&milli++<5000)
睡眠(1);
//甩掉线
如果(t.IsAlive)
t、 中止();
//如果超时,则返回null。
返回返回;
}

请注意糟糕的线程代码。不能在MTA线程上执行此操作;如果您使用的是STA线程,您也可以摆脱它。

如果您使用的是.NET(v2或更高版本),您可以非常轻松地从WPF visual生成有效的XPS文档

例如,请看我的这篇博文:

在本例中,我创建了一个WPF visual,并将其转换为XPS文件,然后再进行进一步处理


如果您不在.NET中工作,或者希望对XPS输出进行更多控制,那么我建议您为此使用库(如)。与自己编写XML构造(并进行适当的资源管理等)相比,编写XML构造代码要容易得多,出错率也要低得多。

奇怪。但肯定有一种方法可以做到。除非您理解XPS文档规范,否则我不会建议您这样做。创建一个奇怪的XML文档,压缩成zip?不完全是我在写《最简单的方法》时想的:)这篇教程在哪里还可用吗?博客不见了——但我很感兴趣……有趣的线程超时代码——你为什么不使用t.Join(5000)呢?我仍在试图理解其余的:)这段代码在.NET4中编译/工作吗?我看到变量“writer”在同一范围内定义了两次,并且FixedPage集合中的项将从创建它们的线程以外的线程访问。我尝试了这段代码,但出现错误:参数的类型为意外的“System.String”。预期类型为“System.Windows.Documents.FixedPage”。参数名称:((IAddChild)pc.AddChild(fp)行中的值;我如何解决这个问题?@sudha您试图传入一个字符串而不是一个固定页面。如果你不能找出问题出在哪里,我就帮不了你。@Sudha是的,这是一个程序员方便的时候。我建议你雇一个。你的博客链接不起作用,也许你可以复制答案中的代码示例?复制并粘贴URL而不是跟随它,只是href错误。它完美地展示了如何从WPF visual创建XPS文件。WPF(Windows Presentation Foundation)直到.NET Framework 3.0(使用Windows Vista)才发布。注意:NiXPS SDK需要花钱(750欧元是目前最便宜的软件包)NiXPS目前似乎已经死了。主页显示一个空白页,最近一次更新新闻是在2010年()这也可能有帮助: