Load XpsDocument from a .XPS file into existing FixedDocument

1.8k Views Asked by At

I'm trying to load a XPS file from disk and print it as part of a FixedDocument or FixedDocumentSequence of in memory documents I've created. They need to be printed as one sequence because they're duplexed.

Here's my best attempt so far:

// create my memory FixedDocument (a packing slip)
DocumentReference mainDocRef = GetMainDoc();  // created in memory

// load XPS document from file (to print on the back)
XpsDocument xpsDoc = new XpsDocument("flyer.xps", FileAccess.Read);
var docSequenceFromFile = xpsDoc.GetFixedDocumentSequence();
var xpsDocRef = docSequenceFromFile.References.First();

// try to combine together
FixedDocumentSequence documentSequence = new FixedDocumentSequence();
documentSequence.References.Add(mainDocRef);
documentSequence.References.Add(xpsDocRef);     // THROWS EXCEPTION

// print
XpsDocumentWriter xps = PrintQueue.CreateXpsDocumentWriter(printQueue);
xps.Write(documentSequence, ticket);

I always end up with the exception :

InvalidOperationException : Additional information: Specified element is already the logical child of another element. Disconnect it first.

I've tried several ways to do this, but keep ending up with errors like this

How can I load an XpsDocument and print it as a second page in a FixedDocumentSequence I've created in memory?

1

There are 1 best solutions below

0
On

Simon_Weaver,

As I dont exactly know what is being returned by the GetMainDoc() method I have excluded that and just commented out the mainDocRef refrences however this seems trivial as your issue is adding the loaded xps file to your documentSequence and the mainDocRef is somewhat irrelevant to the question (please correct me if I am wrong).

Now the problem as stated is that the xpsDoc is loaded to another element (document) and we must detach it as the exception states. However the ability to do so is protected by an internal method. This being said the easiest way is just enumerate through all the pages of the document and create a new page from the source of the page being enumerated to a new document.

The final code looks something like.. (code commented)

//DocumentReference mainDocRef = GetMainDoc();  // created in memory. commented as I dont have a reference to what this object contains.

//create our new document reference to add the pages to
DocumentReference newDocReference = new DocumentReference();

// load XPS document from file (to print on the back)
using (XpsDocument xpsDoc = new XpsDocument(@"flyer.xps", FileAccess.Read))
{
    var docSequenceFromFile = xpsDoc.GetFixedDocumentSequence();
    var xpsDocRef = docSequenceFromFile.References.First();

    //get the fixed document to enumerate
    FixedDocument xpsFixedDoc = xpsDocRef.GetDocument(false);

    //get the fixed document to add to
    FixedDocument newFixedDoc = new FixedDocument();

    //set the new document reference
    newDocReference.SetDocument(newFixedDoc);

    //enumerate each page of the fixed document
    foreach (PageContent page in xpsFixedDoc.Pages)
    {
        PageContent newPageContent = new PageContent();
        newPageContent.Source = page.Source;
        ((IUriContext)newPageContent).BaseUri = ((IUriContext)page).BaseUri;
        newPageContent.GetPageRoot(true);
        newFixedDoc.Pages.Add(newPageContent);
    }
}

// try to combine together.
FixedDocumentSequence documentSequence = new FixedDocumentSequence();

//documentSequence.References.Add(mainDocRef); <<-- commented out, re-add after tests

//add the new document reference
documentSequence.References.Add(newDocReference);     

// print
XpsDocumentWriter xps = PrintQueue.CreateXpsDocumentWriter(printQueue);
xps.Write(documentSequence, ticket);

mainDocRef = null;
newDocReference = null;

Now one thing to note is XpsDocument and PrintQueue inherit from IDisposable. (Dont need to tell you what to do there).

Now there could still be problems with the GetMainDoc() but as the reference to this method is not posted I cant test any errors here. Let me know how it goes.

Cheers. Nico