简体   繁体   中英

WPF DocumentViewer override Print button

I have implemented print preview functionality within my application using a custom DocumentViewer (shown below). I call PrintDialog.ShowDialog() before showing the preview so as to correctly create the document based on paper orientation.

The DocumentViewer print button however calls the PrintDialog.ShowDialog() prompting the user to chose printer and options once again (which they already did prior to the preview window opening).

Is there a way to have the DocumentViewer print button simply print without calling PrintDialog.ShowDialog() ?

Here are my method calls:

ReportViewModel.cs

    public void PrintButtonClick(DataGrid dataGrid)
    {
        PrintDialog printDialog = new PrintDialog();
        if (printDialog.ShowDialog() == false)
            return;

        // Get page size based on print dialog printable area (orientation)
        Size pageSize = new Size(printDialog.PrintableAreaWidth, printDialog.PrintableAreaHeight);

        // create new paginator for datagrid
        DataGridDocumentPaginator paginator = new DataGridDocumentPaginator(dataGrid as DataGrid, "Employer Match Report", pageSize, new Thickness(30, 20, 30, 20));
        ...
    }

I am doing it this way so that I can correctly generate the paginator with either Portrait or Landscape size values. Without this the preview document within the DocumentViewer might not display correctly based on orientation chosen.

PrintDocumentViewer : DocumentViewer

   protected override void OnPrintCommand()
   {
       PrintDialog printDialog = new PrintDialog();
       printDialog.PrintQueue = LocalPrintServer.GetDefaultPrintQueue();
       printDialog.PrintTicket = printDialog.PrintQueue.DefaultPrintTicket;

       printDialog.PrintTicket.PageOrientation = PageOrientation;
       // Code assumes this.Document will either by a FixedDocument or a FixedDocumentSequence
       FixedDocument fixedDocument = this.Document as FixedDocument;
       FixedDocumentSequence fixedDocumentSequence = this.Document as FixedDocumentSequence;

       if (fixedDocument != null)
           fixedDocument.PrintTicket = printDialog.PrintTicket;

       if (fixedDocumentSequence != null)
           fixedDocumentSequence.PrintTicket = printDialog.PrintTicket;

       XpsDocumentWriter writer = PrintQueue.CreateXpsDocumentWriter(printDialog.PrintQueue);

       if (fixedDocument != null)
           writer.WriteAsync(fixedDocument, printDialog.PrintTicket);

       if (fixedDocumentSequence != null)
           writer.WriteAsync(fixedDocumentSequence, printDialog.PrintTicket);

       // Create Preview Window and show preview
       string s = _previewWindowXaml;
       using (var reader = new System.Xml.XmlTextReader(new StringReader(s)))
       {
           Window preview = System.Windows.Markup.XamlReader.Load(reader) as Window;

           DocumentViewer _docViewer = LogicalTreeHelper.FindLogicalNode(preview, "PrintDocumentViewer") as DocumentViewer;
           _docViewer.Document = (fixedDocument != null) ? fixedDocument as IDocumentPaginatorSource : fixedDocumentSequence as IDocumentPaginatorSource;

           // hide the search bar in the PrintPreview dialog
           ContentControl cc = _docViewer.Template.FindName("PART_FindToolBarHost", _docViewer) as ContentControl;
           cc.Visibility = Visibility.Collapsed;

           preview.ShowDialog();
       }
   }

You may fill printer and paper size properties, then dialog is not shown.

var pd = new PrintDialog();
pd.PrintTicket.PageMediaSize = new PageMediaSize(PageMediaSizeName.NorthAmericaLetter, 816.0, 1056.0);
pd.PrintQueue = new LocalPrintServer().GetPrintQueue("Microsoft Print to PDF");

To override Print command:

<DocumentViewer>
    <DocumentViewer.CommandBindings>
        <CommandBinding Command="ApplicationCommands.Print" Executed="Print_Executed" />
    </DocumentViewer.CommandBindings>
</DocumentViewer>

The print button allone can not easily be overridden but I found a way to do it. Even if it may be considered a dirty hack, what counts in the end is the result.

I just overlayed the print button (which is the first button anyway) with a non-visible button that redirects clicks to my own print function. In this example code the search toolbar is also hidden and Ctrl+P is disabled:

<Grid>
    <DocumentViewer x:Name="DocumentViewer">
        <DocumentViewer.Resources>
            <Style TargetType="ContentControl">
                <Style.Triggers>
                    <Trigger Property="Name" Value="PART_FindToolBarHost">
                        <Setter Property="Visibility" Value="Collapsed" />
                    </Trigger>
                </Style.Triggers>
            </Style>
        </DocumentViewer.Resources>
        <DocumentViewer.InputBindings>
            <KeyBinding Key="P" Modifiers="Control" Command="ApplicationCommands.NotACommand" />
        </DocumentViewer.InputBindings>
    </DocumentViewer>
    <Button Width="32" Height="32" VerticalAlignment="Top" HorizontalAlignment="Left" Opacity="0.01" Click="OnPrint" ></Button>
</Grid>

I hope you have resolved this by now, but you may be able to use this question as a base for modifying the template for the DocumentViewer control:

How do you hide a WPF DocumentViewer's menu bars?

There is a link to an MSDN article that should show you how to modify the template so that the print button does what you want instead of the default Print action.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM