如何在WPF应用程序中生成FlowDocument的“打印预览”?

我的各种WPF应用程序显示FlowDocument的。 我可以使用打印WPF FlowDocument 的答案中描述的方法来打印它们。

现在我想添加一个“打印预览”function。 在正常情况下,我正在打印显示在窗口中的FlowDocument,所以我不需要打印预览。 但是在某些情况下,要打印的FlowDocument在内存中即时构build。 在这些情况下,我想在打印之前显示它。

现在,我当然可以popup一个新窗口并显示FlowDocument,但是

  1. 我希望预览真正感觉它是打印操作的一部分,而不是应用程序中的另一个窗口。

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

build议?

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

  • 有没有更多的“集成”的方式来作为Windows的一部分的PrintDialog UI的范围内预览?

谢谢

从添加到我的问题的意见提示,我做到了这一点:

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文件中,该文件以stringforms存储,而不是作为单独的模块存储,并在运行时dynamic加载。 生成的窗口具有DocumentViewerbutton:print,调整到最大页面宽度等等。

我还添加了一些代码来隐藏search框。 看到这个WPF的答案:如何删除DocumentViewer中的search框? 我是怎么做到的

效果是这样的:

替代文字160wpb4.jpg

可以在ReachFramework dll中findXpsDocument,并且可以在System.Printing dll中findXpsDocumentWriter,两者都必须作为项目的引用添加

“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应用程序有相似的行为,你可以直接打印或预览(显示上面的界面)并从那里打印。