将WPF(XAML)控件转换为XPS文档。

50
我可以将现有的WPF(XAML)控件进行数据绑定,然后将其转换为XPS文档,并使用WPF XPS文档查看器显示和打印吗?如果可以,如何实现?如果不行,那么我应该如何在WPF中使用XPS/PDF等来进行报表生成呢?基本上,我想要将现有的WPF控件进行数据绑定,以获取其中的有用数据,然后使它可打印和可保存给最终用户。理想情况下,文档的创建应该是在内存中完成的,除非用户明确地保存了该文档,否则不需要在磁盘上进行操作。这种方案可行吗?

http://msdn.microsoft.com/en-us/library/system.windows.xps.visualstoxpsdocument.aspx - Logan Capaldo
1个回答

74

在研究许多不同的示例之后,我发现它们都非常复杂,需要使用文档编写器、容器、打印队列和打印票据,然而我找到了Eric Sink关于WPF中的打印的文章。
这篇文章提供的简化代码仅有10行。

public void CreateMyWPFControlReport(MyWPFControlDataSource usefulData)
{
  //Set up the WPF Control to be printed
  MyWPFControl controlToPrint;
  controlToPrint = new MyWPFControl();
  controlToPrint.DataContext = usefulData;

  FixedDocument fixedDoc = new FixedDocument();
  PageContent pageContent = new PageContent();
  FixedPage fixedPage = new FixedPage();

  //Create first page of document
  fixedPage.Children.Add(controlToPrint);
  ((System.Windows.Markup.IAddChild)pageContent).AddChild(fixedPage);
  fixedDoc.Pages.Add(pageContent);
  //Create any other required pages here

  //View the document
  documentViewer1.Document = fixedDoc;
}

我的示例相当简单,它不包括页面大小和方向,其中包含一组完全不符合预期的问题。 也没有任何保存功能,因为微软似乎忘记在文档查看器中包含保存按钮。

保存功能相对简单(也来自Eric Sinks文章)

public void SaveCurrentDocument()
{
 // Configure save file dialog box
 Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
 dlg.FileName = "MyReport"; // Default file name
 dlg.DefaultExt = ".xps"; // Default file extension
 dlg.Filter = "XPS Documents (.xps)|*.xps"; // Filter files by extension

 // Show save file dialog box
 Nullable<bool> result = dlg.ShowDialog();

 // Process save file dialog box results
 if (result == true)
 {
   // Save document
   string filename = dlg.FileName;

  FixedDocument doc = (FixedDocument)documentViewer1.Document;
  XpsDocument xpsd = new XpsDocument(filename, FileAccess.ReadWrite);
  System.Windows.Xps.XpsDocumentWriter xw = XpsDocument.CreateXpsDocumentWriter(xpsd);
  xw.Write(doc);
  xpsd.Close();
 }
}

答案是肯定的,你可以取一个现有的WPF (XAML)控件,将其数据绑定,并将其转换为XPS文档 - 这并不难。


1
请问您能提供MyWPFControl和MyWPFControlDataSource的定义吗?如果没有它们,示例代码就毫无意义了,而且Sinks文章中好像也没有包含它们。 - Unknown Coder
7
Jim,MyWPFControl指的是任何希望在XPS文档中呈现为页面的控件(自定义、组合、独立或其他类型)。而MyWPFControlDataSource则是你想要绑定到该控件上的任何数据(通常是一个ViewModel)。这个例子故意留下了一般形式,以便于任何人查看时都能获益,而不仅仅是那些希望将特定控件渲染到XAML的人。 - Scott
1
太棒了!我已经花了整整一周的时间寻找这个答案,其他的例子都没有这个简单和有效!如果可以的话,我会给你点赞两次!只有一件事;在我的搜索过程中,我发现IAddChild已经过时了,应该“将ContentPropertyAttribute应用于自定义类”。http://msdn.microsoft.com/en-us/library/system.windows.markup.iaddchild.aspx虽然这个解决方案仍然有效,但是这意味着什么,未来如何实施? - Jason Ebersey
2
这是否适用于大型WPF控件,还是我需要添加一些额外的代码来进行多页分页? - mayur Rathod
1
@Scott,我正在寻找一种方法来创建类似于这样的东西,但需要自动分页(无需手动创建页面并将它们添加到“FixedDocument”中),有没有办法实现? - Rizki Pratama
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接