代码之家  ›  专栏  ›  技术社区  ›  Cheeso

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

  •  12
  • Cheeso  · 技术社区  · 15 年前

    矿井显示流程文件的各种WPF应用。我能够使用中描述的方法打印它们 the answer to Printing a WPF FlowDocument

    现在我想添加一个“打印预览”功能。在正常情况下,我正在打印窗口中显示的FlowDocument,因此不需要打印预览。但在某些情况下,要打印的流程文档是在内存中动态构建的。我想在打印之前把它放在这些箱子里。

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

    1. 我想让预览真的 感觉 就像它是打印操作的一部分,而不仅仅是应用程序中的另一个窗口。

    2. 我不想在FlowDocumentScrollViewer中使用普通的FlowDocument。它不是“任何尺寸”,而是需要限制为纸张的尺寸、特定的HxW比率和分页。

    2 回复  |  直到 8 年前
        1
  •  22
  •   Glorfindel Doug L.    6 年前

    从添加到我问题中的评论中得到暗示,我这样做了:

    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

        2
  •  2
  •   Daniel Pratt    15 年前

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