C# WPF 的打印对话框和打印预览对话框

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29892177/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 04:21:23  来源:igfitidea点击:

Print dialog and print prewiew dialog for WPF

c#wpfxamlprintingprint-preview

提问by H. Pauwelyn

Is there a print dialog for WPF that is combinated whit a print preview dialog in WPF like Google Chrome or Word does?

是否有 WPF 的打印对话框与 WPF 中的打印预览对话框(如 Google Chrome 或 Word)相结合?

Like Google chrome does.

就像谷歌浏览器一样。

At this moment I use a the print preview dialog from Windows forms. I have also try for to use the WPF version of it. But WPF has no PrintPreviewDialogor PrintPrewiewControl. This is my code:

此时我使用 Windows 窗体中的打印预览对话框。我也尝试使用它的 WPF 版本。但是 WPF 没有PrintPreviewDialogPrintPrewiewControl. 这是我的代码:

//To the top of my class file:
using Forms = System.Windows.Forms;

//in a methode on the same class:
PageSettings setting = new PageSettings();
setting.Landscape = true;

_document = new PrintDocument();
_document.PrintPage += _document_PrintPage;
_document.DefaultPageSettings = setting ;

Forms.PrintPreviewDialog printDlg = new Forms.PrintPreviewDialog();
printDlg.Document = _document;
printDlg.Height = 500;
printDlg.Width = 200;

try
{
    if (printDlg.ShowDialog() == Forms.DialogResult.OK)
    {
        _document.Print();
    }
}
catch (InvalidPrinterException)
{
    MessageBox.Show("No printers found.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}

I've also searched for a NuGet package but nothing found really good.

我还搜索了 NuGet 包,但没有找到真正好的。

采纳答案by ELH

What you want to do, is to create an xpsDocumentout from the content you want to print (a flowDocument) and use that XpsDocumentto preview the content, for example let say you have the following Xaml, with a flowDocumentthat you want to print its content :

您想要做的是xpsDocument从您想要打印的内容 (a flowDocument)创建一个out并使用它XpsDocument来预览内容,例如假设您有以下XamlflowDocument您想要打印其内容:

 <Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <FlowDocumentScrollViewer>
        <FlowDocument x:Name="FD">
            <Paragraph>
                <Image Source="http://www.wpf-tutorial.com/images/logo.png" Width="90" Height="90" Margin="0,0,30,0" />
                <Run FontSize="120">WPF</Run>
            </Paragraph>

            <Paragraph>
                WPF, which stands for
                <Bold>Windows Presentation Foundation</Bold> ,
                is Microsoft's latest approach to a GUI framework, used with the .NET framework.
                Some advantages include:
            </Paragraph>

            <List>
                <ListItem>
                    <Paragraph>
                        It's newer and thereby more in tune with current standards
                    </Paragraph>
                </ListItem>
                <ListItem>
                    <Paragraph>
                        Microsoft is using it for a lot of new applications, e.g. Visual Studio
                    </Paragraph>
                </ListItem>
                <ListItem>
                    <Paragraph>
                        It's more flexible, so you can do more things without having to write or buy new controls
                    </Paragraph>
                </ListItem>
            </List>

        </FlowDocument>
    </FlowDocumentScrollViewer>        
    <Button Content="Print" Grid.Row="1" Click="Button_Click"></Button>
</Grid>

the flowDocument Sample is from Wpf tutorials site

flowDocument 示例来自Wpf 教程站点

the print button Click event handler should looks like this :

打印按钮 Click 事件处理程序应如下所示:

 private void Button_Click(object sender, RoutedEventArgs e)
    {
if (File.Exists("printPreview.xps"))
            {
                File.Delete("printPreview.xps");
            }
        var xpsDocument = new XpsDocument("printPreview.xps", FileAccess.ReadWrite);
        XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(xpsDocument);
        writer.Write(((IDocumentPaginatorSource)FD).DocumentPaginator);            
        Document = xpsDocument.GetFixedDocumentSequence();
        xpsDocument.Close();
        var windows = new PrintWindow(Document);
        windows.ShowDialog();
    }

public FixedDocumentSequence Document { get; set; }

so here you are mainly :

所以在这里你主要是:

  • Creating an Xps document and storing it in printPreview.xps file,
  • Writing the FlowDocumentcontent into that file,
  • passing the XpsDocumentto the PrintWindowin which you will handle the preview and the print actions,
  • 创建 Xps 文档并将其存储在 printPreview.xps 文件中,
  • FlowDocument内容写入该文件,
  • 将 传递XpsDocumentPrintWindow您将在其中处理预览和打印操作的地方,

here how the PrintWindowlooks like :

这里的PrintWindow样子:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="1.5*"/>
    </Grid.ColumnDefinitions>
    <StackPanel>
        <Button Content="Print" Click="Button_Click"></Button>
        <!--Other print operations-->
    </StackPanel>
    <DocumentViewer  Grid.Column="1" x:Name="PreviewD">            
    </DocumentViewer>
</Grid>

and the code behind :

以及背后的代码:

public partial class PrintWindow : Window
{
    private FixedDocumentSequence _document;
    public PrintWindow(FixedDocumentSequence document)
    {
        _document = document;
        InitializeComponent();
        PreviewD.Document =document;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        //print directly from the Xps file 
    }
}

the final result looks something like this

最终结果看起来像这样

enter image description here

enter image description here

Ps: to use XpsDocument you should add a reference to System.Windows.Xps.Packaging namespace

Ps:要使用 XpsDocument,您应该添加对System.Windows.Xps.Packaging 命名空间的引用

回答by Noam M

Your requirements can be achieved in a number of ways, for instance, you can use the PrintDialogclass. The following MSDN pages contains descriptions as well as some sample code:

您的要求可以通过多种方式实现,例如,您可以使用PrintDialog该类。以下 MSDN 页面包含说明以及一些示例代码:

Alternatively it can be achieved via C# ,for example, consider the next code:

或者,它可以通过 C# 实现,例如,考虑下一个代码:

 private string _previewWindowXaml =
    @"<Window
        xmlns ='http://schemas.microsoft.com/netfx/2007/xaml/presentation'
        xmlns:x ='http://schemas.microsoft.com/winfx/2006/xaml'
        Title ='Print Preview - @@TITLE'
        Height ='200' Width ='300'
        WindowStartupLocation ='CenterOwner'>
                      <DocumentViewer Name='dv1'/>
     </Window>";

internal void DoPreview(string title)
{
    string fileName = System.IO.Path.GetRandomFileName();
    FlowDocumentScrollViewer visual = (FlowDocumentScrollViewer)(_parent.FindName("fdsv1"));

    try
    {
        // write the XPS document
        using (XpsDocument doc = new XpsDocument(fileName, FileAccess.ReadWrite))
        {
            XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(doc);
            writer.Write(visual);
        }

        // Read the XPS document into a dynamically generated
        // preview Window 
        using (XpsDocument doc = new XpsDocument(fileName, FileAccess.Read))
        {
            FixedDocumentSequence fds = doc.GetFixedDocumentSequence();

            string s = _previewWindowXaml;
            s = s.Replace("@@TITLE", title.Replace("'", "&apos;"));

            using (var reader = new System.Xml.XmlTextReader(new StringReader(s)))
            {
                Window preview = System.Windows.Markup.XamlReader.Load(reader) as Window;

                DocumentViewer dv1 = LogicalTreeHelper.FindLogicalNode(preview, "dv1") as DocumentViewer;
                dv1.Document = fds as IDocumentPaginatorSource;


                preview.ShowDialog();
            }
        }
    }
    finally
    {
        if (File.Exists(fileName))
        {
            try
            {
                File.Delete(fileName);
            }
            catch
            {
            }
        }
    }
} 

What it does: it actually prints the content of a visual into an XPS document. Then it loads the "printed" XPS document and displays it in a very simple XAML file that is stored as a string, rather than as a separate module, and loaded dynamically at runtime. The resulting Window has the DocumentViewer buttons: print, adjust-to-max-page-width, and so on.

它的作用:它实际上将视觉内容打印到 XPS 文档中。然后它加载“打印的”XPS 文档并将其显示在一个非常简单的 XAML 文件中,该文件存储为一个字符串,而不是一个单独的模块,并在运行时动态加载。生成的窗口具有 DocumentViewer 按钮:打印、调整到最大页面宽度等。

I also added some code to hide the Search box. See this answer to WPF: How can I remove the searchbox in a DocumentViewer?for how I did that.

我还添加了一些代码来隐藏搜索框。请参阅WPF 的答案:How can I remove the searchbox in a DocumentViewer? 我是怎么做到的。

The effect is like this:

效果是这样的:

alt text

alt text

The XpsDocument can be found in the ReachFramework dll and the XpsDocumentWriter can be found in the System.Printing dll both of which must be added as references to the project

XpsDocument 可以在 ReachFramework dll 中找到,XpsDocumentWriter 可以在 System.Printing dll 中找到,两者都必须添加为对项目的引用