Как создать "предварительный просмотр" FlowDocument в приложении WPF?

Различные приложения WPF отображают FlowDocument's. Я могу напечатать их, используя подход, описанный в ответе на Печать WPF FlowDocument.

Теперь я хотел бы добавить возможность "предварительного просмотра". В обычном случае я печатаю FlowDocument, который отображается в окне, и тогда мне не нужен предварительный просмотр. Но в некоторых случаях FlowDocument для печати создается на лету в памяти. И в этих случаях я хотел бы показать это перед печатью.

Теперь я могу открыть новое окно и отобразить FlowDocument, но

  1. Я хочу, чтобы предварительный просмотр действительно ощущался как часть операции печати, а не просто как другое окно в приложении.

  2. Я не хочу нормальный FlowDocument в FlowDocumentScrollViewer. Вместо того, чтобы быть "любого размера", он должен быть ограничен размером бумаги, определенным соотношением HxW и разбит на страницы.

Предложения?

  • я должен просто использовать стандартное окно, и в таком случае, как мне обеспечить правильное соотношение FlowDocument?

  • Есть ли более "интегрированный" способ сделать предварительный просмотр в рамках интерфейса PrintDialog, который является частью Windows?

Спасибо

2 ответа

Решение

Взяв подсказку из комментария, добавленного к моему вопросу, я сделал это:

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: печать, настройка максимальной ширины страницы и т. Д.

Я также добавил код, чтобы скрыть окно поиска. Посмотрите этот ответ для WPF: Как я могу удалить окно поиска в DocumentViewer? за то, как я это сделал.

Эффект таков:

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

XpsDocument можно найти в dll ReachFramework, а XpsDocumentWriter можно найти в System.Printing dll, оба из которых должны быть добавлены в качестве ссылок на проект

Элемент управления "FlowDocumentPageViewer" является основой для элемента управления "Предварительный просмотр", используемого в одном из наших проектов. Вот XAML элемента управления "DocumentPreviewer" (извинения за длину - 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, где вы можете печатать напрямую или просматривать (с указанным выше интерфейсом) и печатать оттуда.,

Другие вопросы по тегам