Как преобразовать страницу xaml в файл PDF и показать ее в программе просмотра PDF в приложении UWP? - PullRequest
1 голос
/ 01 апреля 2019

Я пытаюсь использовать средство просмотра PDF Syncfusion, но для того, чтобы использовать его, мне нужно в конечном итоге сохранить страницу xaml в виде файла PDF. Как мне это сделать?

Я перешел по этой ссылке, но она не дает мне то, что я хочу. Преобразование XAML в PDF

Я пытаюсь описать код ниже, чтобы сохранить страницу xaml [ new GenericManifestPDF (_manifestPDFDataModel); ] из класса моей модели представления и получаю эту ошибку: ' Значение не попадает в ожидаемый диапазон 'в этой строке await renderTargetBitmap.RenderAsync (new GenericManifestPDF (_manifestPDFDataModel));

   PdfDocument document = new PdfDocument();
   //Add a new page
   PdfPage page = document.Pages.Add();
   //Initialize render to bitmap
   var logicalDpi = DisplayInformation.GetForCurrentView().LogicalDpi;
   var renderTargetBitmap = new RenderTargetBitmap();
   //Create a Bitmap from XAML page
   await renderTargetBitmap.RenderAsync(new GenericManifestPDF(_manifestPDFDataModel));
   var pixelBuffer = await renderTargetBitmap.GetPixelsAsync();
   //Save the XAML in bitmap image
   using (var stream = new Windows.Storage.Streams.InMemoryRandomAccessStream())
   {
   var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
   encoder.SetPixelData(
   BitmapPixelFormat.Bgra8,
   BitmapAlphaMode.Ignore,
   (uint)renderTargetBitmap.PixelWidth,
   (uint)renderTargetBitmap.PixelHeight,
   logicalDpi,
   logicalDpi,
   pixelBuffer.ToArray());
   await encoder.FlushAsync();
   //Load and draw the bitmap image in PDF
   PdfImage img = PdfImage.FromStream(stream.AsStream());
   if (img.Width > img.Height)
      document.PageSettings.Orientation = PdfPageOrientation.Portrait;
          else                                                                                      document.PageSettings.Orientation = PdfPageOrientation.Landscape;
       var section = document.Sections.Add();
       section.PageSettings.Size = new SizeF(img.Width, img.Height);
       page = section.Pages.Add();
       page.Graphics.DrawImage(img, new RectangleF(0, 0, img.Width, img.Height));
                                        }
        //Save the document
        MemoryStream docStream = new MemoryStream();
        document.Save(docStream);
        //Close the document
        document.Close(true);
        Save(docStream, "SampleManifest.pdf");

Это метод сохранения:

 public async void Save(Stream stream, string filename)
    {
        stream.Position = 0;
        StorageFile stFile;
        if (!(Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons")))
        {
            FileSavePicker savePicker = new FileSavePicker();
            savePicker.DefaultFileExtension = ".pdf";
            savePicker.SuggestedFileName = "Output";
            savePicker.FileTypeChoices.Add("Adobe PDF Document", new List<string>() { ".pdf" });
            stFile = await savePicker.PickSaveFileAsync();
        }
        else
        {
            StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;
            stFile = await local.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
        }
        if (stFile != null)
        {
            Windows.Storage.Streams.IRandomAccessStream fileStream = await stFile.OpenAsync(FileAccessMode.ReadWrite);
            Stream st = fileStream.AsStreamForWrite();
            st.Write((stream as MemoryStream).ToArray(), 0, (int)stream.Length);
            st.Flush();
            st.Dispose();
            fileStream.Dispose();
            MessageDialog msgDialog = new MessageDialog("Do you want to view the Document?", "File created.");
            UICommand yesCmd = new UICommand("Yes");
            msgDialog.Commands.Add(yesCmd);
            UICommand noCmd = new UICommand("No");
            msgDialog.Commands.Add(noCmd);
            IUICommand cmd = await msgDialog.ShowAsync();
            if (cmd == yesCmd)
            {
                // Launch the retrieved file
                bool success = await Windows.System.Launcher.LaunchFileAsync(stFile);
            }
        }
    }

Вот как я связываю данные в верхнем упомянутом конструкторе страницы:

public GenericManifestPDF(ManifestPDFDataModel PDFDataModel)
    {
        this.InitializeComponent();
        Function.Text = "Function :" + PDFDataModel.Function;
        Counts.Text = "Count :" + PDFDataModel.Counts;
        PrintedValue.Text = "Printed :" + PDFDataModel.CreationDate;
        RouteValue.Text = "Route :" + PDFDataModel.Route;
        BatchIDValue.Text = "Batch :" + PDFDataModel.BatchID;
        BatchBarcodeText.Text = "Batch Barcode :" + PDFDataModel.Barcode;
        IBarcodeWriter writer = new BarcodeWriter
        {
            Format = BarcodeFormat.CODE_39,
            Options = new ZXing.Common.EncodingOptions
            {
                Height = 100,
                Width = 450
            }
        };

        var result = writer.Write(PDFDataModel.Barcode);
        BarcodeImage.Source = result;
        PDFItemsList.ItemsSource = PDFDataModel.ItemsPDFList;
    }

Это код xaml страницы:

<Grid x:Name="ManifestPDFGrid">
    <Grid.RowDefinitions>
        <RowDefinition Height="30*"/>
        <RowDefinition Height="70*"/>
    </Grid.RowDefinitions>
    <Grid BorderBrush="Black" BorderThickness="2" Margin="30">
        <Grid.RowDefinitions>
            <RowDefinition Height="80*"/>
            <RowDefinition Height="20*"/>
        </Grid.RowDefinitions>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                </Grid.RowDefinitions>
                <TextBlock Text="Manifest PDF Report" Foreground="Black" FontWeight="Bold" Margin="20,20,0,0"/>
                <TextBlock x:Name="Function" Foreground="Black" Grid.Row="1" FontWeight="Bold" Margin="20,20,0,0"/>
                <TextBlock x:Name="Counts" Grid.Row="2" Foreground="Black" FontWeight="Bold" Margin="20,20,0,0"/>
            </Grid>
            <Grid Grid.Column="1">
                <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                </Grid.RowDefinitions>
                <TextBlock x:Name="PrintedValue" Foreground="Black" FontWeight="Bold" Margin="20,20,0,0"/>
                <TextBlock x:Name="RouteValue" Foreground="Black" Grid.Row="1" FontWeight="Bold" Margin="20,20,0,0"/>
                <TextBlock x:Name="BatchIDValue" Grid.Row="2" Foreground="Black" FontWeight="Bold" Margin="20,20,0,0"/>
            </Grid>
            <Grid Grid.Column="2">
                <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                </Grid.RowDefinitions>
                <Image x:Name="BarcodeImage" Margin="20,0,0,0" HorizontalAlignment="Center"/>
                <TextBlock x:Name="BatchBarcodeText" Grid.Row="1" Foreground="Black" FontWeight="Bold" Margin="20,20,0,0"/>
            </Grid>
        </Grid>
        <Grid Grid.Row="2">
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <TextBlock Text="Delivered By :" Foreground="Black" Margin="20,0,0,0" VerticalAlignment="Center"/>
            <TextBlock Text="Batch Delivery Time :" Foreground="Black" Grid.Column="1" Margin="20,0,0,0" VerticalAlignment="Center"/>
        </Grid>
    </Grid>
    <Grid Grid.Row="2">
        <Grid.RowDefinitions>
            <RowDefinition Height="10*"/>
            <RowDefinition Height="90*"/>
        </Grid.RowDefinitions>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <TextBlock FontWeight="Bold" Text="Carrier/PKG/BILL#" Foreground="Black" TextDecorations="Underline" Margin="20,20,0,0"/>
            <TextBlock FontWeight="Bold" Grid.Column="1" Foreground="Black" TextDecorations="Underline" Text="Location/Item Type" Margin="20,20,0,0"/>
            <TextBlock FontWeight="Bold" Grid.Column="2" Foreground="Black" TextDecorations="Underline" Text="Deliver To/ Sender" Margin="20,20,0,0"/>
            <TextBlock FontWeight="Bold" Grid.Column="3" Foreground="Black" TextDecorations="Underline" Text="DATE/TIME/PO/Control#" Margin="20,20,0,0"/>
        </Grid>
        <ListView Grid.Row="1" x:Name="PDFItemsList" IsItemClickEnabled="False">
            <ListView.ItemContainerStyle>
                <Style TargetType="ListViewItem">
                    <Setter Property="BorderThickness" Value="0,0,0,1" />
                    <Setter Property="BorderBrush" Value="Black"/>
                    <Setter Property="Width" Value="Auto"/>
                </Style>
            </ListView.ItemContainerStyle>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ContentControl Style="{StaticResource EmptyContentControlStyle}">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="1*"/>
                                <ColumnDefinition Width="1*"/>
                                <ColumnDefinition Width="1*"/>
                                <ColumnDefinition Width="1*"/>
                            </Grid.ColumnDefinitions>
                            <Grid>
                                <Grid.RowDefinitions>
                                    <RowDefinition/>
                                    <RowDefinition/>
                                    <RowDefinition/>
                                </Grid.RowDefinitions>
                                <TextBlock Text="{Binding CarrierName}" Foreground="Black" Margin="20,20,0,0"/>
                                <TextBlock Text="{Binding PackageID}" Foreground="Black" Grid.Row="1" Margin="20,20,0,0"/>
                                <TextBlock Text="{Binding Bill}" Foreground="Black" Grid.Row="2" Margin="20,20,0,0"/>
                            </Grid>
                            <Grid Grid.Column="1">
                                <Grid.RowDefinitions>
                                    <RowDefinition/>
                                    <RowDefinition/>
                                    <RowDefinition/>
                                </Grid.RowDefinitions>
                                <TextBlock Text="{Binding Location}" Foreground="Black" Margin="20,20,0,0"/>
                                <TextBlock Text="{Binding ItemType}" Foreground="Black" Grid.Row="1" Margin="20,20,0,0"/>
                                <TextBlock Text="{Binding Quantity}" Foreground="Black" Grid.Row="2" Margin="20,20,0,0"/>
                            </Grid>
                            <Grid Grid.Column="2" HorizontalAlignment="Right">
                                <Grid.RowDefinitions>
                                    <RowDefinition/>
                                    <RowDefinition/>
                                    <RowDefinition/>
                                    <RowDefinition/>
                                </Grid.RowDefinitions>
                                <TextBlock Text="{Binding DeliverTo}" HorizontalAlignment="Right" Foreground="Black" Margin="20,20,0,0"/>
                                <TextBlock Text="{Binding Sender}" HorizontalAlignment="Right" Foreground="Black" Grid.Row="1" Margin="20,20,0,0"/>
                                <TextBlock Text="" Foreground="Black" HorizontalAlignment="Right" TextDecorations="Underline" Grid.Row="2" Margin="20,20,0,0"/>
                                <TextBlock Text="Signature" HorizontalAlignment="Right" Foreground="Black" FontWeight="ExtraLight" Grid.Row="3" Margin="20,20,0,0"/>
                            </Grid>
                            <Grid Grid.Column="3" HorizontalAlignment="Right">
                                <Grid.RowDefinitions>
                                    <RowDefinition/>
                                    <RowDefinition/>
                                    <RowDefinition/>
                                    <RowDefinition/>
                                    <RowDefinition/>
                                </Grid.RowDefinitions>
                                <TextBlock Text="{Binding CreationDate}" HorizontalAlignment="Right" Foreground="Black" Margin="20,20,0,0"/>
                                <TextBlock Text="{Binding PONumber}" HorizontalAlignment="Right" Grid.Row="1" Foreground="Black" Margin="20,20,0,0"/>
                                <TextBlock Text="{Binding ControlNumber}" HorizontalAlignment="Right" Grid.Row="2" Foreground="Black" Margin="20,20,0,0"/>
                                <TextBlock Text="" Foreground="Black" TextDecorations="Underline" Grid.Row="3" Margin="20,20,0,0"/>
                                <TextBlock Text="Print Name Here" HorizontalAlignment="Right" Foreground="Black" FontWeight="ExtraLight" Grid.Row="4" Margin="20,20,0,0"/>
                            </Grid>
                        </Grid>
                    </ContentControl>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Grid>

Я могу сохранить его в формате PDF, но он не отображается должным образом, я думаю, что мне нужно что-то изменить здесь

  using (var stream = new Windows.Storage.Streams.InMemoryRandomAccessStream())
                                        {
                                            var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
                                            encoder.SetPixelData(
                                            BitmapPixelFormat.Bgra8,
                                            BitmapAlphaMode.Ignore,
                                            (uint)renderTargetBitmap.PixelWidth,
                                            (uint)renderTargetBitmap.PixelHeight,
                                            logicalDpi,
                                            logicalDpi,
                                            pixelBuffer.ToArray());
                                            await encoder.FlushAsync();
                                            //Load and draw the bitmap image in PDF
                                            PdfImage img = PdfImage.FromStream(stream.AsStream());
                                            if (img.Width > img.Height)
                                                document.PageSettings.Orientation = PdfPageOrientation.Portrait;
                                            else
                                                document.PageSettings.Orientation = PdfPageOrientation.Landscape;
                                            var section = document.Sections.Add();
                                            section.PageSettings.Size = new SizeF(img.Width, img.Height);
                                            PdfPage page = section.Pages.Add();
                                            page.Graphics.DrawImage(img, new RectangleF(0, 0, img.Width, img.Height));
                                        }

Единственная проблема, с которой я сталкиваюсь сейчас, - это как генерировать страницы PDF в соответствии с элементами представления списка. Приведенный выше код генерирует только 1 страницу каждый раз, поэтому список не будет виден полностью.

Заранее спасибо.

1 Ответ

0 голосов
/ 02 апреля 2019

Вы можете напрямую сохранить PDF-файл в Windows.Storage.ApplicationData.Current.LocalFolder и использовать Windows.Data.Pdf Namespace API для отображения PDF в приложении, вместо вызова Windows.System.Launcher.LaunchFileAsync(stFile) метода для запуска другого приложения, чтобы открыть PDF-файл.

Подробнее см. Образец документа UWP PDF .

...