2010-02-23 114 views
11

矿山显示FlowDocument的各种WPF应用程序。我可以使用the answer to Printing a WPF FlowDocument中描述的方法打印它们。如何在WPF应用程序中生成FlowDocument的“打印预览”?

现在我想添加一个“打印预览”功能。在正常情况下,我正在打印显示在窗口中的FlowDocument,因此我不需要打印预览。但在某些情况下,要打印的FlowDocument在内存中即时构建。在这些情况下,我想在打印前显示它。

现在,我当然可以弹出一个新窗口,显示的FlowDocument,但

  1. 我想预览真的觉得喜欢它的打印操作的一部分,而不是只是另一个窗口应用程序。

  2. 我不想在FlowDocumentScrollViewer中使用正常的FlowDocument。它不是“任何大小”,而是需要限制在纸张的大小,特定的HxW比率和分页。

建议?

  • 我应该只是使用一个标准的窗口,在这种情况下,如何确保FlowDocument是在适当的比例?

  • 是否有更多的“集成”方式在Windows的一部分PrintDialog UI范围内进行预览?

感谢

+1

嗨切西,这个答案http://stackoverflow.com/questions/584551/how-do-i-do-print-preview-when-using-a -documentpaginator-to-print/587962#587962建议使用XpsDocument与标准窗口结合使用...不想将它写为答案,因为我担心您已经看到该链接。以防万一。干杯:) – Anvaka 2010-02-23 22:11:14

回答

19

以从注释提示加入到我的问题,我这样做:

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?我是如何做到这一点的。

的效果是这样的:

alt text http://i48.tinypic.com/2hzkfat.jpg

的XpsDocument可以在ReachFramework DLL被发现和XpsDocumentWriter可以在系统中找到。打印dll必须添加为项目的参考

+2

我无法使用你的代码,因为我的项目找不到XpsDocument并且无法解决它。我必须将哪些参考添加到我的项目中? – icaptan 2011-09-14 19:21:01

+1

为Cheacho状态添加ReachFramework和System.Printing的引用,然后编写'using System.Windows.Xps;使用System.Windows.Xps.Packaging;使用System.Printing;'来包含。我的编译没有问题。 – 2015-10-26 01:44:09

+2

什么是_parent? – 2016-09-15 06:44:55

2

的“FlowDocumentPageViewer”控制是我们的一个项目中使用的“预览”控制的基础。这里是“DocumentPreviewer”控制的XAML(为长度的歉意 - XAML是不是简洁):

<Control 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:sys="clr-namespace:System;assembly=mscorlib" 
    xmlns:l="clr-namespace:Tyler.ComPort.UI" 
    mc:Ignorable="d" 
    x:Class="Tyler.ComPort.UI.DocumentPreviewer" 
    x:Name="UserControl" 
    Background="Gray" 
    d:DesignWidth="640" d:DesignHeight="480"> 
    <Control.Resources> 
     <ObjectDataProvider x:Key="ViewStyles" MethodName="GetValues" ObjectType="{x:Type sys:Enum}" > 
      <ObjectDataProvider.MethodParameters> 
       <x:Type TypeName="l:ViewType" /> 
      </ObjectDataProvider.MethodParameters> 
     </ObjectDataProvider> 
     <l:EnumMatchVisibilityConverter x:Key="EnumVisibilityConverter" /> 
    </Control.Resources> 
    <Control.Template> 
     <ControlTemplate> 
      <ControlTemplate.Triggers> 
       <Trigger Property="l:DocumentPreviewer.ViewType"> 
        <Trigger.Value> 
         <l:ViewType>Actual</l:ViewType> 
        </Trigger.Value> 
        <Trigger.Setters> 
         <Setter TargetName="ScrollViewer" Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" /> 
         <Setter TargetName="ScrollViewer" Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" /> 
         <Setter TargetName="Viewbox" Property="Viewbox.Stretch" Value="None" /> 
        </Trigger.Setters> 
       </Trigger> 
       <Trigger Property="l:DocumentPreviewer.ViewType"> 
        <Trigger.Value> 
         <l:ViewType>Fit</l:ViewType> 
        </Trigger.Value> 
        <Trigger.Setters> 
         <Setter TargetName="ScrollViewer" Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" /> 
         <Setter TargetName="ScrollViewer" Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled" /> 
         <Setter TargetName="Viewbox" Property="Viewbox.Stretch" Value="Uniform" /> 
        </Trigger.Setters> 
       </Trigger> 
       <Trigger Property="l:DocumentPreviewer.ViewType"> 
        <Trigger.Value> 
         <l:ViewType>Wide</l:ViewType> 
        </Trigger.Value> 
        <Trigger.Setters> 
         <Setter TargetName="ScrollViewer" Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" /> 
         <Setter TargetName="ScrollViewer" Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" /> 
         <Setter TargetName="Viewbox" Property="Viewbox.Stretch" Value="UniformToFill" /> 
        </Trigger.Setters> 
       </Trigger> 
      </ControlTemplate.Triggers> 
      <DockPanel> 
       <ToolBar DockPanel.Dock="Top"> 
        <Button Command="{x:Static ApplicationCommands.Print}" CommandTarget="{Binding ElementName=PageViewer}" Content="Print..." /> 
        <Separator /> 
        <Button Command="{x:Static NavigationCommands.PreviousPage}" CommandTarget="{Binding ElementName=PageViewer}" Content="&lt; Previous" /> 
        <Button Command="{x:Static NavigationCommands.NextPage}" CommandTarget="{Binding ElementName=PageViewer}" Content="Next &gt;" /> 
        <Separator /> 
        <l:ToolBarButtonGroup 
         ItemsSource="{Binding Source={StaticResource ViewStyles}}" 
         SelectedItem="{Binding ViewType, ElementName=UserControl}" 
         IsSynchronizedWithCurrentItem="True" 
         > 
         <l:ToolBarButtonGroup.ItemTemplate> 
          <DataTemplate> 
           <StackPanel Orientation="Horizontal" ToolTip="{Binding}" SnapsToDevicePixels="True"> 
            <Image Source="../Images/actual.png" Visibility="{Binding Converter={StaticResource EnumVisibilityConverter}, ConverterParameter=Actual}" /> 
            <Image Source="../Images/fit.png" Visibility="{Binding Converter={StaticResource EnumVisibilityConverter}, ConverterParameter=Fit}" /> 
            <Image Source="../Images/wide.png" Visibility="{Binding Converter={StaticResource EnumVisibilityConverter}, ConverterParameter=Wide}" /> 
           </StackPanel> 
          </DataTemplate> 
         </l:ToolBarButtonGroup.ItemTemplate> 
        </l:ToolBarButtonGroup> 
       </ToolBar> 
       <ScrollViewer x:Name="ScrollViewer" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Disabled"> 
        <Border 
          BorderBrush="Black" 
          BorderThickness="1" 
          HorizontalAlignment="Center" 
          VerticalAlignment="Top" 
          Background="White" 
          Margin="10"> 
         <Viewbox x:Name="Viewbox" Stretch="Uniform"> 
          <FlowDocumentPageViewer 
           x:Name="PageViewer" 
           Document="{Binding Document, ElementName=UserControl}" 
           Zoom="100" 
           MinZoom="20" 
           MaxZoom="200"> 
           <FlowDocumentPageViewer.Template> 
            <ControlTemplate TargetType="{x:Type FlowDocumentPageViewer}"> 
             <AdornerDecorator> 
              <DocumentPageView FlowDocumentPageViewer.IsMasterPage="True" /> 
             </AdornerDecorator> 
            </ControlTemplate> 
           </FlowDocumentPageViewer.Template> 
          </FlowDocumentPageViewer> 
         </Viewbox> 
        </Border> 
       </ScrollViewer> 
      </DockPanel> 
     </ControlTemplate> 
    </Control.Template> 
</Control> 

在那里你可以把这样的控制是高达当然,你(和你的应用程序),但我们的应用程序与典型的Office应用程序具有类似的行为,您可以直接打印或预览(显示上述界面)并从那里打印。

+0

绝对有趣,但我不想拥有和管理所有的代码!我希望有一个更简单的方法。以下是我如何做到的:http://stackoverflow.com/questions/2322064/how-can-i-produce-a-print-preview-of-a-flowdocument-in-a-wpf-application/2322751#2322751 – Cheeso 2010-03-04 19:08:55