Data binding 为什么在打印到XpsDocument时会丢失数据绑定?

Data binding 为什么在打印到XpsDocument时会丢失数据绑定?,data-binding,xps,fixedpage,fixeddocument,fixeddocumentsequence,Data Binding,Xps,Fixedpage,Fixeddocument,Fixeddocumentsequence,更新 装订工作。问题是XpsDocumentWriter没有正确写入FixedDocumentSequence的第一个文档的第一页。这似乎是许多从事这类工作的人(即全球五名开发人员)遇到的问题。这个解决方案有点奇怪。我把它作为一个答案 好吧,这比问题暗示的要微妙一点 我有一系列的FixedPage,每个都有各自的DataContext集。每个FixedPage还具有一个或多个绑定到上下文的控件 如果我将这些FixedPages添加到单个FixedDocument,并将此单个FixedDocum

更新

装订工作。问题是XpsDocumentWriter没有正确写入FixedDocumentSequence的第一个文档的第一页。这似乎是许多从事这类工作的人(即全球五名开发人员)遇到的问题。这个解决方案有点奇怪。我把它作为一个答案


好吧,这比问题暗示的要微妙一点

我有一系列的FixedPage,每个都有各自的DataContext集。每个FixedPage还具有一个或多个绑定到上下文的控件

如果我将这些FixedPages添加到单个FixedDocument,并将此单个FixedDocument写入XpsDocument,我的绑定将被取消引用(可以这么说),正确的值将显示在XpsDocument中

如果我将这些FixedPage添加到各个FixedDocuments(每个FP都添加到一个新的FD),那么这些FixedDocuments将添加到FixedDocuments序列,然后该序列将写入XpsDocument,我的绑定不会被取消引用,我的FixedPage将显示为空

调试告诉我没有丢失绑定或绑定上下文,因此这不是导致此失败的原因

下面是一些示例代码来说明发生了什么:

// 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 = 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 a fixed document sequence and add the fixed document to it
FixedDocumentSequence fds = CreateFixedDocumentSequence();
var dr = new DocumentReference();
dr.BeginInit();
dr.SetDocument(fd);
dr.EndInit();
(fds as IAddChild).AddChild(dr);
// Create an xps document and write the fixed document sequence to it
var p = Package.Open("c:\\output.xps", FileMode.CreateNew);
var doc = new XpsDocument(p);
var writer = XpsDocument.CreateXpsDocumentWriter(doc);
wri2.Write(fds);
p.Flush();
p.Close();
您可以看到,两者之间的唯一区别是,我将固定文档添加到固定文档序列中,然后写入

显然,当我的固定文档没有写入Xps文档时,无论发生什么魔法,都不会导致对数据绑定进行求值并插入绑定值。我需要能够编写多个固定文档,并且write方法只能调用一次,因此需要将FixedDocuments添加到FixedDocuments序列中,然后再编写该序列。但我也需要我该死的数据绑定才能工作


在这种情况下,任何帮助都将不胜感激。我知道这并不是框架中最常见的部分;我只是希望这里有人对此有一些操作经验(我在看你,潜伏着微软员工)。

你丢失绑定的一个原因是你在某个地方抛出了一个异常-不幸的是,这个异常被悄悄地吞没了,你的绑定只是“停止工作”。打开First chance exceptions,查看是否有任何内容被命中。

此错误的原因是在写入之前没有更新FixedPage的布局。这会导致FixedDocument序列中第一个FixedDocument中的第一个FixedPage写入错误。这不会影响结果文档中的任何其他页面,这使得这个bug/edge案例更难确定

以下作品(非工作示例的重写版本):


我在尝试使用
XpsDocumentWriter
写入
PrintQueue
时发现此问题。以下代码正确打印第一页

//Prints correctly
FixedDocumentSequence Documents = new FixedDocumentSequence();

//some code to add DocumentReferences to FixedDocumentSequence

PrintDialog printDialog = new PrintDialog
{
    PrintQueue = LocalPrintServer.GetDefaultPrintQueue() 
};
printDialog.PrintTicket = printDialog.PrintQueue.DefaultPrintTicket;
if (printDialog.ShowDialog() == true)
{
    Documents.PrintTicket = printDialog.PrintTicket;

    XpsDocumentWriter writer = PrintQueue.CreateXpsDocumentWriter(printDialog.PrintQueue);
    writer.Write(Documents, printDialog.PrintTicket);
    printerName = printDialog.PrintQueue.FullName;
}

如果删除
printDialog.ShowDialog()
并仅尝试对默认打印机进行静默打印,则第一页打印不正确。然而,在我的场景中,我不需要使用
FixedDocumentSequence
,所以我将它换成了一个
FixedDocument
,静默打印工作正常。我尝试更新
FixedPage
上的布局,但没有成功。奇怪的是,如果我显示“打印”对话框,第一页的打印效果会很好。

这个过程充满了凹坑,当我尝试以另一种方式进行打印时,我看到了许多例外情况。只有在绑定过程中才会出现异常,我知道这是可行的(我可以成功地编写文档,然后立即将其添加到序列中并编写,但失败)。后台可能会有其他内容,但框架的这一部分没有很好的文档记录或广泛使用,因此,我可能缺少详细信息/副作用/原因/效果。请搜索者注意——我最近了解到的另一个有趣的事实是,如果您使用SerializerWriterCollector将视觉效果写入XpsDocumentWriter(在writer上调用CreateVisualsCollator以获取它),则可以在每次写入后重新使用视觉效果。当你有成千上万的视觉作品要写的时候,省去了这一天。而且,对于每一个视觉作品,你必须至少调用一次度量和安排。在这之后,您可以在更改DataContextUp和bug报告后调用UpdateLayout来更新绑定。编辑功能似乎已损坏,因此我无法将其添加到摘要或添加解决方法:/固定文档似乎是关键
//Prints correctly
FixedDocumentSequence Documents = new FixedDocumentSequence();

//some code to add DocumentReferences to FixedDocumentSequence

PrintDialog printDialog = new PrintDialog
{
    PrintQueue = LocalPrintServer.GetDefaultPrintQueue() 
};
printDialog.PrintTicket = printDialog.PrintQueue.DefaultPrintTicket;
if (printDialog.ShowDialog() == true)
{
    Documents.PrintTicket = printDialog.PrintTicket;

    XpsDocumentWriter writer = PrintQueue.CreateXpsDocumentWriter(printDialog.PrintQueue);
    writer.Write(Documents, printDialog.PrintTicket);
    printerName = printDialog.PrintQueue.FullName;
}