Windows Store App Contracts

14 January 2013
by Ambily Kavumkal Kamalasanan

Windows Store Apps use contracts to declare the interactions that they support with other apps and with the 'Charm Bar'. They bind your app to other 'Metro' style apps and to the system user-interface: They provide a great deal of functionality for little programming effort.

Introduction

Amongst the many new features of Windows 8 was the new programming model called Windows Store Application, previously known as ‘Metro’. This introduced a whole new Tile-based application development paradigm where applications are designed to share a universal ‘toolbar’ called the ‘Charm Bar’. The Charm bar is activated using Win+Q keys, using a swipe from right bottom to top edge of the screen or using an upward mouse movement from right bottom edge. It contains buttons, called ‘Charms’, for Search, Share, Devices, and Settings. Each of the Charms represents functionality that can be added to your application through what are called contracts. Contracts save the application from having to implement the user-interface to do this, and gives the user a consistent way of searching, printing, and sharing. This Charm Bar is the most obvious and most visible use of contracts, but contracts are of wider value than this.

With contracts, the new unified communication model defines how applications can interact. When you define a contract, you are specifying only the requirements for participating in a communication rather than on how the other application will work with this interface. This ensures only that the applications that are implementing the Contract can communicate with each other irrespective of their internal implementation.

If, for example, you are writing a traditional Windows application that needs to share such data as images, brochures, content or links, you’d need to write one module for sharing the content in email using the SMTP service, another module for sharing the same content with Facebook and yet another for sharing with SkyDrive. Any module that we created for sharing the data through email would not work with other ‘share targets’ such as SkyDrive or Facebook. As shown in figure 1, we would require 6 different modules at minimum for implementing the content sharing through email, Facebook and SkyDrive. The implementation will differ from application to application.

Traditional Share Implementation

Figure 1: Traditional Share Implementation

But, if the app is a Windows Store (Metro) app, you just need to implement the Share Source Contract which will then be able to share the content with all these three applications. As shown in figure 2, each application will implement the Share Source or Share Target contract in the same way and so will be able to share the content with various applications that do likewise.

Share Contract Implementation

Figure 2: Share Contract Implementation

Windows 8 Contracts

Contracts that are defined in Windows 8 are:

  1. Search Contract – defines that the application is search enabled.
  2. Share Contract – defines that the application is ready to share its content with any other application or it is ready to accept specific types of data from any other application.
  3. Settings Contract – define the settings specific to the application.
  4. Play To Contract – stream the audio, video and images to DLNA-enabled devices.
  5. File Picker Contract – defines that the application is used as a file saving location or can be used as a file open location. Files can be opened and saved directly into the application.
  6. Cached File Updater Contract – track the file updates and bring the latest version to the user.

There are considerable advantages in implementing these contracts.

  1. User Friendly: Users will find it easier to do general tasks such as searching or changing configuration settings. In previous versions of Windows, few applications use a configuration file for defining the configurations and users might be required to use a configuration wizard or an admin screen for setting the configurations, and search functionality is defined in each application differently in terms of placement, look and feel and implementation.
  2. Easy to Maintain: Because of the standard implementation of contracts, Windows store applications are easier to maintain. Taking content sharing as an example, there will be a single implementation of the share contract and it follows the predefined format.
  3. Invoke from Outside: Even if the application is not running, users can perform various operations on the application. No longer does the user need to open each application and locate the search feature and do the operation. Now, with the new search contract, we can perform the search across multiple applications, files, settings, and so on without having to open each application.
  4. Consistency: Windows 8 OS and the Windows Store applications share the same contracts for performing various activities. Search contract is used for searching files and settings in both the OS level and at application level. File picker contracts are used for saving or opening files from system drives and from other applications.
  5. Highly Adaptive: Contract based Windows Store application can integrate with any new application without any code modification. If, for example, there is a new development or requirement for sharing data with a new system such as LinkedIn or Google+, then the application will work with new systems that implement the same contract without any code modification.

Search Contract

The Search contract defines the way that the application is ready for search.

Search contracts define a unified search experience in both the OS and applications. Figure 3 shows the default search contract implementation in Windows 8, the ‘Charm bar’. Enabling the Search contract in your application will allow the contents of the app to be searched from anywhere within the system via the Search charm.

Search Contract

Figure 3: Search Contract

Search Contract Implementation

We can get the same search experience in our application. First, for this walk-through, we’ll define a Windows Store application using any of the project templates in VS 2012 and then show the rudiments setting up the various contracts. I have used the Grid App template associated with the Windows Store App

Step 1: Declare the Search Contract in App Manifest

Open the Package.appxmanifest file and locate the Declarations section. Add the Search Contract from the declarations list.

Package Manifest

Figure 4: Package manifest

Step 2: Add the Search Contract item

Select the ‘Add new itemoption and select the ‘Search Contract ‘item. The ‘Search Contract item will add the default search result page and the OnSearchActivated method in the App.xaml.cs file. We will discuss about this method latter.

Search Contract Item

Figure 5: Search Contract Item

Step 3: Handle the QuerySubmitted event

When we invoke the search charm, it will raise the QuerySubmitted event. Register the QuerySubmitted event handler in the OnWindowCreated method of app.xmal.cs file. When the search query is submitted to the application, opens the Search result page with the result. Retrieve the query text and navigate to the Search result page.

  protected override void OnWindowCreated(WindowCreatedEventArgs args)
        {
            base.OnWindowCreated(args);
            Windows.ApplicationModel.Search.SearchPane.GetForCurrentView().QuerySubmitted += App_QuerySubmitted;
        }

  void App_QuerySubmitted(Windows.ApplicationModel.Search.SearchPane sender, Windows.ApplicationModel.Search.SearchPaneQuerySubmittedEventArgs args)
        {
            var previousContent = Window.Current.Content;
            var frame = previousContent as Frame;
            frame.Navigate(typeof(MySearchResult), args.QueryText);
        }

Step 4: Define the Search logic

Firstly, we must define the custom search logic to retrieve our application-specific data inside the search results page. If we are planning to display any filters on top of the search result page, we need to add them in the LoadState method of Search result page.

We must implement the search logic inside the Filter_SelectionChanged method. For our sample implementation, I have defined a GetItems method inside the SampleDataSource provided as part of the project template. This method will return all the items with title or content containing the specified query string.

Once the result is available, pass the same to Results view model.

object queryText;
                this.DefaultViewModel.TryGetValue("QueryText", out queryText);

                var data = SampleDataSource.GetItems(queryText.ToString().Trim('"'));
                this.DefaultViewModel["Results"] = data;

Step 5: Test Search

Now our application is search-enabled. Run the application and invoke the Search charm and perform the search.

Search Contract Result

Figure 6: Search Contract Result

Compare with Windows 8 Implementation

Search is now enabled in our application. We will now run our search contract implementation with the OS level search implementation in the Charm bar.

1. Invoke by typing

If we go to the start screen and start typing, this will invoke the Search charm and start entering the text in the search box. You can see that this feature is not working in our application. At the moment, our application will respond to the search only when we explicitly invoke the search charm. We can incorporate the feature of initiating a search on every key press in our application by setting the ShowOnKeyboardInput property of the SearchPane to true.

protected override void OnWindowCreated(WindowCreatedEventArgs args)
        {
            base.OnWindowCreated(args);
            SearchPane.GetForCurrentView().ShowOnKeyboardInput = true;
		…………………………………………………..
}

Now, when we open the application and start typing on any page, this will invoke the search charm.

2. Add query suggestions

Another feature that is missing in our application is the list of search query suggestions, which will appear just below the search box in the search charm depending on the search text that is entered. We can implement this by handling the SearchPane’s SuggestionRequested event.

We need to handle this event inside the OnWindowCreated method.

protected override void OnWindowCreated(WindowCreatedEventArgs args)
        {
            base.OnWindowCreated(args);
            SearchPane.GetForCurrentView().ShowOnKeyboardInput = true;
            Windows.ApplicationModel.Search.SearchPane.GetForCurrentView().QuerySubmitted += App_QuerySubmitted;
            SearchPane.GetForCurrentView().SuggestionsRequested += App_SuggestionsRequested;
        }

        void App_SuggestionsRequested(SearchPane sender, SearchPaneSuggestionsRequestedEventArgs args)
        {
            args.Request.SearchSuggestionCollection.AppendQuerySuggestion(args.QueryText + " 1");
            args.Request.SearchSuggestionCollection.AppendQuerySuggestion(args.QueryText + " 2");
            args.Request.SearchSuggestionCollection.AppendQuerySuggestion(args.QueryText + " 3");
            args.Request.SearchSuggestionCollection.AppendQuerySuggestion(args.QueryText + " 4");
            args.Request.SearchSuggestionCollection.AppendQuerySuggestion(args.QueryText + " 5");

        }

Append the query suggestions to the SearchSuggestionCollection. Note, that only 5 query suggestion can be displayed on the Search charm.

3. Invoke the app from Start Screen

As you noticed from Figure 1, we can invoke the search charm from the start screen and perform the search on system resources as well as on any applications. If it is not search-enabled, it will display the message saying that the app is not searchable.

If we invoke the Search charm from the start menu and select our application from the list of applications, we’ll see that that the search is returning the expected search result, even though the application is not running on the system. When the search invokes the app from outside the application, it will call the OnSearchActivated method added inside the App.xmal.cs file. This method implements the App Activation logic, which activates the application. This method will respond to the search query when the app is not the main app on the screen.

Share Contract

The Share contract allows your application to share your content from the app with other apps on the system. It also means that you can receive items to share through your app from other apps, though you would then need to design the interface in your app for sharing content from other apps

We can implement our application as Share Source, where the app will share the content with other application or as Share Target, where the app will process the data shared by other apps. We can do one or both.

The Share Contract defines a standardized format for sharing contents that allows for various approaches to sharing.

Share Source Implementation

Applications that are working in an integrated environment may require sharing their contents with many other applications. By implementing the ‘Share source’, the application is enabled to share content with any app which satisfies the contract requirements.

Step 1: Identify the Data format

The first job is to decide the format of the content you are going to share with another app. We can share data in text format, URL, HTML, files, images and custom defined format. For our walkthrough, we will be defining two different custom formats, where in our application will share a link and associated data, and in a second example it will share an attached file.

Step 2: Handle the DataRequested Event

When the Share Charm is invoked, it will fire the DataRequested event to the current page. We need to handle this event inside the page, from where we are going to share the content. Handle the DataRequest event inside the OnNavigateTo() method of the page.

Include the namespace corresponding to the DataTransfermanager

	using Windows.ApplicationModel.DataTransfer;

Add the handler.

private DataTransferManager dataTransferManager;  

datatransferManager = DataTransferManager.GetForCurrentView();
  	datatransferManager.DataRequested += datatransferManager_DataRequested;

Implement the data sharing logic inside the DataRequested event handler. Set the properties to the Data property of the DataRequest.

void datatransferManager_DataRequested(DataTransferManager sender, DataRequestedEventArgs args)
        {
            DataRequest req = args.Request;
            req.Data.Properties.Title = "Sample Title";
            req.Data.Properties.Description = "Sample Content";
            req.Data.SetUri(new Uri("http://www.mnsd.com"));
        }

Invoke the Share Contract from the application and observe the share targets available.

Share Source Contract

Figure 7: Share Source Contract

We’ll now select the Mail option and see how our shared content will appear in a mail.

Share Source Contract with Mail Target

Figure 8: Share Source Contract with Mail Target

You’ll see that the title is converted as subject, a description is added in the content and the URI is specified in content. Also, you can observe that the system added a new heading and a thumbnail to our content, which is derived from the URI.

Step 3: Remove the event handler

Our application will implement the share source in different ways in different pages. So, when we move out of a page, unregister the event handle inside theOnNavigatedFrom method.

protected override void OnNavigatedFrom(NavigationEventArgs e)
  {
            dataTransferManager.DataRequested -= this.dataTransferManager_DataRequested;
         }

The next code snippet is another sample for sharing a file.

async void dataTransferManager_DataRequested(DataTransferManager sender, DataRequestedEventArgs args)
        {
            DataRequest request = args.Request;
            request.Data.Properties.Title = "Sample Title";
            request.Data.Properties.Description = "Sample Content";

            DataRequestDeferral deferral = request.GetDeferral();

            try
            {
                StorageFile file = null;
                file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(filePath));
                if (file != null)
                {
                    List storageItems = new List();
                    storageItems.Add(file);
                    request.Data.SetStorageItems(storageItems);
                }
            }
            finally
            {
                deferral.Complete();
            }
        }

Share Target Implementation

In the previous section, we mentioned the share source implementation where our application will share content with another application. In this section, we will discuss the way that our application can consume the data shared by another application.

Step 1: Add the Share Target Contract

Open the manifest file Package.appxmanifestand add the Share Target from the Declarations section in the manifest file. Once you add the Share Target, it will ask for the supported file type and the Data formats. Specify the Supported file types, .docx in our example, and data formats, we’ll specify Text. We can specify one or more file types and data formats. By using the “Supports any file type” option, we can specify that our application will accept any type of files.

Share Target Contract Declaration

Figure 9: Share Target Contract Declaration

Step 2: Define the OnShareTargetActivated method

When we select our application as the share target from any other application, the OnShareTargetActivated method will be invoked. Inside this method we will activate our application, if it is not already activated, and navigate to the page which will be displayed in the share charm.

using Windows.ApplicationModel.Activation;
……………………………………………………………………………………………
protected override void OnShareTargetActivated(ShareTargetActivatedEventArgs args) 
        { 
            var rootFrame = new Frame(); 
            rootFrame.Navigate(typeof(ShareTarget), args.ShareOperation); 
            Window.Current.Content = rootFrame; 
            Window.Current.Activate(); 
        } 

For our sample app, we use the ShareTarget as the share target page, which will be displayed in the Share charm.

Step 3: Define the Logic to handle Shared Content

Define the logic inside the Share target page to handle the shared content. For our sample application, we are handling both the URI and text data shared from any other application. Received content will be displayed back to the user in the share charm.

using Windows.ApplicationModel.DataTransfer; 
using Windows.ApplicationModel.DataTransfer.ShareTarget; 
………………………………………………………………………………
private ShareOperation shareOperation;
………………………………………………………………………………
protected override async void OnNavigatedTo(NavigationEventArgs e)
        {
            StringBuilder sb = new StringBuilder();
            this.shareOperation = (ShareOperation)e.Parameter;
            await Task.Factory.StartNew(async () =>
                {
                    sb.Append(" \nTitle:  " + this.shareOperation.Data.Properties.Title);
                    sb.Append(" \nDescription: " + this.shareOperation.Data.Properties.Description);
                    if (this.shareOperation.Data.Contains(StandardDataFormats.Uri))
                    {
                        sb.Append(" \nUri: " + await this.shareOperation.Data.GetUriAsync());
                    }
                    else if (this.shareOperation.Data.Contains(StandardDataFormats.Text))
                    {
                        sb.Append(" \nText:  " + await this.shareOperation.Data.GetTextAsync());
                    }
                });

            msg.Text = sb.ToString();
        }

Open another application. For our sample, we will open the Internet Explorer application in Windows 8 and try to share some content from the app.

Share target Contract Implementation

Figure 10: Share target Contract Implementation

We have two options to share our selected text – mail and our application –SampleApp. Let’s select the SampleApp.

Share Target Implementation - Text Sharing

Figure 11: Share Target Implementation - Text Sharing

Now, let us select the URL of the webpage and try to share using our application.

Share Target Implementation - URL Sharing

Figure 12: Share Target Implementation - URL Sharing

Settings Contract

Another widely-used Contract is the Settings contract, where we define the application settings. This will define a center location for defining the application configurations and authentication and authorization settings. The Settings contract is used for defining the login screen, account settings, application-specific settings, etc.

We can invoke the Settings charm using Win+I keys or by swiping the mouse from right bottom to top. We will define two settings commands with one event handler for our sample application.

Step 1: Handle the CommandsRequested event

Handle the CommandsRequested event, which will be fired when we invoke the Settings charm from our application in App.xaml.cs file.

	SettingsPane.GetForCurrentView().CommandsRequested += App_CommandsRequested;

Add the SettingsCommands and the corresponding operations inside the event handler.

void  App_CommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args)
        {
            args.Request.ApplicationCommands.Add(new SettingsCommand("Sample", "Sample Config", (y) => { }));
            args.Request.ApplicationCommands.Add(new SettingsCommand("Sample", "Test Config",  async(x) => 
                {
                    var msgDial = new MessageDialog("Called from the Config entry in Settings pane");
                    msgDial.Commands.Add(new UICommand("OK"));
                    await msgDial.ShowAsync();
                }));
        }

Invoke the Settings charm from inside the application and see the new settings commands.

Settings Contract

Figure 13: Settings Contract

Click on the ‘Test Config’ settings command and observe the fired event handler.

Settings Contract - Action

Figure 14: Settings Contract - Action

Conclusion

Contracts are the centralized communication model introduced in Windows 8. It is hard to imagine a Windows Store application that doesn’t need to use them. They make individual Windows Store applications easier to develop since a lot of the interface is delegated to the Metro ‘Charm bar’. They also allow much better cooperation and easier data transfer between applications. They give the user a much more consistent user-interface. Contracts are highly adaptive, easy to maintain and implement. Apps developed using Contracts are able to work with any new applications introduced in the market that conform to the centralized communication model.


© Simple-Talk.com