首页 > 解决方案 > 提取我的应用程序的每个 XAML 页面的确切内容

问题描述

我有一个UWP包含几页的表单应用程序XAML,用户应该填写每一页,然后保存他填写的内容。

之后,我将数据保存到应用程序LocalStorage,但我还想将每个页面的副本创建到自定义文件夹中,以防本地保存不起作用。

我寻找的是创建一个PDF格式文件,其中包含我的应用程序中每个XAML页面的内容,但我发现它比我想象的要难(不支持PDF生成,非常昂贵的第 3 部分库,......)。

我还考虑过创建页面的一些图像,但我真的不知道这是否可能。

那么我可以用什么来生成我的应用程序页面的副本并将其保存到LocalStorage(当然没有用户的交互)?

有了RenderTargetBitmap我能够捕获根页面,但是每当我尝试在 XAML 树中捕获另一个东西时,它都会给我一个ArgumentException

页面 XAML :

<Page x:Name="rootPage"
    x:Class="BasePosteMobilite2.Views.InfosPosteView"
    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:postecomponents="using:BasePosteMobilite2.Services.PosteComponents"
    xmlns:utils="using:BasePosteMobilite2.Utils"
    xmlns:converters="using:BasePosteMobilite2.Utils.Converters"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    DataContext="{Binding InfoPosteViewModel, Source={StaticResource Locator}}">

    <Grid 
        x:Name="ContentArea">
        <Pivot x:Name="Items" Margin="0,84,0,0">
            <PivotItem Header="Généralités" x:Uid="InfosPoste_Generalites">
                <Grid>
                    <ScrollViewer>
                        <Grid x:Name="gridGeneralites" Background="{ThemeResource SystemControlPageBackgroundChromeLowBrush}" Padding="0,12,0,12" Margin="0,0,0,12">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition/>
                                <ColumnDefinition/>
                                <ColumnDefinition/>
                                <ColumnDefinition/>
                                <ColumnDefinition/>
                                <ColumnDefinition/>
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                            </Grid.RowDefinitions>

                            [content]

                            </Grid>
                    </ScrollViewer>

                </Grid>
            </PivotItem>

            <PivotItem x:Name="pivotHTA" Header="HTA" x:Uid="InfosPoste_HTA">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition Height="70"/>
                    </Grid.RowDefinitions>
                    <ScrollViewer x:Name="scrollHTA">
                        <ListView x:Name="listHTA" Background="{ThemeResource SystemControlPageBackgroundChromeLowBrush}"
                              ItemsSource="{x:Bind ViewModel.CurrentPoste.Hta, Mode=TwoWay}" Margin="0,0,0,12"
                              SelectionMode="None">
                            <ListView.ItemTemplate>
                                <DataTemplate x:DataType="postecomponents:HTA">
                                    <Grid x:Name="gridHTA" BorderBrush="Silver" BorderThickness="0,0,0,1" Padding="0,24,0,24">
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition/>
                                            <ColumnDefinition/>
                                            <ColumnDefinition/>
                                            <ColumnDefinition/>
                                            <ColumnDefinition/>
                                            <ColumnDefinition/>
                                        </Grid.ColumnDefinitions>
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="Auto"/>
                                            <RowDefinition Height="Auto"/>
                                            <RowDefinition Height="Auto"/>
                                        </Grid.RowDefinitions>

                                        [content]

                                    </Grid>
                                </DataTemplate>
                            </ListView.ItemTemplate>
                        </ListView>
                    </ScrollViewer>
                    <Button x:Name="bAddHTA" Grid.Row="1" HorizontalAlignment="Right" Content="Ajouter HTA" Margin="0,0,0,0" VerticalAlignment="Center" FontSize="16" Click="AddComponentClick"/>

                </Grid>
            </PivotItem>
        </Pivot>

        <TextBlock MaxLines="1" TextTrimming="CharacterEllipsis" HorizontalAlignment="Left" Margin="12,12,0,0" Text="Indice poste :" TextWrapping="Wrap" VerticalAlignment="Top" FontSize="16"/>
        <TextBox x:Name="tbCodePoste" Margin="114,12,0,0" Text="{x:Bind ViewModel.CurrentPoste.CodePoste, Mode=TwoWay}" VerticalAlignment="Top"  FontSize="16" IsTextPredictionEnabled="False" MaxLength="6" CharacterCasing="Upper" HorizontalAlignment="Left" Width="160" KeyUp="Page_KeyUp"/>
        <Button x:Name="bRechercherPoste" Content="Rechercher" Margin="279,12,0,0" VerticalAlignment="Top" Click="BRechercherPoste_Click" FontSize="16" IsDoubleTapEnabled="False" IsHoldingEnabled="False" IsRightTapEnabled="False" Width="117" Height="34" />
        <Button x:Name="bScannerPoste" Content="Scanner code poste" Margin="401,12,0,0" VerticalAlignment="Top" FontSize="16" IsDoubleTapEnabled="False" IsHoldingEnabled="False" IsRightTapEnabled="False" Width="170" Height="34" Click="BScannerPoste_Click" />
        <Button x:Name="bRAZ" Content="Remise à zéro" Margin="576,12,0,0" VerticalAlignment="Top" FontSize="16" IsDoubleTapEnabled="False" IsHoldingEnabled="False" IsRightTapEnabled="False" Width="170" Height="34" Click="BRAZ_Click"/>
        <Grid x:Name="spWarning" Margin="752,16,208,0" VerticalAlignment="Top" Height="63" Visibility="Collapsed">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Image HorizontalAlignment="Left" VerticalAlignment="Top" Source="/Assets/warning.png" Stretch="Fill" Width="24" Height="24"></Image>
            <TextBlock x:Name="tbWarning" Text="Poste introuvable" FontSize="16" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="4,0,0,0" TextWrapping="Wrap" Grid.Column="1"/>
        </Grid>
        <Button x:Name="bEnregistrer" HorizontalAlignment="Right" VerticalAlignment="Top" Content="Enregistrer modifications" Margin="0,12,12,0" Width="191" Click="BEnregistrer_Click"/>
    </Grid>
</Page>

SaveXamlToPng 类:

public static class SaveXamlAsPng
{
    public static async Task XAMLtoPNG(UIElement element, string filename)
    {
        try
        {
            RenderTargetBitmap rtb = new RenderTargetBitmap();
            await rtb.RenderAsync(element);

            var pixelBuffer = await rtb.GetPixelsAsync();
            var pixels = pixelBuffer.ToArray();
            var displayInformation = DisplayInformation.GetForCurrentView();
            var file = await ApplicationData.Current.LocalFolder.CreateFileAsync(filename + ".png", CreationCollisionOption.GenerateUniqueName);
            using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite))
            {
                var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
                encoder.SetPixelData(BitmapPixelFormat.Bgra8,
                                        BitmapAlphaMode.Premultiplied,
                                        (uint)rtb.PixelWidth,
                                        (uint)rtb.PixelHeight,
                                        displayInformation.RawDpiX,
                                        displayInformation.RawDpiY,
                                        pixels);
                await encoder.FlushAsync();
            }
        }
        catch (Exception e)
        {
            Debug.WriteLine(e.Message);
        }
    }
}

使用该方法单击按钮:

private async void BEnregistrer_Click(object sender, RoutedEventArgs e)
{
    await SaveXamlAsPng.XAMLtoPNG(pivotHTA, "test");
}

因此,例如,我可以从中得到一个.pngrootPage但是当我在其中使用pivotHTA作为参数时,renderAsync()它向我抛出了一个ArgumentException说法System.ArgumentException : 'The specified buffer index is not within the buffer capacity.'

注意:我不知道它是否会改变任何东西,但 XAML 页面位于NavigationView

标签: c#xamluwp

解决方案


我还考虑过创建页面的一些图像,但我真的不知道这是否可能。

是的。这当然是可能的。您可以使用带有相关方法的RenderTargetBitmap 类将 XAML 呈现为位图图像并将其保存在 StorageFile 中。

请检查我在线程Save Grid as png上的代码。

private async void saveButton_Click(object sender, RoutedEventArgs e)
{
    RenderTargetBitmap rtb = new RenderTargetBitmap();
    await rtb.RenderAsync(pivotHTA);

    var pixelBuffer = await rtb.GetPixelsAsync();
    var pixels = pixelBuffer.ToArray();
    var displayInformation = DisplayInformation.GetForCurrentView();
    var file = await ApplicationData.Current.LocalFolder.CreateFileAsync("testImage" + ".png", CreationCollisionOption.ReplaceExisting);
    using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite))
    {
        var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
        encoder.SetPixelData(BitmapPixelFormat.Bgra8,
                             BitmapAlphaMode.Premultiplied,
                             (uint)rtb.PixelWidth,
                             (uint)rtb.PixelHeight,
                             displayInformation.RawDpiX,
                             displayInformation.RawDpiY,
                             pixels);
        await encoder.FlushAsync();
    }
}
<Grid 
    x:Name="ContentArea">
    <Pivot x:Name="Items" Margin="0,84,0,0">
        <PivotItem Header="Généralités" x:Uid="InfosPoste_Generalites">
            <Grid>
            </Grid>
        </PivotItem>
        <PivotItem x:Name="pivotHTA" Header="HTA" x:Uid="InfosPoste_HTA">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition Height="70"/>
                </Grid.RowDefinitions>
                <Image Source="Assets/panda.jpg">
                </Image>
            </Grid>
        </PivotItem>
    </Pivot>
    <Button Content="render" Click="Button_Click"></Button>
</Grid>

推荐阅读