当将FixedDocument序列化为XPS时,我有时会FileFormatException告诉我字体的格式(我假设)不符合预期的文件格式规范(请参阅下面的例外).
神秘的部分是:
有人知道为什么会发生这种情况(特别是为什么它不会一直发生但只是在不可预测的时间间隔内)?
遵循最小可重复性示例将在每次运行时触发异常约4至5次(在我的Windows 10计算机上,发生在.NET 4,4.6.1等):
private void TestXpsSerialization(object a)
{
for (int i = 0; i < 400; ++i)
{
TextBlock block = new TextBlock
{
Text = "Test",
FontFamily = new FontFamily("Segoe UI"),
FontStyle = FontStyles.Italic,
FontWeight = FontWeights.Bold,
Background = null,
FontSize = 12
};
FixedDocument fixedDoc = new FixedDocument();
PageContent pageContent = new PageContent();
FixedPage fixedPage = new FixedPage();
fixedPage.Children.Add(block);
((IAddChild) pageContent).AddChild(fixedPage);
fixedDoc.Pages.Add(pageContent);
using (MemoryStream documentStream = new MemoryStream())
{
string …Run Code Online (Sandbox Code Playgroud) 我想创建一个用于存储和打印的XPS文档.
在我的程序中创建XPS文档的最简单方法是什么(例如,在其中包含一些带有一些数据的简单网格),并传递它?
这里的想法是我有一个DocumentPaginator,我想与XpsDocumentWriter或PrintDialog一起使用,因为两者都可以选择打印给定的分页器.当我使用其中任何一个,即XpsDocumentWriter.Write [Async]或PrintDialog.PrintDocument时,通过GetPage与GetPageAsync加入paginator,我在派生的DocumentPaginator类中重写了它.
除了手动使用分页器并将Visuals提供给文档编写器之外,有没有办法触发DocumentPaginator的Asyc函数的使用?
我创建了一个.NET Windows服务,它执行某些操作并生成报告.这些报告是我保存在某个目录中的XPS文档.
熟悉WPF,我选择创建报告的方法是实例化a System.Windows.Documents.FixedDocument,FixedPage根据需要添加包含内容的对象.
我的问题是服务内存使用量随着时间的推移而上升和上升.
起初,我严格检查了我的代码,确保所有一次性物品都被丢弃等,以及其他明显的内存泄漏候选者,但仍然存在问题.然后我使用CLR Profiler详细查看服务的内存使用情况.
我发现,随着服务生成这些FixedDocument报告,并将其保存为XPS文件,所有相关的各种UI元素FixedDocument的对象(Dispatcher,FixedPage,UIElementCollection,Visual是住在存储器等).
当我在WPF应用程序中执行相同操作时似乎不会发生这种情况,因此我的预感是它与在WPF应用程序之外使用的WPF UI Dispatcher模型有关.
FixedDocument在像这样的服务中(或者一般在WPF应用程序之外)使用它们时,如何"处置"我的对象?
========编辑=========
好吧,我发现我的内存泄漏与创建/填充FixedDocument无关.如果我这样做,但实际上并没有将其作为XPS保存到磁盘,则不会发生内存泄漏.所以,我的问题必须是保存为XPS文件.
这是我的代码:
var paginator = myFixedDocument.DocumentPaginator;
var xpsDocument = new XpsDocument(filePath, FileAccess.Write);
var documentWriter = XpsDocument.CreateXpsDocumentWriter(xpsDocument);
documentWriter.Write(paginator);
xpsDocument.Close();
Run Code Online (Sandbox Code Playgroud)
我尝试过的:
UpdateLayout()每一页myFixedDocument(如下面的答案所示) - 我也试过myFixedDocument直接传入Write() ie而不是paginator仍然没有运气.
==========替代方案==========
通过使用http://msdn.microsoft.com/en-us/library/system.appdomain.aspx上的示例中显示的常规方法将上述代码隔离到自己的AppDomain中,内存泄漏不再影响我的服务(I说"不再影响",因为它仍然会发生,但是当卸载AppDomain时,所有泄露的资源都会被卸载).
我仍然希望看到一个真正的解决方案.
(在相关的说明中,对于那些感兴趣的人,使用单独的AppDomain导致PDFSharp组件中的内存泄漏,我用来将某些XPS文件转换为PDF文件.结果PDFSharp使用全局字体缓存,在正常情况下不会增长使用这些AppDomains后,缓存增长和增长.我编辑了PDFSharp源代码,使我能够手动清除FontDescriptorStock和FontDataStock,解决了这个问题.)
==========解决方案==========
请参阅下面的答案以获得最终解决方
我正在尝试使用FreeSpire将安全的PDF转换为XPS并返回PDF,然后使用iTextSharp将它们组合在一起.下面是我转换各种文件的代码段.
char[] delimiter = { '\\' };
string WorkDir = @"C:\Users\rwong\Desktop\PDF\Test";
Directory.SetCurrentDirectory(WorkDir);
string[] SubWorkDir = Directory.GetDirectories(WorkDir);
//convert items to PDF
foreach (string subdir in SubWorkDir)
{
string[] Loan_list = Directory.GetFiles(subdir);
for (int f = 0; f < Loan_list.Length - 1; f++)
{
if (Loan_list[f].EndsWith(".doc") || Loan_list[f].EndsWith(".DOC"))
{
Spire.Pdf.PdfDocument doc = new Spire.Pdf.PdfDocument();
doc.LoadFromFile(Loan_list[f], FileFormat.DOC);
doc.SaveToFile((Path.ChangeExtension(Loan_list[f],".pdf")), FileFormat.PDF);
doc.Close();
}
. //other extension cases
.
.
else if (Loan_list[f].EndsWith(".pdf") || Loan_list[f].EndsWith(".PDF"))
{
PdfReader reader = new PdfReader(Loan_list[f]);
bool PDFCheck = reader.IsOpenedWithFullPermissions;
reader.Close(); …Run Code Online (Sandbox Code Playgroud) 在WPF DocumentViewer中显示XPS文件并关闭DocumentViewer实例后,XPS文件被锁定,我无法删除它.我需要释放XPS文件上的锁,以便我可以删除它,编写另一个具有相同名称的文件,并可选择在新的DocumentViewer实例中显示新的XPS文件.我需要在同一个应用程序实例中执行此操作 - 无需关闭应用程序(这是打印预览方案).
换句话说,如何在不在"File.Delete(tempXpsFile);"处抛出异常的情况下运行以下代码?声明?
var tempXpsFile = @"c:\path\to\Temporary.xps";
var previewWindow = new Window();
var docViewer = new DocumentViewer();
previewWindow.Content = docViewer;
GenerateXpsFile(tempXpsFile);
var xpsDocument = new XpsDocument(tempXpsFile);
previewWindow.ShowDialog();
File.Delete(tempXpsFile); //this will throw an exception due to a file lock on tempXpsFile
GenerateXpsFile(tempXpsFile); //assume this generates a different file
//otherwise the scenario doesn't make sense as we could just skip the above delete
//and this statement and re-use the same file
previewWindow = new Window();
docViewer = new DocumentViewer();
previewWindow.Content …Run Code Online (Sandbox Code Playgroud) 题
BlockUIContainer?背景
我生成FlowDocument了一段文本,其中Rectangle包含DrawingBrushes从资源字典和BlockUIContainer自定义控件填充的一些元素.
在任何的FlowDocument*的观察时,所述文档正确呈现控制无论其当文档被转换为固定文档/ XpsDocument,没有一个Rectangle或BlockUIContainer元素渲染.
我几乎可以肯定这是因为没有测量/安排控件,但是无法弄清楚如何在转换为XpsDocument之前强制执行.
我已经LogicalTree递归地走过去做了以下事情,
UIElement element = (UIElement)d;
element.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
element.Arrange(new Rect(element.DesiredSize));
element.UpdateLayout();
Run Code Online (Sandbox Code Playgroud)
这里d是一个DependencyObject.我可以看到这在调试器中以break-pointed为单位设置ActualWidth和ActualHeight属性.
我试图Dispatcher按照Will♦的建议强制渲染.
用于打印XpsDocument的代码
public class XpsDocumentConverter
{
public static XpsDocumentReference CreateXpsDocument(FlowDocument document)
{
// Need to clone the document so that the paginator can work
FlowDocument clonedDocument = DocumentHelper.Clone<FlowDocument>(document); …Run Code Online (Sandbox Code Playgroud) XpsDocument是从磁盘加载的
通过XpsDocument.GetFixedDocumentSequence方法()创建一个FixedDocumentSequence
通过DocumentViewer显示
想添加添加页眉和页脚打印
我不需要将页眉和页脚添加回XPS文档 - 仅打印输出
我尝试实现DocumentPaginator但无法使大小调整或放置工作
与FlowDocument的这个页脚不一样
我在那里使用FlowDocuments的解决方案就好了
将XAML流文档转换为带样式的XPS
在FixedDocumentSequence上,大小调整来自文档(我猜)
例如可以混合横向和纵向
我无法弄清楚如何挂钩到大小调整并为页眉和页脚腾出空间
我可以在其上标记一个标题但它超过顶部页面
和横向页面被切断
无法分配每页当它来自一个文档序列
作为链接说,它是建议的页面大小
DocumentPage .Size是只读
即使我使用DocumentPaginator.GetPage加载页面时创建我想要的大小的DocumentPage,然后大小被覆盖
更糟糕的是,DocumentPaginator似乎没有正确地意识到尺寸,因为它没有正确处理混合风景和肖像.风景是打印的肖像,只是在页面上运行.
有人问我发布代码
也可能是一个更简单更好的方法
看看页脚到FlowDocument如何使用它
这是它破坏
//这从GetPage获取页面大小 - 忽略上面的大小
public class DocumentPaginatorWrapperXPS : DocumentPaginator
{
System.Windows.Size m_PageSize;
System.Windows.Size m_Margin;
DocumentPaginator m_Paginator;
FixedDocumentSequence fixedDocumentSequence;
Typeface m_Typeface;
private string printHeader;
private int? sID;
private string docID;
public DocumentPaginatorWrapperXPS(FixedDocumentSequence FixedDocumentSequence, System.Windows.Size margin, string PrintHeader, …Run Code Online (Sandbox Code Playgroud) 我在获取FlowDocument中包含的图像时遇到一些困难,以显示FlowDocument何时保存为XPS文档.
这是我做的:
如果我然后在XPS查看器中查看保存的文件,则不显示图像.问题是,在WPF实际显示在屏幕上之前不会加载图像,因此它们不会保存到XPS文件中.因此,有一种解决方法:如果我首先使用FlowDocumentPageViewer在屏幕上显示文档,然后保存XPS文件,则会加载图像并显示在XPS文件中.即使隐藏了FlowDocumentPageViewer,这也可以工作.但这给了我另一个挑战.这是我想做的(在伪代码中):
void SaveDocument()
{
AddFlowDocumentToFlowDocumentPageViewer();
SaveFlowDocumentToXpsFile();
}
Run Code Online (Sandbox Code Playgroud)
这当然不起作用,因为在文档保存到XPS文件之前,FlowDocumentPageViewer永远不会有机会显示其内容.我尝试在调用Dispatcher.BeginInvoke时包装SaveFlowDocumentToXpsFile但它没有帮助.
我的问题是:
我有一个FlowDocument,我想转换为XPS文档并将其附加到电子邮件并将它们一起发送.我正在使用此代码
public static MemoryStream FlowDocumentToXPS(FlowDocument flowDocument, int width, int height)
{
MemoryStream stream = new MemoryStream();
using (Package package = Package.Open(stream, FileMode.Create, FileAccess.ReadWrite))
{
using (XpsDocument xpsDoc = new XpsDocument(package, CompressionOption.Maximum))
{
XpsSerializationManager rsm = new XpsSerializationManager(new XpsPackagingPolicy(xpsDoc), false);
DocumentPaginator paginator = ((IDocumentPaginatorSource)flowDocument).DocumentPaginator;
paginator.PageSize = new System.Windows.Size(width, height);
rsm.SaveAsXaml(paginator);
rsm.Commit();
}
}
stream.Position = 0;
Console.WriteLine(stream.Length);
Console.WriteLine(stream.Position);
return stream;
}
Run Code Online (Sandbox Code Playgroud)
然后我使用以下代码附加它:
Attachment xps = new Attachment(FlowDocumentToXPS(FD, 768, 676), "FileName.xps", "application/vnd.ms-xpsdocument");
Run Code Online (Sandbox Code Playgroud)
其中FD是我要转换的FlowDocument,我接收到附加的0.0KB大小的XPS文件,并且无法使用XPS Viewer打开,我在这里缺少什么?
编辑:有效的最终代码,请参阅注释
提前致谢
xpsdocument ×10
wpf ×7
c# ×5
flowdocument ×3
.net ×2
dispatcher ×1
filelock ×1
image ×1
itextsharp ×1
memory-leaks ×1
printing ×1
spire.doc ×1
xps ×1