views:

1382

answers:

2

Update!

Binding works. The issue is that the XpsDocumentWriter doesn't properly write the first page of the first document of a FixedDocumentSequence. This seems to be an issue encountered by lots of people doing this sort of thing (i.e., five developers worldwide). The solution is slightly odd. I include it as an answer.


Okay, its a bit more subtle than the question suggests.

I've got a series of FixedPages, each has its DataContext set individually. Each FixedPage also has one or more controls that are bound to the context.

If I add these FixedPages to a single FixedDocument and write this single FixedDocument to an XpsDocument, my binds are de-referenced (so to speak) and the correct values are presented in the XpsDocument.

If I add these FixedPages to individual FixedDocuments (each FP gets added to a new FD), then these FixedDocuments are added to a FixedDocumentSequence, and this sequence is then written to the XpsDocument, my binds are NOT de-referenced and my FixedPages appear blank.

Debugging tells me that I'm not losing my bindings or my binding context, so that's not the cause of this failure.

Here's some sample code to illustrate what's going on:

// 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();

You can see that the only difference between the two is that I'm adding the fixed document to a fixed document sequence, which then gets written.

Obviously, whatever magic happens that causes the databinding to be evaluated and the bound values be inserted isn't happening when my fixed documents aren't being Written to the Xps Document. I need to be able to write more than one fixed document, and the Write method can only be called once, thus requiring I add the FixedDocuments to a FixedDocumentSequence which I then write. But I also need my damn databinding to work as well!

Any help in this situation would be appreciated. I know its not exactly the most common part of the framework; I'm just hoping that someone here has some operational experience with this (I'm looking at you, lurking MS employee).

A: 

One reason that you lose a binding is that you throw an exception somewhere - unfortunately, this exception is silently swallowed and your binding just "stops working". Turn on First-chance exceptions and see if anything gets hit.

Paul Betts
This process is full of potholes and I've seen many exceptions when trying to do this another way. Exceptions are only swallowed during the binding, and I know that works (I can write he document successfully and then immediately add it to a sequence and write that, which fails).
Will
+2  A: 

The cause of this bug is that the FixedPage's layout isn't being updated prior to writing. This causes the first FixedPage in the first FixedDocument in the FixedDocumentSequence to be written incorrectly. This affects NO OTHER PAGES IN THE RESULTING DOCUMENT, which made this bug/edge case harder to nail down.

The following WORKS (rewritten version of the non-working example):

FixedPage fp = CreateFixedPageWithBinding();
fp.DataContext = CreateDataContext();
var fd = new FixedDocument();

/* PAY ATTENTION HERE */
// set the page size on our fixed document 
fd.DocumentPaginator.PageSize =
   new System.Windows.Size()
   {
       Width = DotsPerInch * PageWidth,
       Height = DotsPerInch * PageHeight
   };
// Update the layout of our FixedPage
var size = fd.DocumentPaginator.PageSize;
page.Measure(size);
page.Arrange(new Rect(new Point(), size));
page.UpdateLayout();    
/* STOP PAYING ATTENTION HERE */

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();
Will
There might be additional stuff going on in the background, but this part of the framework is not well documented or widely used, so I might be missing details/side effects/causes/effects.
Will