Sharing in Windows 8 Apps

This post will show an example of sharing using a Windows 8 app.

Background

I am working on a team project with a requirement to post information to Twitter and Facebook from a Windows 8 app.  We started looking at writing our own user interfaces to do this, and then realized this was kind of nuts as Windows Store apps already provide this functionality.  If you’ve built Windows 8 apps before, this isn’t going to be earth-shattering, but when I brought it up to the team I realized it was new to many people on the call.  Thus, I am writing a quick example.

The opportunities here are really very interesting.  Instead of you building all the capabilities for various social networks into your app (post to Yammer, Twitter, Facebook, and more) when that’s not its real function, you can use the share capabilities to defer that to other apps. 

Create a Windows App

Open Visual Studio 2013 and create a new Windows App. 

image

I use the Hub App template as it is really easy to get started with.  The other thing I like about this project template is that it contains 3 distinct pages (HubPage, SectionPage, and ItemPage) that we will use to illustrate contextual sharing.  As a reminder, here is what the Hub App template generates by default: a hub page, clicking on a section reveals the section page, and clicking an item reveals the item page.

image

image

image

How Sharing Works

The next thing to determine is how you will share.  There are two ways to look at it:  the app that is sharing data, and the app that receives data.

Block diagram showng the components involved in sharing

[Via https://msdn.microsoft.com/en-us/library/windows/apps/hh758314.aspx]

Sharing as the Source App

I could write the code once and from any page in the app share the same information, however this is so easy I want to complicate things by sharing different information on different pages.  I determine that I want my app to share the following information in context:

Page Information to share
HubPage.xaml Name of app
SectionPage.xaml Name of app, URL to my blog
ItemPage.xaml Name of app, URL to my blog, photo

In each of the following examples, we will share data and show the result.

Sharing Simple Text

Let’s start with HubPage.xaml.  Edit the page contstructor and add an event handler for navigationHelper.SaveState.

Code Snippet

  1. public HubPage()
  2. {
  3.     this.InitializeComponent();
  4.     this.navigationHelper = new NavigationHelper(this);
  5.     this.navigationHelper.LoadState += navigationHelper_LoadState;
  6.     this.navigationHelper.SaveState += navigationHelper_SaveState;
  7.     
  8. }

In the LoadState method, there is already some code there.  Let’s just add to the existing code.  We will use the DataTransferManager type to add a handler for the DataRequested event as illustrated in the diagram above.

Code Snippet

  1. private async void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
  2.         {
  3.             // TODO: Create an appropriate data model for your problem domain to replace the sample data
  4.             var sampleDataGroup = await SampleDataSource.GetGroupAsync("Group-4");
  5.             this.DefaultViewModel["Section3Items"] = sampleDataGroup;
  6.  
  7.             var dtm = Windows.ApplicationModel.DataTransfer.DataTransferManager.GetForCurrentView();
  8.             dtm.DataRequested += new TypedEventHandler<DataTransferManager, DataRequestedEventArgs>(dtm_DataRequested);
  9.         }

Our implementation for the DataRequested event handler is very simple.  Obtain the DataPackage from the args parameter, and set properties of the item that is being shared.

Code Snippet

  1. void dtm_DataRequested(Windows.ApplicationModel.DataTransfer.DataTransferManager sender, Windows.ApplicationModel.DataTransfer.DataRequestedEventArgs args)
  2. {
  3.     DataPackage shareData = args.Request.Data;
  4.     shareData.Properties.Title = "Kirk Sharing Demo";
  5.     shareData.Properties.Description = "Kirk Demo of sharing with shared contracts";
  6.     shareData.SetText("Sharing from the hub page!");
  7. }

When the user navigates away from the page, we don’t want to leave our share registration there, we need to remove it.  In the SaveState handler, we simply remove the event handler reference.

Code Snippet

  1. private async void navigationHelper_SaveState(object sender, SaveStateEventArgs e)
  2. {
  3.     var dtm = Windows.ApplicationModel.DataTransfer.DataTransferManager.GetForCurrentView();
  4.     dtm.DataRequested -= dtm_DataRequested;
  5. }

The result is very simple.  In the charm bar, click the Share charm.

image

Clicking the Share charm shows the list of apps that are registered to receive this type of data.  The title of the item being shared corresponds to the .Title property that we set in our code, and the description corresponds to the .Description property.

image

We click Facebook and then see the value from the SetText method is shown.

image

We can do the same for the Mail app or the Twitter app.

image

image

Note: If you are getting an error that the request could not be completed or the app is unavailable for sharing, try uninstalling the target app and then reinstalling.

In the preceding example, we shared simple text.  Now, let’s share a URL and see what happens.  On the SectionPage.xaml page, we follow the exact same pattern: add handlers for LoadState and SaveState, and implement the event for DataRequested,

Code Snippet

  1. private async void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
  2. {
  3.     // TODO: Create an appropriate data model for your problem domain to replace the sample data
  4.     var group = await SampleDataSource.GetGroupAsync((String)e.NavigationParameter);
  5.     this.DefaultViewModel["Group"] = group;
  6.     this.DefaultViewModel["Items"] = group.Items;
  7.  
  8.     var dtm = Windows.ApplicationModel.DataTransfer.DataTransferManager.GetForCurrentView();
  9.     dtm.DataRequested += new TypedEventHandler<DataTransferManager, DataRequestedEventArgs>(dtm_DataRequested);
  10. }
  11. void navigationHelper_SaveState(object sender, SaveStateEventArgs e)
  12. {
  13.     var dtm = Windows.ApplicationModel.DataTransfer.DataTransferManager.GetForCurrentView();
  14.     dtm.DataRequested -= dtm_DataRequested;
  15. }

The implementation for the DataRequested event handler looks just the same as before, but this time we add one property to it to expose a URL using the SetWebLink property.

Code Snippet

  1. void dtm_DataRequested(DataTransferManager sender, DataRequestedEventArgs args)
  2. {
  3.     DataPackage shareData = args.Request.Data;
  4.     shareData.Properties.Title = "Kirk Sharing Demo";
  5.     shareData.Properties.Description = "Kirk Demo of sharing with shared contracts";
  6.     shareData.SetText("Sharing from the section page!");
  7.     shareData.SetWebLink(new Uri("https://blogs.msdn.com/kaevans"));
  8. }

Just adding that one property to the item being shared has a noticeable effect when the app is run.  We get a few more apps that are registered to receive that type of data.  Where before we had Facebook, Twitter, and Mail, we now have People, Reading List, and Yammer. 

image

We can now share to the People app to share to our contacts on different social networks.

image

Sharing Images

This time, we are going to add a button to the page to launch the share charm, just because we can.

Code Snippet

  1. private void Button_Click(object sender, RoutedEventArgs e)
  2. {
  3.     Windows.ApplicationModel.DataTransfer.DataTransferManager.ShowShareUI();
  4. }

The pattern is exactly the same as before, so we will show the few lines of code that are different for sharing pictures.  When we create the hub app, it contains a folder “Assets” that contains a few sample images.  We’ll steal the DarkGray.png file for our purposes here.

Code Snippet

  1. private async void dtm_DataRequested(Windows.ApplicationModel.DataTransfer.DataTransferManager sender, Windows.ApplicationModel.DataTransfer.DataRequestedEventArgs args)
  2. {
  3.     DataPackage shareData = args.Request.Data;
  4.     shareData.Properties.Title = "Kirk Sharing Demo";
  5.     shareData.Properties.Description = "Kirk Demo of sharing with shared contracts";
  6.     shareData.SetText("Sharing from the item page!");
  7.  
  8.     var storageFile = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync("Assets\\DarkGray.png");
  9.     var imageStream = Windows.Storage.Streams.RandomAccessStreamReference.CreateFromFile(storageFile);
  10.     shareData.SetBitmap(imageStream);
  11. }

That is just ridiculous easy.  Let’s run it and see the experience.

image

Receiving Data as a Target App

So far, we just showed how to send data from our app to a list of apps that are registered to receive different types of data. Now let’s show a quick example of receiving data.  The first step is to declare in our app manifest that the app is available as a share target.  We can choose different data formats or files.  We choose a simple Text example in the app manifest and save.

image 

In app.xaml. we add the following code.

Code Snippet

  1. protected override async void OnShareTargetActivated(ShareTargetActivatedEventArgs args)
  2. {
  3.  
  4.     ShareOperation shareOperation = args.ShareOperation;
  5.     
  6.     if (shareOperation.Data.Contains(StandardDataFormats.Text))
  7.     {
  8.  
  9.         string sharedText = await shareOperation.Data.GetTextAsync();
  10.         
  11.     }
  12. }

Add a breakpoint on our receiver logic.  Run another app, such as Twitter.  Select a single tweet and choose Share from the charm bar, and our demo app is now an available target.

image

The breakpoint is hit and we can see the data that is shared from the other app.

image

There’s much more to it than this.  You can defer the processing of the shared item to a background task, report on success/failure, and more.  There are samples and documentation available at Sharing and receiving content to help you get started.

For More Information

Sharing to Facebook/Twitter from Windows 8/WinRT App

31 Days of Windows 8 | Day #7: Share Contract

https://windows8center.sourceforge.net/31-days-of-windows-8-day-7-share-contract/

Sharing and receiving content