Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XPSDocumentWriter - Printing Specific Pages to Specific Trays

Tags:

printing

wpf

xps

I'm currently working on a printing application. This app has the requirement that certain pages need to come from specific trays on the printer. Here's the guts of what I've got so far:

    foreach (var dto in dispensersToPrint)
    {
        var documents = FilterDocumentSections(DispenserDocumentsToPrint.RetrieveByDispenserId(dto.DispenserId));
        var groupedDocs = documents.GroupBy(t => t.DocumentTypeId);
        var queueName = Properties.Settings.Default.PrinterName;
        var queue = RawPrinterHelper.GetPrintQueue(queueName);
        var seq = new FixedDocumentSequence();
        var xpsWriter = PrintQueue.CreateXpsDocumentWriter(queue);

        foreach (var docGroup in groupedDocs)
        {
            var printTicket = queue.DefaultPrintTicket.Clone();
            var printTray = MapPrintTray((DocumentSectionType)docGroup.Key);
            if (!printTray.IsNullOrEmpty())
            {
                printTicket = RawPrinterHelper.ModifyPrintTicket(printTicket, "psk:JobInputBin", printTray);
            }
            var fixedDoc = new FixedDocument();
            fixedDoc.PrintTicket = printTicket;

            foreach (var doc in docGroup)
            {
                var pageContent = new PageContent();
                var fixedPage = new FixedPage();

                var localFileName = string.Empty;
                var unzippedFileName = string.Empty;
                //copy files locally
                localFileName = CopyFileToLocalMachine(doc.FileName);
                //unzip file
                unzippedFileName = EmfPrintingHelper.UnzipEmfFile(localFileName);
                var itemToPrint = new PrintableEmfImage
                                           {
                                               DataContext = new EmfImageViewModel { FileName = unzippedFileName }
                                           };
                fixedPage.Children.Add(itemToPrint);
                pageContent.Child = fixedPage;
                fixedDoc.Pages.Add(pageContent);
            }
            var docRef = new DocumentReference();
            docRef.SetDocument(fixedDoc);
            seq.References.Add(docRef);
        }
        xpsWriter.Write(seq);
    }

At a real high level:

  • For each Dispenser (Work Order) i need to print; i first start by grouping by the DocumentType (i.e. Print type A to tray 1)
  • I then create a new FixedDocumentSequence
  • For each DocumentType; I then create a fixed document. I then modify the print ticket to look at the appropriate tray.
  • I then build each individual page for each document type; and add them to the FixedDocument
  • Once the building of the FixedDocument is complete; I append it to the DocumentSequence.
  • I then send the FixedDocumentSequence to the xpsWriter.

But for some reason; these settings aren't being honored. I get all the documents printing out of the same tray.

Here are some of my observations so far:

  • The modifying of the print ticket does work; I've verified this by sending a modified printTicket into the xpsWriter; but this applies the settings to the entire job; which is a no go for me.
  • When querying my print capabilities; i noticed that i only have JobInputBin. I don't quite think this means this printer doesn't support the functionality; as multi-tray printing works from a similar WindowsForms app (which uses PageSettings.PaperSource)

Any ideas on what I could try next? Has anyone been successful doing something like this before?

like image 582
Jim B Avatar asked Feb 18 '14 16:02

Jim B


1 Answers

I'll start off by saying, I don't have access to a printer with trays, so I am unfortunately not capable of testing this solution. That said, I'll direct your attention to an MSDN forum post, here, where the original poster was in pursuit of the same tray-per-page behavior.

Based on your posted code, you may have already seen some of what's in this post, judging by your posted code having at least some implementation of ModifyPrintTicket().

In the post, there are several different users, each citing a solution for their specific version of the problem. However, the one that seems most relevant in this case is the solution regarding namespaces not being correctly accounted for in ModifyPrintTicket() (as posted by Jo0815). I say 'most relevant' because the poster speaks of the print tray being disregarded. They (wittersworld) provide an alternate implementation to correct the issue. In the post on MSDN, the link to the complete source is broken, but can be located here.

The gist is, on ModifyPrintTicket(), they add a namespaceUri parameter, then withing changed this:

if (node != null)
{
    node.Attributes["name"].Value = newValue;
}

to this:

if (node != null)
{
    if (newValue.StartsWith("ns0000"))
    {
        // add namespace to xml doc
        XmlAttribute namespaceAttribute = xmlDoc.CreateAttribute("xmlns:ns0000");                   
        namespaceAttribute.Value = namespaceUri;                   
        xmlDoc.DocumentElement.Attributes.Append(namespaceAttribute);
    }
    node.Attributes["name"].Value = newValue;
}

allowing the user to specify the printer-specific namespace used.

I hope this is helpful.

like image 190
cokeman19 Avatar answered Nov 06 '22 14:11

cokeman19