【问题标题】:Print dialog and print prewiew dialog for WPFWPF 的打印对话框和打印预览对话框
【发布时间】:2015-07-05 16:41:51
【问题描述】:

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

此时我使用 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);
}

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

【问题讨论】:

    标签: c# wpf xaml printing print-preview


    【解决方案1】:

    这是 print prewiw 的示例解决方案: MainWindow.xaml

    <FlowDocumentScrollViewer>
            <FlowDocument x:Name="FD">
                <Paragraph>                    
                    <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" Click="Button_Click"></Button>
    

    MainWindow.xaml.cs

     private void Button_Click(object sender, RoutedEventArgs e)
            {
                //Fix the size of the document
                PrintDialog pd = new PrintDialog();
                FD.PageHeight = pd.PrintableAreaHeight;
                FD.PageWidth = pd.PrintableAreaWidth;
                FD.PagePadding = new Thickness(30);
                FD.ColumnGap = 0;
                FD.ColumnWidth = pd.PrintableAreaWidth;
    
                ////to print the document directly without print preview
                //IDocumentPaginatorSource dps = FD;
                //pd.PrintDocument(dps.DocumentPaginator, "flow doc");
    
                //Print preview the document before printing
                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 PrintPreview(Document);
                windows.ShowDialog();
            }
    

    PrintPreview.xaml

    <Window ........>        
        <DocumentViewer x:Name="PreviewD" />    
    </Window>
    

    PrintPreview.xaml.cs

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

    【讨论】:

      【解决方案2】:

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

      也可以通过 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
                  {
                  }
              }
          }
      } 
      

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

      我还添加了一些代码来隐藏搜索框。请参阅 this answer to WPF: How can I remove the searchbox in a DocumentViewer? 了解我是如何做到的。

      效果是这样的:

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

      【讨论】:

      • 你能把PrintPreviewDialogPrintPreviewDialog结合起来吗?就像 Google Chrome 或 Word 一样。
      • 什么是_parent和fdsv1
      • WPF PrintDialog 类是否允许预览?
      【解决方案3】:

      您要做的是从您要打印的内容中创建一个xpsDocumentflowDocument)并使用该XpsDocument 预览内容,例如假设您有以下内容Xaml,带有您要打印其内容的flowDocument

       <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>
      

      flowDocument 样本来自Wpf tutorials site

      打印按钮 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; }
      

      所以你主要在这里:

      • 创建 Xps 文档并将其存储在 printPreview.xps 文件中,
      • FlowDocument 内容写入该文件,
      • XpsDocument 传递给PrintWindow,您将在其中 处理预览和打印操作,

      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>
      

      以及背后的代码:

      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 
          }
      }
      

      最终的结果是这样的

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

      【讨论】:

      • 所以没有办法使用标准化的打印对话框来做到这一点?
      • 这很好,使用内存流而不是文件进行 XPS 渲染可能更好......(消除对文件系统的依赖)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-12
      • 2015-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多