Render xaml content to bitmap

112 Views Asked by At

I work with avalonia and skiasharp in c# project. Is it possible to render xaml content (userControl) to bitmap?

This is my xaml:

<UserControl xmlns="https://github.com/avaloniaui"
            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"
            mc:Ignorable="d" d:DesignWidth="1583" d:DesignHeight="800"
            x:Class="UI.Views.ExportToPng.ExportToPngView"
            xmlns:localization="clr-namespace:Localization;assembly=Localization"
            xmlns:vm="clr-namespace:UI.Views.ExportToPng"
            xmlns:markupextensions="clr-namespace:UI.MarkupExtensions">


 <!-- RESOURCES -->
 <UserControl.Resources>
   <ResourceDictionary>
     <ResourceDictionary.MergedDictionaries>
       <ResourceInclude Source='/UI/Resources/Common/CommonResources.axaml'/>
     </ResourceDictionary.MergedDictionaries>
   </ResourceDictionary>
 </UserControl.Resources>

 <!-- STYLES -->
 <UserControl.Styles>
   <StyleInclude Source='/UI/Resources/Views/TacticalBoardViewStyles.axaml'/>
 </UserControl.Styles>

 <Design.DataContext>
   <vm:ExportToPngViewModel/>
 </Design.DataContext>

 <UserControl.DataContext>
   <vm:ExportToPngViewModel/>
 </UserControl.DataContext>

 <Grid x:Name="MainContent">
   <Grid.RowDefinitions>
     <RowDefinition Height="*"/>
   </Grid.RowDefinitions>

   <!-- Training content -->
   <Grid x:Name="trainingContent" Grid.Row="0" Background="White">
     <Grid.RowDefinitions>
       <RowDefinition Height="*"/>
       <RowDefinition Height="1.7*"/>
       <RowDefinition Height="1.7*"/>
       <RowDefinition Height="1.7*"/>
       <RowDefinition Height="1.7*"/>
     </Grid.RowDefinitions>

     <!-- Title -->
     <Grid Grid.Row="0" Margin="15,5,15,5">
       <Grid.RowDefinitions>
         <RowDefinition Height="*"/>
         <RowDefinition Height="*"/>
       </Grid.RowDefinitions>

       <Grid Grid.Row="0">
         <TextBlock Text="{markupextensions:Localization Label=NewTrainingDialog_Title}" Foreground="Black" FontWeight="DemiBold" TextWrapping="NoWrap" FontSize="16"/>
       </Grid>
       <Border Grid.Row="1" CornerRadius="0,5,5,0" Margin="0,0,0,0">
         <TextBox Classes="TextboxDark" VerticalContentAlignment="Top" Text="{Binding Title,Mode=TwoWay}" TextWrapping="NoWrap" AcceptsReturn="True" HorizontalContentAlignment="Stretch"  Foreground="Black"
                    x:Name="txtTitle" />
       </Border>
     </Grid>

     <!-- Training objectives / goals -->
     <Grid Grid.Row="1" Margin="15,5,15,5" IsVisible="{Binding IsTrainingObjectivesHasValue}">
       <Grid.RowDefinitions>
         <RowDefinition Height="*"/>
         <RowDefinition Height="3*"/>
       </Grid.RowDefinitions>

       <Grid Grid.Row="0">
         <TextBlock Text="{markupextensions:Localization Label=NewTrainingDialog_TrainingObjectives}" Foreground="Black" FontWeight="DemiBold" TextWrapping="NoWrap" FontSize="16"/>
       </Grid>
       <Grid Grid.Row="1">
         <TextBox Classes="TextboxDark" VerticalContentAlignment="Top" Text="{Binding TrainingObjectives,Mode=TwoWay}" TextWrapping="Wrap" AcceptsReturn="True" HorizontalContentAlignment="Stretch"  Foreground="Black"
                    x:Name="txtTrainingObjectives" />
       </Grid>
     </Grid>

     
     <!-- Description -->
     <Grid Grid.Row="2" Margin="15,5,15,5" IsVisible="{Binding IsDescriptionHasValue}">
       <Grid.RowDefinitions>
         <RowDefinition Height="*"/>
         <RowDefinition Height="3*"/>
       </Grid.RowDefinitions>

       <Grid Grid.Row="0">
         <TextBlock Text="{markupextensions:Localization Label=NewTrainingDialog_Description}" Foreground="Black" FontWeight="DemiBold" TextWrapping="NoWrap" FontSize="16"/>
       </Grid>
       <Grid Grid.Row="1">
         <TextBox Classes="TextboxDark" VerticalContentAlignment="Top" Text="{Binding Description,Mode=TwoWay}" TextWrapping="Wrap" AcceptsReturn="True" HorizontalContentAlignment="Stretch"  Foreground="Black"
                    x:Name="txtDescription" />
       </Grid>
     </Grid>


     <!-- Introduction / Warm up -->
     <Grid Grid.Row="3" Margin="15,5,15,5" IsVisible="{Binding IsIntroductionHasValue}">
       <Grid.RowDefinitions>
         <RowDefinition Height="*"/>
         <RowDefinition Height="3*"/>
       </Grid.RowDefinitions>

       <Grid Grid.Row="0">
         <TextBlock Text="{markupextensions:Localization Label=NewTrainingDialog_Introduction}" Foreground="Black" FontWeight="DemiBold" TextWrapping="NoWrap" FontSize="16"/>
       </Grid>
       <Grid Grid.Row="1">
         <TextBox Classes="TextboxDark" VerticalContentAlignment="Top" Text="{Binding Introduction,Mode=TwoWay}" TextWrapping="Wrap" AcceptsReturn="True" HorizontalContentAlignment="Stretch"  Foreground="Black"
                    x:Name="txtIntroduction" />
       </Grid>
     </Grid>

     <!-- Main part -->
     <Grid Grid.Row="4" Margin="15,5,15,5" IsVisible="{Binding IsMainPartHasValue}">
       <Grid.RowDefinitions>
         <RowDefinition Height="*"/>
         <RowDefinition Height="3*"/>
       </Grid.RowDefinitions>

       <Grid Grid.Row="0">
         <TextBlock Text="{markupextensions:Localization Label=NewTrainingDialog_MainPart}" Foreground="Black" FontWeight="DemiBold" TextWrapping="NoWrap" FontSize="16"/>
       </Grid>
       <Grid Grid.Row="1">
         <TextBox Classes="TextboxDark" VerticalContentAlignment="Top" Text="{Binding MainPart,Mode=TwoWay}" TextWrapping="Wrap" AcceptsReturn="True" HorizontalContentAlignment="Stretch"  Foreground="Black"
                    x:Name="txtMainPart" />
       </Grid>
     </Grid>
   </Grid>
 </Grid>
 
</UserControl>

This view is not displayed anywhere, i just wrote the content. ViewModel contains only string properties.

I also wrote two methods:

public static SKBitmap RenderTargetBitmapToSKBitmap(RenderTargetBitmap renderTargetBitmap)
{
    using (MemoryStream stream = new MemoryStream())
    {
        renderTargetBitmap.Save(stream);

        stream.Seek(0, SeekOrigin.Begin);

        return SKBitmap.Decode(stream);
    }
}

private SKBitmap RenderControlToSKBitmap()
{
    ExportToPngView exportToPngView = new ExportToPngView(this);
    exportToPngView.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
    exportToPngView.Arrange(new Rect(exportToPngView.DesiredSize));
           
    var width = exportToPngView.Bounds.Width;
    var height = exportToPngView.Bounds.Height;

    RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap(
        new PixelSize((int)width, (int)height));
    renderTargetBitmap.Render(exportToPngView);

    SKBitmap skBitmap = RenderTargetBitmapToSKBitmap(renderTargetBitmap);
    return skBitmap;
}

As a result I get an empty image (black) without any content. Can someone suggest what I should do to get the content of the xaml control displayed as an image. Thanks a lot.

UPDATE:

Render is not working, and I don't know why...

renderTargetBitmap.Render(ExportToPngDialog);
0

There are 0 best solutions below