如何将 xaml 页面转换为 pdf 文件并在 UWP 应用程序内的 pdf 查看器中显示?

How to convert a xaml page to pdf file and show it in a pdf viewer inside a UWP application?

我正在尝试使用 Syncfusion PDF 查看器,但为了使用它,我最终必须将 xaml 页面另存为 pdf 文件。我该怎么做?

我遵循了这个 link 但它没有给我想要的东西。 XAML to PDF Conversion

我正在尝试使用下面的代码从我的视图模型 class 中保存一个 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 页,因此列表不会完全可见。

提前致谢。

您可以直接将 pdf 文件保存在 Windows.Storage.ApplicationData.Current.LocalFolder 中并使用 Windows.Data.Pdf Namespace API 在应用程序中显示 pdf,而不是调用 Windows.System.Launcher.LaunchFileAsync(stFile) 方法启动其他应用程序打开 pdf文件。

有关详细信息,请参阅 UWP PDF document sample