OK, let's look at a simple sample here and start with a UIElement we want to render
<
Grid
x:Name
=
"elementToRender"
Width
"500"
Height
>
Image
Source
"turtle.jpg"
Stretch
"UniformToFill"
/>
TextBlock
Text
"This text is on top of the image"
FontSize
"40"
TextWrapping
"Wrap"
Margin
"50"
</
The output in the application looks like this: Notice that the Grid-element in the snippet above has the name "elementToRender", so we can access it in C# with that name. Now let's fill a RenderTargetBitmap with it.
To fill a RenderTargetBitmap with a UIElement, you just call it's RenderAsync-method. Pass in the UIElement you want to render into the RenderTargetBitmap. In the example here we're using the Grid with the name "elementToRender":
var bitmap =
new
RenderTargetBitmap();
await bitmap.RenderAsync(elementToRender);
As the RenderTargetBitmap-class directly inherits from ImageSource, you can just assign in e.g. to the Source-Property of any Image-Element defined in your UI. Let's assume you've an Image-Element named image:
"image"
"200"
.../>
private
async
void
ButtonRender_Click(
object
sender, RoutedEventArgs e)
{
image.Source = bitmap;
}
// Get the pixels
IBuffer pixelBuffer = await bitmap.GetPixelsAsync();
byte
[] pixels = pixelBuffer.ToArray();
public
sealed
partial
class
MainPage : Page
...
protected
override
OnNavigatedTo(NavigationEventArgs e)
base
.OnNavigatedTo(e);
DataTransferManager.GetForCurrentView().DataRequested+= MainPage_DataRequested;
OnNavigatedFrom(NavigationEventArgs e)
.OnNavigatedFrom(e);
DataTransferManager.GetForCurrentView().DataRequested -= MainPage_DataRequested;
MainPage_DataRequested(DataTransferManager sender, DataRequestedEventArgs args)
var deferral = args.Request.GetDeferral();
// 1. Get the pixels
// 2. Write the pixels to a InMemoryRandomAccessStream
var stream =
InMemoryRandomAccessStream();
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.BmpEncoderId, stream);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, (
uint
)bitmap.PixelWidth, (
)bitmap.PixelHeight, 96, 96,
pixels);
await encoder.FlushAsync();
stream.Seek(0);
// 3. Share it
args.Request.Data.SetBitmap(RandomAccessStreamReference.CreateFromStream(stream));
args.Request.Data.Properties.Description =
"RenderTargetBitmap-Sample"
;
args.Request.Data.Properties.Title =
"Wow, here the shared Bitmap :-)"
deferral.Complete();
In this section you'll learn about an issue or maybe an unexpected behavior of the RenderTargetBitmap if you're used to WPFs RenderTargetBitmap-class. I first want to describe the issue and then show you a workaround.
When you render an element that has a child-element crossing its borders, your RenderTargetBitmap gets bigger. This is the behavior in Windows Store Apps. In WPF your RenderTargetBitmap will still have the same size as the element to render, and the child-element crossing the borders is just clipped. Let's look at an example. Let’s say we’ve the following element to render with a transformed element inside:
"100" Width="500"
Background
"Red"
Rectangle
Fill
"Yellow"
"100"
Rectangle.RenderTransform
TranslateTransform
Y
<Grid x:Name=
Height=
Width=
Background=
<Grid.Clip>
<RectangleGeometry Rect=
"0 0 500 100"
</Grid.Clip>
<Rectangle Fill=
<Rectangle.RenderTransform>
<TranslateTransform Y=
</Rectangle.RenderTransform>
</Rectangle>
</Grid>
As you've seen in the previous section, the thought workaround using the Clip-Property didn't work. The RenderTargetBitmap is still bigger as the clipped element to render (the Grid). But the Clip-Property is the first step to a solution. The second step is to add an additional element to the visual tree that contains your clipped element. Then render that additional element, and you're fine. Let's walk through this. Ok, the first step we already did in the previous section. We clipped our Grid by using its Clip-Property (defined in UIElement)
Grid.Clip
RectangleGeometry
Rect
"oldElementToRender"