You can use the RenderTargetBitmap class. Create an extension method which takes any UIElement of which you want to create an image (in this case it will be your page) and a file into which the generated image will be saved. The method return true if successful:
public static async Task<bool> SaveVisualElementToFile(this UIElement element, StorageFile file)
{
try
{
var renderTargetBitmap = new RenderTargetBitmap();
await renderTargetBitmap.RenderAsync(element);
var pixels = await renderTargetBitmap.GetPixelsAsync();
using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
byte[] bytes = pixels.ToArray();
encoder.SetPixelData(
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Straight,
(uint)renderTargetBitmap.PixelWidth,
(uint)renderTargetBitmap.PixelHeight,
DisplayInformation.GetForCurrentView().LogicalDpi,
DisplayInformation.GetForCurrentView().LogicalDpi,
bytes);
await encoder.FlushAsync();
}
return true;
}
catch (Exception)
{
return false;
}
}
You need to make sure that your UIElement is in the visual tree (rendered), otherwise the method will not work.
Then you can call the method like this:
StorageFolder localFolder = ApplicationData.Current.TemporaryFolder;
StorageFile file = await localFolder.CreateFileAsync(ShareSreenshotFileName, CreationCollisionOption.ReplaceExisting);
await view.SaveVisualElementToFile(file);
EDIT:
Your problem appears because the ListView is virtualized and therefore not all items are rendered. You can disable virtualization by using a StackPanel as the items panel of the list view:
<ListView>
<ListView.ItemsStackPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ListView.ItemsStackPanel>
</ListView>
Another problem is if you are passing the container of the listview (grid or whatever it is), only the container bounds will be displayed in the generated image, so you need to pass the ListView reference to the SaveVisualElementToFile method.