I'd like to create an XPS document for storing and printing.
What is the easiest way to create an XPS document (for example with a simple grid with some data inside) in my program, and to pass it around?
I'd like to create an XPS document for storing and printing.
What is the easiest way to create an XPS document (for example with a simple grid with some data inside) in my program, and to pass it around?
簡単なことは何もありません。しかし、それは可能です。メモリ内にドキュメントを作成するためのサンプルコードと情報がブログにあります(残念ながら、まだバグがあります)。
これは、すべてをカプセル化するテスト用に作成したコードです(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スレッドを使用している場合は、それも取り除くことができます。
.NET (v2 以降) で作業している場合は、WPF ビジュアルから有効な XPS ドキュメントを非常に簡単に生成できます。
例として、私のこのブログ投稿を見てください。
http://nixps.blogspot.com/2008/12/wpf-to-pdf.html
この例では、さらに処理を行う前に、WPF ビジュアルを作成し、それを XPS ファイルとして変換します。
.NET で作業していない場合、または XPS 出力をより詳細に制御したい場合は、ライブラリ ( NiXPS SDKなど) を使用することをお勧めします。XML 構造を自分で書き出す (そして適切なリソース管理を行うなど) よりも、コーディングがはるかに簡単で、エラーが発生しにくくなります。
All it is, is really XML. If you're comfortable working with XML files, you should have no problem working with XPS documents. Here's a simple tutorial I've used in the past to get me started: