Wednesday, May 29, 2013

Sharing App Content using MVVM and the Okra App Framework

One of the key differentiating features of the Windows Store application model in Windows 8 is the availability of system provided “charms” for common tasks such as sharing, search and application settings. In this post I will focus on sharing, and how the Okra App Framework makes it easy to incorporate this functionality into applications using the MVVM pattern.

How to share content the Windows 8 way?

The MSDN documentation details how to share content from Windows Store apps in C#/VB. The first step is to get a reference to the application’s DataTransferManager, and then register for its DataRequested event. When the user selects the share charm this event is fired, passing a DataRequestedEventArgs object to the event handler.

There are a number of problems with this approach in the context of an MVVM application,

  • The content to share should be determined dynamically based upon the page displayed and any user selected content. In the MVVM pattern this is best accomplished by the view-model, and not by a single event handler.
  • The application specific sharing code is passed a DataRequestedEventArgs object (which is a sealed class with no public constructors). This makes unit testing this code difficult.
  • Supporting pull operations (see the MSDN documentation on this topic) requires additional event handler registration, not following the typical Task based async support used elsewhere.

Sharing content with the Okra App Framework

The Okra App Framework overcomes these problems, whilst maintaining the power of the sharing contract by allowing view-models to implement a simple, easily unit-testable, IShareable interface. The framework will handle all the other infrastructure required for application sharing. Since the IShareable interface is applied to the view-model, a ‘ViewPhoto’ page can share an individual photo, whilst a ‘ViewAlbum’ page can share the whole album (or selected photos if the user has done so).

The first step in adding sharing support to an application is to add a reference to an IShareSourceManager in the application bootstrapper.

public class AppBootstrapper : OkraBootstrapper
{
    [Import]
    public IShareSourceManager ShareSourceManager { get; set; }
}

You can then add the IShareable interface to any view-model that has suitable data to share,

[ViewModelExport("MyPage")]
public class MyViewModel : IShareable
{
    public void ShareRequested(IDataRequest dataRequest)
    {
        ...
    }
}

You will notice that the ShareRequested method is passed an IDataRequest object in which to return the data to share. This is a unit-testable wrapper around the WinRT DataRequest object and the standard MSDN documentation can be followed from this point to respond to the share request. For example to share some text you would implement this as follows,

[ViewModelExport("MyPage")]
public class MyViewModel : IShareable
{
    public void ShareRequested(IDataRequest dataRequest)
    {
        dataRequest.Data.Properties.Title = "...";
        dataRequest.Data.Properties.Description = "...";
 
        request.Data.SetText("Hello World!");
    }
}

Sharing content asynchronously (optional)

There are occasions when you may wish to only download the data once the user has completed the share request (e.g. when sharing a large file from a web service) – these are known as pull operations. The Okra App Framework provides extension methods to allow you to implement pull operations using the async features of .Net. For each SetXXX(…) method, Okra provides a corresponding SetAsyncXXX(…) method. For example, the code below demonstrates how to return text returned from some async method call. Note the signature of the GetShareTextAsync(…) method.

[ViewModelExport("MyPage")]
public class MyViewModel : IShareable
{
    public void ShareRequested(IDataRequest dataRequest)
    {
        ...
 
        request.Data.SetAsyncText(GetShareTextAsync);
    }
 
    private async Task<string> GetShareTextAsync(string formatId, DateTimeOffset deadline)
    {
        string text = await SomeAsyncMethod();
        return text;
    }
}

Sunday, May 12, 2013

Windows Store MVVM Templates for Visual Studio

If you have ever tried to create a Windows Store application using the MVVM pattern then you will probably have found that the Visual Studio project and item templates are a bit cumbersome. I often find myself adding a new page to my projects using one of the default templates, only to need to rewrite it to follow the MVVM pattern before I can even start adding application specific logic. What if there was a way to take advantage of the selection of project and page templates provided by Visual Studio, but have them produce fully MVVM compliant code?

Well today I’d like to announce the release of a free extension for Visual Studio 2012 (including the Express editions for Windows 8) that provides just that. It is based upon the open source Okra App Framework, and provides almost all of the Visual Studio Windows Store templates in an MVVM friendly manner.

Installing the Extension

The “Windows Store MVVM Templates for the Okra App Framework” extension is available for download from the Visual Studio Gallery, or available directly in the Visual Studio Extensions and Updates manager (the recommended method). Instructions for installing via Visual Studio are available at the Downloading the Okra App Framework page in the Okra App Framework documentation.

What Templates are Provided?

There are two types of template included, project templates and item templates. The project templates are designed to get you started with a new application and provide exactly the same behaviour as the default Visual Studio templates (but written following the MVVM pattern).

  • Okra Basic App - A single-page Okra App Framework project with no predefined controls or layout.
  • Okra Grid App - A three-page Okra App Framework project that navigates among grouped items arranged in a grid. Dedicated pages display group and item details.
  • Okra Split App - A two-page Okra App Framework project that navigates among grouped items. The first page allows group selection while the second displays an item list alongside details for the selected item.

Also included are a number of item templates that allow you to add new pages to any existing Okra App Framework based application, whether created using the project templates or not.

  • Basic Page (MVVM)
  • Split Page (MVVM)
  • Items Page (MVVM)
  • Item Detail Page (MVVM)
  • Grouped Items Page (MVVM)
  • Group Detail Page (MVVM)
  • Search Contract (MVVM)
  • Share Target Contract (MVVM)
  • Settings Pane (MVVM)
 

What do the MVVM Pages Look Like?

All the page templates (and each of the pages in the project templates) include the following files,

  • A XAML file containing the UI design, as well as an associated code-behind file. Since we are following the MVVM pattern this code-behind file contains very little logic.
  • A view-model that contains the properties and logic for the page.
  • In addition a file for design-time data is provided. This allows you to easily layout complex user interfaces in the designer with a visual representation of how the resulting page will look.

Summary

As I have discussed the new “Windows Store MVVM Templates for the Okra App Framework” make it quick and easy to implement pages following the MVVM pattern for use in Windows Store applications. The behaviour of all the templates has been designed to be identical to the default Visual Studio templates, with the added benefit of clean separation of code, unit testability and design-time data.

Sunday, March 24, 2013

Improvements in Version 0.9.6 of the Okra App Framework

To start off I would like to announce that I have just pushed a minor fix for the Okra App Framework NuGet packages with the version number v0.9.6.1. This fixes an issue with the NuGet packaging and contains the same code base as the recent v0.9.6 release. If you have previously updated to v0.9.6 via NuGet I would recommend you update to the new packages. Anyone who has downloaded the source code releases of v0.9.6 do not need to make any changes.

Following that brief announcement I would like to use the rest of this post to discuss a couple of changes that were made with the recent v0.9.6 release of the Okra App Framework to support more advanced activation and navigation scenarios. The good news is that these changes should not affect any existing code, however you may wish to implement these changes to take full advantage of future features within Okra.

Activation of Applications via the OkraApplication class

In previous releases of the Okra App Framework the recommended way of initializing your application was to create an AppBootstrapper class that derived from OkraBootstrapper. This would then be initialized from your App.xaml.cs file’s constructor,

sealed partial class App : Application
{
    public App()
    {
        this.InitializeComponent();
 
        // *** NB: THIS CODE IS NOT RECOMMENDED! ***
 
        AppBootstrapper bootstrapper = new AppBootstrapper();
        bootstrapper.Initialize();
    }
}

Whilst this will continue to work for existing applications based on the Okra App Framework, this approach does not support certain types of activation, in particular the recently introduced share target support.

Instead the recent release has introduced an OkraApplication class that should be used to derive your App class from. The AppBootstrapper is still required and needs no further changes, however the OkraApplication class will ensure that all activation events are recognised.

The changes that you should make are:

  • Change your App.xaml.cs class to read,
sealed partial class App : OkraApplication
{
    public App()
        : base(new AppBootstrapper())
    {
        this.InitializeComponent();
    }
}
  • Change the type of your App.xaml definition to be derived from OkraApplication (NB: Only the changes are shown in the code snippet below),
<okra:OkraApplication
    ...
    xmlns:okra="using:Okra">
 
    ...
 
</okra:OkraApplication>

Introduction of INavigationContext

The second feature I will discuss is the introduction of the INavigationContext interface. This is designed to allow more consistent navigation code, better code reuse and better support for more advanced navigation scenarios (such as those discussed here and here).

In previous releases of the Okra App Framework you would support navigation from you view-model by importing an INavigationManager. For example,

public class MyViewModel : NotifyPropertyChangedBase
{
    // *** NB: NO LONGER RECOMMENDED ***
 
    [Import]
    INavigationManager NavigationManager { get; set; }
 
    ...
}

If you were writing a settings pane then INavigationManager would be replaced with ISettingsPaneManager, and in other cases (such as file pickers or in multiple navigation applications) you may have a number of simultaneous navigation stacks of the same type to choose from.

With the v0.9.6 release of the Okra App Framework this has all been consolidated into a single INavigationContext interface. This can be imported via your view-models constructor and will return the correct navigation manager for the current page’s context,

public class MyViewModel : NotifyPropertyChangedBase
{
    INavigationBase NavigationManager { get; private set; }
 
    [ImportingConstructor]
    public MyViewModel(INavigationContext context)
    {
        this.NavigationManager = context.GetCurrent();
    }
 
     ...
}

The advantage of this approach is that you can use the same code in any of the cases mentioned above, and even reuse the same view-model definition between different contexts.

Summary

In this post I have discussed a couple of improvements in the latest release of the Okra App Framework. Whilst existing code should continue to work using the old mechanisms, I would recommend that you adapt your code to take advantage of the benefits described above.

Version 0.9.6 of the Okra App Framework is available from the Okra CodePlex site and via NuGet (v0.9.6.1).

Thursday, March 21, 2013

Okra App Framework v0.9.6 Released

The latest update to the Okra App Framework has just been released and is available from the Okra CodePlex site and via NuGet.

New Features in This Release

  • Support for the share charm (more information on these in a future post),
    • View-model centric share source support – by implementing ISharable on view-models they can automatically provide context specific sharing of data with other applications.
    • MVVM based share target support – implement a share target to accept data from other applications via a specified view/view-model.
    • Helper methods for task based asynchronous data sharing.
  • New OkraApplication base class that will allow the framework to handle more advanced activation events in the future (more on this in a future post).
  • Introduction of an INavigationContext that can be imported into views and view-models (more on this in a future post).
  • The INavigationBase interface now has an additional CanNavigateTo(…) method that allows consumers to determine if a named page is available without performing the navigation.
  • Refactoring of state persistence into the NavigationBase abstract class to allow reuse of this logic in custom navigation scenarios.
  • Additional events are raised,
    • upon navigation between pages (on INavigationBase)
    • upon flyout opening/closing (on ISettingsPaneManager)
  • All exceptions on application start-up should now be injected back into the application and not lost.

Breaking Changes

There are a small number of breaking changes in this release of the framework, however most of these are unlikely to apply to users of the framework (they are mostly under-the-hood interface changes that would only be applicable in advanced scenarios).

The only important change is,

  • The default OkraBootstrapper base class no longer implements the SearchManager property. If you are using the Okra search functionality then you should simply add the following code to your application bootstrapper.
[Import]
public ISearchManager SearchManager { get; set; }

For reference the other breaking changes are,

  • The SearchManager implementation now includes a default search page name (specified in the SpecialPageNames class). Since search is now opt-in this should not cause problems for existing code.

  • Removal of the obsolete SetupNavigationManager() method from OkraBootstrapper – this code can simply be placed in the SetupServices() method instead.

  • This IViewFactory now accepts an INavigationContext when creating pages. This should be injected during the composition process (handled automatically by the default MEF implementation).

  • Additional methods/properties to the INavigationBase, IViewFactory and ISettingsPaneManager interfaces. These will need to be added to any custom implementations.

Monday, February 04, 2013

Creating Authentic Looking Settings Panes with SettingsChrome

In my last post I described how the Okra App Framework allows you easily add multi-page settings panes to your Windows Store applications using the MVVM pattern.

However, the built in Windows 8 applications have a very distinctive style of settings pane and many Windows Store applications will want to recreate this style. To aid with this the Okra App Framework provides a SettingsChrome control to recreate the standard UI chrome.

SettingsPaneUI

Using the SettingsChrome control

If you remember from previously, you define the UI for an Okra App Framework settings pane using a standard UserControl with the PageExportAttribute applied to it.

[PageExport("MySettings")]
public sealed partial class MySettingsPage : UserControl
{
    ...
}

In the XAML we can add the Okra SettingsChrome control as the first child element (this can be done either manually in the XAML or added in the designer). SettingsChrome is a content control, and anything that you add inside it will be displayed within the content region of the settings pane. Also you may wish to set the width of the UserControl to define the size of the resulting settings pane.

<UserControl
    ...
    xmlns:ui="using:Okra.UI"
    Width="346">
 
    <ui:SettingsChrome Title="Sample"
        Logo="ms-appx:///Assets/SmallLogo.png"
        BackButtonCommand="{Binding ...}"
        HeaderBackgroundBrush="{StaticResource ...}"
        HeaderForegroundBrush="{StaticResource ...}">
 
        <!-- Insert settings pane content here -->
 
    </ui:SettingsChrome>
 
</UserControl>

There are a number of properties that you can set on SettingsChrome,

  • “Title” – This property allows you to set the text that is displayed at the top of the settings pane

  • “Logo” – This should point to an image resource to use as the application logo in the top-right corner of the settings pane

  • “BackButtonCommand” – This can be bound to a relevant command on the view-model and will be called whenever the user clicks on the settings pane back button

  • “HeaderBackgroundBrush” – This allows you to set the background colour for the settings pane header. Generally this will be a static resource set to the same colour used for application tile background

  • “HeaderForegroundBrush” – This allows you to set the foreground colour for the settings pane header

Summary

To summarise, the Okra App Framework allows you to easily recreate the standard settings pane UI within your own application by simply adding a SettingsChrome control into the pane’s XAML.

A sample application demonstrating the use of SettingsChrome, as well as how to define a settings pane using MVVM is available from the Okra CodePlex downloads page.

Monday, December 17, 2012

Settings Panes and the Okra App Framework

In this post (the first of two) I will describe how you can use the Okra App Framework to add custom settings panes to your Windows Store application, in particular taking advantage of the MVVM pattern. In my following post I will show you how to easily design a settings UI consistent with the built-in Windows applications.

In Windows 8, application settings are available from any page of a running application by using the settings charm. This brings up a system-provided list of the available settings entry points, with application specific settings at the top (followed by the Windows provided “Permissions” and “Rate and review” items). If the user selects one of these application specified entry points it is the responsibility of the running application to provide the resulting settings UI.

Settings images

Defining a Settings Pane with the Okra App Framework

The Okra App Framework makes it simple to add custom settings panes, following the same pattern as any other page within an Okra based application. The framework takes care of displaying the correct UI and providing a dedicated navigation stack within the settings pane.

Any element may be used to define the settings UI, however a UserControl is most commonly used. This is tagged with a page name using the PageExport attribute in the code-behind file.

[PageExport("MySettings")]
public sealed partial class MySettingsPage : UserControl
{
    ...
}

If using the MVVM pattern, the view-model is similarly defined and attributed with the ViewModelExport attribute.

[ViewModelExport("MySettings")]
class MySettingsViewModel : ...
{
    ...
}

This is all that is required to define an MVVM based settings pane.

Displaying the Settings Pane


Whenever a user opens the settings pane, the currently running application is notified via the ‘SettingsPane.CommandsRequested’ event and asked to return the settings to display. In Okra based applications the recommended place to register for this event is in the SetupServices() method of the application bootstrapper. In the event handler you can add any number of settings commands in the order they are desired.

The Okra App Framework provides an ISettingsManager interface and default implementation to handle the resulting navigation to a settings pane. By calling the ‘NavigateTo(…)’ method the settings UI will be displayed in a slide-in pane at the edge of the screen.

public interface ISettingsPaneManager : INavigationBase
{
    void ShowSettingsPane();
}
 
public interface INavigationBase
{
    bool CanGoBack { get; }
    INavigationEntry CurrentPage { get; }
 
    event EventHandler CanGoBackChanged;
 
    void GoBack();
    void NavigateTo(string pageName);
    void NavigateTo(string pageName, object arguments);
}

To make this even easier, the Okra App Framework provides a helper extension method on any INavigationBase instance named ‘GetNavigateToSettingsCommand(…)’ which takes as arguments the name to display to the user, and the page name we defined in the previous section. Therefore a typical bootstrapper will look as follows,

public class AppBootstrapper : OkraBootstrapper
{
    // *** Imported Properties ***
 
    [Import]
    public ISettingsPaneManager SettingsPaneManager { get; set; }
 
    // *** Overriden Base Methods ***
 
    protected override void SetupServices()
    {
        // Register with Windows to display items in the settings pane
 
        SettingsPane.GetForCurrentView().CommandsRequested += SettingsPane_CommandsRequested;
    }
 
    // *** Private Methods ***
 
    void SettingsPane_CommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args)
    {
        // Add each settings item in the order you wish them to appear
 
        args.Request.ApplicationCommands.Add(SettingsPaneManager.GetNavigateToSettingsCommand("Settings", "MySettings"));
 
    }
}

Navigation Within the Settings Pane


Whilst in many cases a custom settings pane will self contained, multi-page settings are possible. Consider an “Accounts” setting where a link takes you to a further “Add account” settings page. This is fully supported in the Okra App Framework by calling the ISettingsPaneManager.NavigateTo(…) and .GoBack() methods to navigate between sections. In addition, calling ‘GoBack()’ on the first page in the navigation stack will redisplay the system provided settings list.

Summary


To summarise, the Okra App Framework makes adding settings panes to your application simple. The steps are,

  1. Create a UserControl with the desired UI and set the PageExport attribute.
  2. Optionally add a view-model attributed with the ViewModelExport attribute.
  3. In the application bootstrapper register for the SettingsPane.CommandsRequested event and use the GetNavigateToSettingsCommand(…) extension method to return a SettingsCommand.

A sample application demonstrating custom settings panes is available from the Okra CodePlex downloads.

Of course it is up to you to provide a suitable UI for the displayed settings pane. In my next post I will describe how to use Okra’s SettingsChrome to present a UI consistent with the standard Windows experience.