Skip to main content Skip to footer

App-to-App Sharing with C1RichTextBox

App-to-app sharing is a key feature of the Windows 8 user experience. The Share charm provides a means for Windows Store apps to share content with one another. For example, a news reader app can share a popular article, or a photo app can share an image. Sharing is a two part process where one app declares itself as a share source and another as the target. The brilliant thing is that neither app needs to know anything about the other. Every app that participates in the sharing contract can be confident that the sharing workflow is completely supported, end-to-end, by Windows. What can you share? Content formats that can be shared include plain text, rich text (RTF), Html, links (Uri), images and files (StorageItems). If your app has content to share, your app is a share source. If your app can receive content from other apps, then it’s a share target. Of course, apps can be both at once. This blog post shows how you can create a complete sharing experience with one app. We take advantage of sharing HTML content by using the ComponentOne RichTextBox control, which is a complete HTML editor. The sample shows how to share HTML content between the C1RichTextBox app and any other app that supports HTML formatted text, such as Windows Mail and OneNote. First we will look at making the app a share source, and then a share target.

Share Source

For the source app in the sharing contract, you implement sharing when you register a handler for DataRequested event from the DataTransferManager class. This event fires when the user activates the Share charm. You can call this code from the Loaded or OnNavigatedTo events for your page which will host the sharing action.


// Register for DataRequested events  
DataTransferManager.GetForCurrentView().DataRequested += OnDataRequested;  

Below is the basic code required to share html and text data formats in the OnDataRequested event. The DataRequest object has several methods which we use to set the content to be shared, such as SetText and SetHtmlFormat.


void OnDataRequested(DataTransferManager sender, DataRequestedEventArgs args)  
{  
    DataRequest request = args.Request;  

    // Must provide at least title for shared content  
    request.Data.Properties.Title = "Content from C1RichTextBox";  

    // Optionally provide a description  
    request.Data.Properties.Description = "Sharing selected text as html.";  

    // Set Html to the share request  
    request.Data.SetHtmlFormat(HtmlFormatHelper.CreateHtmlFormat(html));  

    // we can also support sharing plain text to some apps that don't support html  
    request.Data.SetText(text);  

}  

Below is a more complete example for sharing html and text from a C1RichTextBox control (named “rtb”). Here we also respect the user’s selection. If they have selected only part of the text we only share that. If the C1RichTextBox is completely empty we can use the DataRequest.FailWithDisplayText method to instruct the user on how to share content from our app.


void OnDataRequested(DataTransferManager sender, DataRequestedEventArgs args)  
{  
    DataRequest request = args.Request;  

    // Must provide at least title for shared content  
    request.Data.Properties.Title = "Content from C1RichTextBox";  

    string html = "";  
    string text = "";  

    // TIP: Respect user selections share selection if user has selected text  
    if (!string.IsNullOrEmpty(rtb.Selection.Text))  
    {  
        C1RichTextBox tempRTB = new C1RichTextBox();  
        tempRTB.Html = rtb.Selection.Html;  

        html = tempRTB.GetHtml(HtmlEncoding.Inline);  
        text = rtb.Selection.Text;  

        // TIP: let user know what they're selecting  
        request.Data.Properties.Description = "Sharing selected rich text as html.";  
    }  
    else if (!string.IsNullOrEmpty(rtb.Text))  
    {  
        // otherwise share entire content  
        html = rtb.GetHtml(C1.Xaml.RichTextBox.Documents.HtmlEncoding.Inline);  
        text = rtb.Text;  

        request.Data.Properties.Description = "Sharing all rich text as html.";  
    }  
    else  
    {  
        // if unable to share nicely tell the user how to share something  
        request.FailWithDisplayText("Type something into the C1RichTextBox control.");  
        return;  
    }  

    // format the html content to Windows specification with Helper class  
    html = HtmlFormatHelper.CreateHtmlFormat(GetHtmlBody(html));  

    // add the html to the share request  
    request.Data.SetHtmlFormat(html);  

    // we can also support sharing plain text to some apps that don't support html  
    request.Data.SetText(text);  

}  

When sharing Html, an important helper class will be necessary. The HtmlFormatHelper class adds necessary header information to your Html content, such as total length and where the actual Html fragment begins and ends. I have tried working around having to use the helper class with C1RichTextBox (because the content is already in proper html format), however common apps like Windows Mail and OneNote require the specific format supplied by this class. Here is an example of what the HtmlFormatHelper appends to the beginning of our html content:


Version:1.0  
StartHTML:00000097  
EndHTML:00000154  
StartFragment:00000122  
EndFragment:00000140  
<!doctype><html><head></head><body><p>Hello World</p></body></html>  

The HtmlFormatHelper also adds HTML and BODY tags to the content (regardless of whether they already exist), so we have to also include this extra helper which extracts just the BODY content from a complete html string. It’s easier to just extract the body of content from C1RichTextBox rather than have to calculate the other meta data which the HtmlFormatHelper provides.


/// <summary>  
/// Returns body of html  
/// </summary>  
public string GetHtmlBody(string html)  
{  
    int bodyIndex = html.IndexOf("body");  
    html = html.Substring(html.IndexOf("body"));  
    html = html.Substring(html.IndexOf(">") + 1);  
    html = html.Substring(0, html.LastIndexOf("</body>"));  
    return html;  
}  

That’s all you need to support for Html sharing to another app. The screenshot below shows sharing to the Windows Mail app. Next, we’ll handle the share target.

Share Target

For the shared target app, you must do a few things:

  1. Declare your app as a Share Target in the Package.appmanifest file. This tells Windows that your app can be a share target for the formats you specify here.
  2. Create and display a share pane when sharing is activated for your app in the OnShareTargetActivated event. The share pane is a pop-up that slides out and displays the to-be shared content in your app running over top of the original app.
  3. Perform any additional tasks necessary to complete the sharing operation.

The first thing to do is to tell Windows that you application is a share target. This is done via the Package.appxmanifest file on the Declarations tab. For our C1RichTextBox sample we declare sharing for both HTML and Text data formats. Next, override the OnShareTargetActivated event in your App.xaml code. This is invoked when the application is activated to receive items. From here you will navigate to the share pane, which should be a separate, smaller page in your application that displays in the flyout. The shared content is passed by parameter with the ShareOperation object which we will work with later.


protected override void OnShareTargetActivated(ShareTargetActivatedEventArgs args)  
{  
    var rootFrame = new Frame();  
    rootFrame.Navigate(typeof(SharePage), args.ShareOperation);  
    Window.Current.Content = rootFrame;  
    Window.Current.Activate();  
}  

In this sample, the SharePage is a smaller version of the MainPage (lesser margins, font size, etc). Note: You can take advantage of the Share Target template in Visual Studio which will set up the necessary events and declarations for your project. Just go to Add – New Item – and select Share Target from the Windows Store template items. Next, override the OnNavigatedTo event in the share page. Here you can check the type of data being shared and proceed. Between Html and Text formats you typically will only support one or the other, so we have set up an If/If Else statement giving Html the first priority. The HtmlFormatHelper class is necessary this time to strip out the Html fragment and exclude the meta data which it added in the first place.


protected override async void OnNavigatedTo(NavigationEventArgs e)  
{  
    ShareOperation shareOperation = (ShareOperation)e.Parameter;  

    if (shareOperation.Data.Contains(StandardDataFormats.Html))  
    {  
        try  
        {  
            string html = HtmlFormatHelper.GetStaticFragment(await shareOperation.Data.GetHtmlFormatAsync());  
            rtb.SetHtml(html, null);  
        }  
        catch (Exception ex)  
        {  
            rtb.Text = "Failed to get html.";  
        }  

    }  
    else if (shareOperation.Data.Contains(StandardDataFormats.Text))  
    {  
        try  
        {  
            rtb.Text = await shareOperation.Data.GetTextAsync();  
        }  
        catch (Exception ex)  
        {  
            rtb.Text = "Failed to get text.";  
        }  
    }  
}  

Now we can support sharing from another app to our own. The screenshot below shows sharing selected text from the OneNote app to our own app.

Conclusion

In this sample we looked at sharing Html content between any other app and our own. We used the C1RichTextBox control to act as our Html editor, and we use the HtmlFormatHelper to better format our shared content with such apps as Windows Mail and OneNote. Only the code relevant to sharing was included in this blog post. You can download the complete sample below to see all code for setting up the C1RichTextBox pages. Download Sample

ComponentOne Product Manager Greg Lutz

Greg Lutz

comments powered by Disqus