【问题标题】:Printing of WPF Window on one page在一页上打印 WPF 窗口
【发布时间】:2011-01-11 15:26:51
【问题描述】:

我可以使用以下代码打印当前的Window

PrintDialog printDialog = new PrintDialog();
if (printDialog.ShowDialog().GetValueOrDefault(false))
{
    printDialog.PrintVisual(this, this.Title); 
}

但是,如果 Window 不适合页面,则会被截断。 如何使 Window 适合页面?
我想我需要先制作一个图形元素并检查此图形是否适合页面,但到目前为止我什么也没找到。

【问题讨论】:

    标签: wpf printing window


    【解决方案1】:

    有一种解决方案,很多人都将其作为自己的解决方案重新发布。可以在这里找到:

    http://www.a2zdotnet.com/View.aspx?id=66

    问题在于它确实会调整您的 UI 大小。因此,下一个链接采用先前的解决方案,并在完成后将大小调整回原始大小。这确实有效,尽管我不禁想到某处可能有更优雅的解决方案:

    http://www.slickthought.net/post/2009/05/26/Visual-Tree-Printing-in-WPF-Applications.aspx


    Slickthought.net 域已失效。 Wayback Machine 来救援。

    https://web.archive.org/web/20130603071346/http://www.slickthought.net/post/2009/05/26/Visual-Tree-Printing-in-WPF-Applications.aspx


    <Button Content="Print" Command="{Binding Path=PrintCommand}" CommandParameter="{Binding ElementName=ReportPanel}"></Button>
    

    这里有两件重要的事情需要注意。首先,我使用 WPF 命令来启动打印过程。您不必这样做,但它让我可以非常干净地将演示者与 UI 联系起来。第二件事是CommandParameter。它传入对 ReportPanel 的引用。 ReportPanel 只是一个 WPF 网格控件,它包含标题 TextBlock 和一个包含实际图表的列表框。简化的 XAML 是:

    <Grid x:Name="ReportPanel" > 
        <Grid.RowDefinitions> 
            <RowDefinition Height="Auto" /> 
            <RowDefinition Height="*" /> 
        </Grid.RowDefinitions> 
        <TextBlock /> 
        <ListBox/>
    </Grid>
    

    建立了 UI,让我们跳转到代码。当用户单击打印按钮时,将执行以下 WPF 命令:

    this.PrintCommand = new SimpleCommand<Grid> 
    { 
        CanExecuteDelegate = execute => true, 
        ExecuteDelegate = grid => 
            { 
                PrintCharts(grid); 
            } 
    };
    

    这是非常简单的东西。 SimpleCommand 实现了 ICommand 接口,并让我传入一些 lambda 表达式,这些表达式定义了在触发此命令时要运行的代码。显然,魔法发生在 PrintCharts(grid) 调用中。下面显示的代码与您在 Pankaj 的文章中找到的代码基本相同,但有一些修改以红色突出显示。

    private void PrintCharts(Grid grid) 
    { 
      PrintDialog print = new PrintDialog(); 
      if (print.ShowDialog() == true) 
      { 
          PrintCapabilities capabilities = print.PrintQueue.GetPrintCapabilities(print.PrintTicket); 
    
          double scale = Math.Min(capabilities.PageImageableArea.ExtentWidth / grid.ActualWidth, 
                                  capabilities.PageImageableArea.ExtentHeight / grid.ActualHeight); 
    
          Transform oldTransform = grid.LayoutTransform; 
    
          grid.LayoutTransform = new ScaleTransform(scale, scale); 
    
          Size oldSize = new Size(grid.ActualWidth, grid.ActualHeight); 
          Size sz = new Size(capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight); 
          grid.Measure(sz); 
          ((UIElement)grid).Arrange(new Rect(new Point(capabilities.PageImageableArea.OriginWidth, capabilities.PageImageableArea.OriginHeight), 
              sz)); 
    
          print.PrintVisual(grid, "Print Results"); 
          grid.LayoutTransform = oldTransform; 
          grid.Measure(oldSize); 
    
          ((UIElement)grid).Arrange(new Rect(new Point(0, 0), 
              oldSize)); 
      } 
    }
    

    好的,这些修改是什么?最明显的是,我用作为命令的一部分传入的 Grid 控件替换了原始 this 对象(在原始代码中表示整个应用程序窗口)的使用。所以所有的测量和转换都是使用网格执行的。另一个变化是我也保存了网格的原始变换和大小。原因是当您转换 Grid 以适应打印页面时,它会导致实际应用程序 UI 也发生变化。这在您的屏幕上看起来不太好,因此在将网格发送到打印机后,我将其转换回其原始屏幕布局。

    【讨论】:

    • 第二个链接不再有效。你能在这里发布解决方案吗?
    • 截至 2015 年 12 月 14 日,两个链接都已失效。这就是为什么我们希望在 SO 上复制此处的内容或至少链接的核心。
    • 如何确保网格宽度和高度缩放以适合纸张?我的网格的一些内容被剪裁了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多