Как я могу произвести “предварительный просмотр” FlowDocument в приложении WPF?

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

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

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

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

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

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

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

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

Спасибо

15
задан Community 23 May 2017 в 10:29
поделиться

2 ответа

В Oracle наиболее полезным является сеанс v $ session о ожидании запущенных сеансов, это означает, что сеанс делает в этот момент (чтение с диска, ожидание блокировки,...)

-121--4501436-

Я разбиваю свои проекты по темам, один каталог для темы:

menu_planner
  src
     recipes
       debug -- contains debug object files and libraries
       release -- contains release object files and libraries
       obsolete -- contains obsolete source files
     ingredients
       debug -- contains debug object files and libraries
       release -- contains release object files and libraries
       obsolete -- contains obsolete source files
     references
       debug -- contains debug object files and libraries
       release -- contains release object files and libraries
       obsolete -- contains obsolete source files
     meals
       debug -- contains debug object files and libraries
       release -- contains release object files and libraries
       obsolete -- contains obsolete source files
     menus
       debug -- contains debug object files and libraries
       release -- contains release object files and libraries
       obsolete -- contains obsolete source files
  docs
     designs

Мой опыт работы с C и C++ показал мне, что заголовочные и исходные файлы должны находиться в одном каталоге. Часто найти файл заголовка сложнее, если он находится не в том же каталоге, что и исходный файл.

Один каталог (папка) на концепцию является хорошей идеей. Любая сложная или составная концепция должна быть разделена на несколько папок или концепций.

Я также научился создавать библиотеки. Я использую библиотеки, чтобы содержать код, который мало меняется. Операция связывания выполняется с библиотеками быстрее, чем с каталогами файлов объектов.

Однако рабочие места (а.к.а. магазины) могут иметь различные правила стиля, которые должны соблюдаться.

-121--3702131-

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

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: print, adjust-to-max-page-width и т. д.

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

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

alt text

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

22
ответ дан 1 December 2019 в 02:55
поделиться

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

3
ответ дан 1 December 2019 в 02:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: