How to make asynchronous calls in your DataRequested handler (XAML)

[This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation]

Here, we'll show you how to produce data asynchronously in response to a DataRequested event. If your app performs any asynchronous operations in response to a DataRequested event, it needs to acquire a DataRequestDeferral object first. Acquiring a deferral lets the system know that your call to SetData might happen after the delegate returns.

Note  If you're just sharing text or a link, you don't need the code in this topic. It's faster to use the SetText and SetUri methods.

 

What you need to know

Technologies

Prerequisites

  • You should be familiar with Visual Studio and its templates.
  • You should be familiar with developing in C#.
  • You should understand how to get files and other data, such as by using FileOpenPicker. You can learn more in Accessing files with file pickers.

Instructions

Step 1: Adding the DataTransfer namespace

First you need to add the right namespaces to your app so you can create and process the objects related to sharing. At a minimum, you should add the Windows.ApplicationModel.DataTransfer namespace:

using Windows.ApplicationModel.DataTransfer;

This namespace has all you need for basic sharing. Remember, though, if you want to share content such as images or files, you'll need to add those namespaces as well. Here's a list of the namespaces you might need:

Step 2: Get the DataTransferManager object

The DataTransferManager object is the main starting point for any sharing operation.

DataTransferManager dataTransferManager = DataTransferManager.GetForCurrentView();

Step 3: Add an event handler for the DataRequested event

Add a DataRequested event handler to fire when the user wants to invoke Share. In a Windows Store app, this occurs automatically when the user invokes the Share charm. If you're developing for Windows Phone, there is no built-in Share charm, so you'll need to add a control for the user to tap and trigger the handler.

dataTransferManager.DataRequested += new TypedEventHandler<DataTransferManager, DataRequestedEventArgs>(this.DataRequested);

Step 4: Get a DataRequest object

When a DataRequested event occurs, your app receives a DataRequest object. This object contains a DataPackage that you can use to provide the content that the user wants to share.

DataRequest request = e.Request;

Step 5: Get a DataRequestDeferral object, if needed.

You'll need to get a DataRequestDeferral object if your app calls any asynchronous methods after it receives DataRequest object. To get a deferral object, call GetDeferral.

DataRequestDeferral deferral = e.Request.GetDeferral();

Step 6: Add the data to the DataPackage

You can use any of the methods that the DataPackage supports to add content. Here, we use SetBitmap to add a modified image as a RandomAccessStream.

e.Request.Data.SetBitmap(imageStreamRef);

Step 7: Call the complete method, if necessary.

If you retrieved a DataRequestDeferral object in Step 5, you need to call the DataRequestDeferral.Complete method to let the system know that the data is ready for sharing.

deferral.Complete();

Note  You also need to call DataRequestDeferral.Complete in the error handler of the asynchronous call.

 

Remarks

To download code that demonstrates how to delay sharing, see our code gallery sample.

Example

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    // Register this page as a share source.
    this.dataTransferManager = DataTransferManager.GetForCurrentView();
    this.dataTransferManager.DataRequested += new TypedEventHandler<DataTransferManager, 
            DataRequestedEventArgs>(this.OnDataRequested);
}

private void OnDataRequested(DataTransferManager sender, DataRequestedEventArgs e)
{
    if (imageFile != null)
    {
        DataPackage requestData = e.Request.Data;
        requestData.Properties.Title = "Delay rendered image";
        requestData.Properties.Description = "Resized image from the Share Source sample";
        requestData.Properties.Thumbnail = RandomAccessStreamReference.CreateFromFile(imageFile);
        requestData.SetDataProvider(StandardDataFormats.Bitmap, 
                new DataProviderHandler(this.OnDeferredImageRequestedHandler));
    }
    else
    {
    e.Request.FailWithDisplayText("Select an image you would like to share and try again.");
    }
}

private async void OnDeferredImageRequestedHandler(DataProviderRequest request)
{
    // In this delegate we provide updated Bitmap data using delayed rendering.

    if (this.imageFile != null)
    {
        // If the delegate is calling any asynchronous operations it needs to acquire
        // the deferral first. This lets the system know that you are performing some
        // operations that might take a little longer and that the call to SetData 
        // could happen after the delegate returns. Once you acquired the deferral object 
        // you must call Complete on it after your final call to SetData.
        DataProviderDeferral deferral = request.GetDeferral();
        InMemoryRandomAccessStream inMemoryStream = new InMemoryRandomAccessStream();

        // Make sure to always call Complete when finished with the deferral.
        try
        {
            // Decode the image and re-encode it at 50% width and height.
            IRandomAccessStream imageStream = await this.imageFile.OpenAsync(FileAccessMode.Read);
            BitmapDecoder imageDecoder = await BitmapDecoder.CreateAsync(imageStream);
            BitmapEncoder imageEncoder = await BitmapEncoder.CreateForTranscodingAsync(inMemoryStream, 
                    imageDecoder);
            imageEncoder.BitmapTransform.ScaledWidth = (uint)(imageDecoder.OrientedPixelWidth * 0.5);
            imageEncoder.BitmapTransform.ScaledHeight = (uint)(imageDecoder.OrientedPixelHeight * 0.5);
            await imageEncoder.FlushAsync();

            request.SetData(RandomAccessStreamReference.CreateFromStream(inMemoryStream));
        }
        finally
        {
            deferral.Complete();
        }
    }
}

Sharing content source app sample

Sharing and exchanging data

How to support pull operations

Quickstart: Sharing content

DataPackage

Windows.ApplicationModel.DataTransfer

Windows.ApplicationModel.DataTransfer.Share

Reversi sample feature scenarios: sharing content