我刚刚开始我当前项目的合同生成例程,其中一个要求是合同中的每一行都必须编号.该数字应位于左边距,并使用垂直规则将编号与文档内容的其余部分分开.
我很确定我可以使用FixedDocument解决这个问题,但它不会很有趣.反正我是否可以使用FlowDocument来做到这一点?
我创建了一个.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,解决了这个问题.)
==========解决方案==========
请参阅下面的答案以获得最终解决方
更新!
绑定工作.问题是XpsDocumentWriter没有正确编写FixedDocumentSequence的第一个文档的第一页.这似乎是很多人在做这类事情时遇到的问题(即全世界有五个开发人员).解决方案有点奇怪.我把它作为答案包括在内.
好吧,它比问题暗示的更微妙.
我有一系列的FixedPages,每个都有单独的DataContext设置.每个FixedPage还有一个或多个绑定到上下文的控件.
如果我将这些FixedPages添加到单个FixedDocument并将此单个FixedDocument写入XpsDocument,我的绑定将被取消引用(可以这么说),并且正确的值将显示在XpsDocument中.
如果我将这些FixedPages添加到单个FixedDocuments(每个FP添加到一个新FD),然后将这些FixedDocuments添加到FixedDocumentSequence,然后将此序列写入XpsDocument,我的绑定不会被引用,我的FixedPages显示为空白.
调试告诉我,我没有丢失绑定或绑定上下文,所以这不是导致失败的原因.
这里有一些示例代码来说明正在发生的事情:
// This works
FixedPage fp = CreateFixedPageWithBinding();
fp.DataContext = CreateDataContext();
// Add my databound fixed page to a new fixed document
var fd = new FixedDocument();
var pc = new PageContent();
((IAddChild)pc).AddChild(fp);
fd.Pages.Add(pageContent);
// Create an xps document and write my fixed document to it
var p = Package.Open("c:\\output.xps", FileMode.CreateNew);
var doc = new XpsDocument(p);
var writer = XpsDocument.CreateXpsDocumentWriter(doc);
wri2.Write(fd);
p.Flush();
p.Close();
// This does NOT work
FixedPage fp = CreateFixedPageWithBinding();
fp.DataContext …Run Code Online (Sandbox Code Playgroud) data-binding fixedpage xps fixeddocument fixeddocumentsequence
当您尝试在XAML中构建一个Visual Studio时,Visual Studio会显示错误,这是一个众所周知的错误FixedDocument.例如,以下代码段
<DocumentViewer>
<FixedDocument>
<PageContent>
<FixedPage Width="21.0cm" Height="29.7cm">
<TextBlock>Hello World!</TextBlock>
</FixedPage>
</PageContent>
</FixedDocument>
</DocumentViewer>
Run Code Online (Sandbox Code Playgroud)
编译并运行完美,但Visual Studio在错误列表中显示错误(Property 'Pages' does not support values of type 'PageContent'.)这很烦人.
我正在寻找一种解决方案,允许我在Visual Studio中的XAML文件中构建我的文档,而不会收到该错误消息.我找到了一个解决方法,我想在下面分享作为答案,但我很好奇是否有一个更好(更优雅)的解决方案.
I have a simple WPF app that displays and prints some reports with a FixedDocument.
How can generate PDF's from that, with a free and open solution, such as iTextSharp?
如何让FixedDocument自动分页?我有以下代码可用于将美化面板放入DocViewer.当Panel扩展到单个页面时会发生此问题.现在,我们只是剪辑.基本上,我想创建一种相当通用的方式来打印用户正在查看的内容.我的方法合理吗?
public void CreateReport(Panel details)
{
FixedDocument fixedDoc = new FixedDocument();
PageContent pageContent = new PageContent();
FixedPage fixedPage = new FixedPage();
fixedPage.DataContext = this.DataContext;
fixedPage.Margin = new Thickness(10);
fixedPage.Children.Add(details);
((System.Windows.Markup.IAddChild)pageContent).AddChild(fixedPage);
fixedDoc.Pages.Add(pageContent);
// This makes the array of controls invisibile, then climbs the details structure
// and makes the controls within details appropriate for the DocumentViewwer (i.e. TextBoxes are
// non-editable, no borders, no scroll bars, etc).
prePrintPrepare(details, fixedPage, new FrameworkElement[] { controlToMakeInvisible });
_dv = new DocViewer();
_dv.documentViewer1.Document = fixedDoc; …Run Code Online (Sandbox Code Playgroud) 如何从fixedDocument中删除页面?
我添加如下页面:
// Add page to pageContent
PageContent pageContent = new PageContent();
((IAddChild)pageContent).AddChild(fixedPage);
// Add pageContent to wholeDoc
fixedDocument.Pages.Add(pageContent);
//Add to documentVeiwer
documentViewer1.Document = fixedDocument;
Run Code Online (Sandbox Code Playgroud)
但是没有'fixedDocument.Pages.Remove(page)'方法!我能做什么?
我正在尝试使用FixedDocument保存XPS文档。到目前为止,我未能更改页面大小。如何将其更改为自定义尺寸?
我的代码基于对该问题的第一个答案,更具体地说,我正在使用以下代码:
if (File.Exists(filename)) {
File.Delete(filename);
}
var oldParent = LogicalTreeHelper.GetParent(this) as ContentControl;
try {
oldParent.Content = null;
FixedDocument doc = new FixedDocument();
PageContent pageCnt = new PageContent();
FixedPage page = new FixedPage();
page.Children.Add(this);
try {
((System.Windows.Markup.IAddChild)pageCnt).AddChild(page);
doc.Pages.Add(pageCnt);
XpsDocument xpsDoc = new XpsDocument(filename, FileAccess.ReadWrite);
try {
var writer = XpsDocument.CreateXpsDocumentWriter(xpsDoc);
writer.Write(doc);
}
finally {
xpsDoc.Close();
}
}
finally {
page.Children.Clear();
}
}
finally {
((ContentControl)oldParent).Content = this;
}
Run Code Online (Sandbox Code Playgroud)
它可以将用户控件复制到XPS文档中,并且可以成功完成复制,但是正如我所说,它使用默认的纸张尺寸。
我尝试使用该DocumentPaginator.PageSize属性设置新的页面大小(在实例化之后FixedDocument),但是分配给该属性的任何内容似乎都将被忽略;生成的XPS文档中的页面保留其默认纸张尺寸。
当逐步执行时,我可以看到该 …
我有FixedDocument页面,我想TextBlock放在它上面,但它可能Textblock不适合页面的高度。
所以我想从繁重的产生线TextBlock带TextWrapping,然后创建新的TextBlock,即通过安装高度,并把它页。
TextBlock有LineCount私有财产,这意味着它TextLines在包装后有,我可以以某种方式得到它。使用运行
创建TextBlock:
public TextItem(PageType pageType, Run[] runs, Typeface typeFace, double fontSize)
: base(pageType)
{
this.TextBlock = new TextBlock();
this.TextBlock.Inlines.AddRange(runs);
if (typeFace != null)
this.TextBlock.FontFamily = typeFace.FontFamily;
if (fontSize > 0)
this.TextBlock.FontSize = fontSize;
this.TextBlock.TextWrapping = TextWrapping.Wrap; //wrapping
}
Run Code Online (Sandbox Code Playgroud)
TextBlock用文本创建:
public TextItem(PageType pageType, String text, Typeface typeFace, double fontSize)
: base(pageType)
{
if (typeFace == null || fontSize == …Run Code Online (Sandbox Code Playgroud) 在WPF中,为了在代码中添加一个FixedPage,FixedDocument需要:
var page = new FixedPage();
var pageContent = new PageContent();
((IAddChild)pageContent).AddChild(page);
Run Code Online (Sandbox Code Playgroud)
但这似乎是唯一的方法:
MSDN文档明确表示不应该这样做('此API支持.NET Framework基础结构,并不打算直接在您的代码中使用.'- PageContent.IAddChild.AddChild方法).
为了添加内容,必须转换为显式接口实现是很难看的PageContent.
执行基本操作并不简单PageContent.
文档实际上没有解释如何执行此操作,我找不到有关如何执行此操作的任何其他信息.还有另外一种方法吗?一个'正确'的方式?
我有:
DocumentPaginator dp = ((IDocumentPaginatorSource)document).DocumentPaginator;
Run Code Online (Sandbox Code Playgroud)
和:
FlowDocument document = new FlowDocument();
// create a flow document...
Run Code Online (Sandbox Code Playgroud)
如何使用DocumentPaginator将FlowDocument转换为FixedDocument?我似乎无法找到如何做到这一点.我查看的所有网站都使用XpsWriter,如:
XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(xpsDoc);
DocumentPaginator dp = ((IDocumentPaginatorSource)document).DocumentPaginator;
writer.Write(dp);
Run Code Online (Sandbox Code Playgroud)
我可以编写XPS然后返回FixedDocument但是必须有更好的方法吗?
我有 10 个System.Drawing.Image。我需要将它们添加到FixedDocument. 我尝试了下面的代码,并且所有 10 页只包含第一张图像的固定文档被生成。
FixedDocument doc = new FixedDocument();
BitmapSource[] bmaps = new BitmapSource[10];
System.Drawing.Image[] drawingimages = //I have System.Drawing.Image in a array
for (int i = 0; i < 10; i++)
{
Page currentPage = this.Pages[i];
System.Drawing.Image im = drawingimages[i];
im.Save(i + ".png");
Stream ms = new MemoryStream();
im.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
var decoder = BitmapDecoder.Create(ms, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnDemand);
ImageSource imgsource = decoder.Frames[0];
bmaps[i] = imgsource as BitmapSource;
}
foreach (BitmapSource b in bmaps)
{
PageContent …Run Code Online (Sandbox Code Playgroud) 我有一个XAML文件,我已经减少了以找到这个问题的原因到以下最小的情况:
<FixedDocument
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" >
<PageContent>
</PageContent>
</FixedDocument>
Run Code Online (Sandbox Code Playgroud)
它在KAXAML中打开很好,但是当我在Expression Blend 4中打开相同的文件时,我在<PageContent>标记处得到以下2个错误:
没有CodeBehind.唯一有趣的是这个文件存在于Winforms项目中,我已经应用了以下hack:http: //social.expression.microsoft.com/Forums/en-US/blend/thread/c726522f-c721-42a7- 8bf1-c73360edaa60 - 但直接WPF项目中的文件也会出现问题.
有谁知道为什么,并解决这个问题?
fixeddocument ×13
wpf ×10
c# ×4
.net ×2
flowdocument ×2
xps ×2
.net-3.5 ×1
data-binding ×1
dispatcher ×1
document ×1
fixedpage ×1
image ×1
itextsharp ×1
line-count ×1
memory-leaks ×1
pagination ×1
pdf ×1
textblock ×1
xaml ×1
xpsdocument ×1