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.

Sunday, November 04, 2012

Okra App Framework v0.9.5 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

  • Settings support
    • The framework now includes support for the Windows 8 settings charm. Custom application settings panes can be defined using the MVVM pattern and Okra will handle the wiring required to show the settings pane – I will write about this in detail in an upcoming blog post.
    • A SettingsChrome control is included to allow developers to easily match the settings UI of the default Windows 8 applications
  • The NavigationManager class has now been refactored to derive from a NavigationBase class with the base functionality. This allows the creation of custom navigation managers (for example the SettingsPaneManager)
  • Updated to support MEF v1.0.16
  • Minor improvements and bug fixes

Monday, October 29, 2012

App Search and the Okra App Framework

One advantage of the Okra App Framework over other MVVM-based application frameworks is that it is designed from the ground up to work great with Windows 8. Over the next few versions this will become more evident as features are added to support the various Windows 8 system contracts – search, settings, sharing, etc.

In this post I will describe how the Okra App Framework makes it easy to add search to your application using the same MVVM principles that you are using for the rest of your application.

The Search Contract in Windows 8

When developing Windows Store applications many developers will want to take advantage of the Windows 8 search charm. This allows users to search across all applications from a single, consistent entry point. In order to add search functionality you would generally override the OnSearchActivated(…) method in the App.xaml.cs code-behind. In fact the standard Visual Studio search page template will add the code required to do this. For a great Windows Store application however you would want to,

  • Fully follow the Windows search design guidelines (available here)
  • Preserve the existing application state and correctly handle back navigation from the search page
  • Navigate to a suitable page (normally the application home page) if an empty search is performed
  • Improve performance by attaching to the SearchPane.QuerySubmitted event where possible
  • You may also want to implement the search page using the MVVM pattern

By simply using the Okra App Framework search manager it will take care of these requirements.

Adding Search to Your Application with the Okra App Framework

The Okra App Framework provides a search manager to handle the process of activating search in your application. This is represented by the ISearchManager interface,

public interface ISearchManager
{
    string SearchPageName { get; set; }
}

By default the SearchPageName property is set to null, and Okra will not handle search activation. To opt-in to the search integration you should set the page name for search in your application’s bootstrapper SetupServices() method.

public class AppBootstrapper : OkraBootstrapper
{
    protected override void SetupServices()
    {
        SearchManager.SearchPageName = "Search";
    }
}

By adding this single line your application has been enabled for search, and a page named “Search” will be navigated to when the user performs a search within your application (note that you will also need to declare that your application supports search in the application manifest).

Defining Your Search Page


Because search uses the standard Okra page discovery mechanisms you define your search page and view-model as you would any other page within your application,

[PageExport("Search")]
public sealed partial class SearchPage : LayoutAwarePage
{
    ...
}
 
[ViewModelExport("Search")]
public class SearchViewModel : NotifyPropertyChangedBase, ISearchPage
{
    ...
}

One thing to note is that the search view model implements the ISearchPage interface (this could also be implemented by the page if you are not using the MVVM pattern),

public interface ISearchPage
{
    void PerformQuery(string queryText, string language);
}


This method will be called whenever the page should show a new set of search results. In this method you provide the application logic to perform the search operation and display the results to the user. Note that this may be called multiple times for a single page as the user performs subsequent searches and you should refresh the content with the new results.

Summary


In the above discussion I have shown how the Okra App Framework makes it simple to implement search functionality in applications based on the MVVM pattern.

A sample search application is available from the Okra CodePlex downloads section. This is based on the Visual Studio search template, but modified to correctly implement the MVVM pattern.

Wednesday, September 05, 2012

Convention Based Page Discovery With The Okra App Framework

One of the key features of the Okra App Framework for developing Windows 8 apps is the navigation framework with its support for the MVVM pattern. By default pages and view-models are marked with attributes so that the framework can locate them. In this post I will describe how you can enable an alternative convention based approach.

The Default Attribute Based Approach

When using the Okra App Framework navigation support all pages are represented by a page name. So that the framework can locate the associated pages and view-models these are normally attributed with either the PageExportAttribute or ViewModelExportAttribute respectively (for more information see my previous post). For example for a page named “Foo” the classes would be attributed as,

[PageExport("Foo")]
public sealed partial class FooPage : LayoutAwarePage
{
    ...
}
 
[ViewModelExport("Foo")]
public class FooViewModel
{
    ...
}

A Convention Based Approach

Often however there will be a common naming pattern throughout the application. In the example above all pages are named XxxPage and view-models named XxxViewModel, where “Xxx” is the associated page name. In a convention based approach you no longer need to apply attributes to classes. Instead they are automatically discovered based on a common naming system.

Since the standard Okra bootstrapper uses MEF for composition (for example when using the Okra.MEF NuGet package), we can use the MEF convention based discovery. To enable this we need to add the following code to the application bootstrapper,

public class AppBootstrapper : OkraBootstrapper
{
    ...
 
    // *** Overriden base methods ***
 
    protected override ContainerConfiguration GetContainerConfiguration()
    {
        ConventionBuilder conventionBuilder = new ConventionBuilder();
 
        conventionBuilder.ForTypesMatching(type => type.FullName.EndsWith("Page"))
                         .Export(builder => builder.AsContractType<object>()
                                                   .AsContractName("OkraPage")
                                                   .AddMetadata("PageName", type => type.Name.Substring(0, type.Name.Length - 4)));
 
        conventionBuilder.ForTypesMatching(type => type.FullName.EndsWith("ViewModel"))
                         .Export(builder => builder.AsContractType<object>()
                                                   .AsContractName("OkraViewModel")
                                                   .AddMetadata("PageName", type => type.Name.Substring(0, type.Name.Length - 9)));
 
        return GetOkraContainerConfiguration()
                .WithAssembly(typeof(AppBootstrapper).GetTypeInfo().Assembly, conventionBuilder);
    }
}

With this code in place we can greatly simplify our page and view-model definitions to the following. Note that since we follow the convention we no longer need to add any attributes.

public sealed partial class FooPage : LayoutAwarePage
{
    ...
}
 
public class FooViewModel
{
    ...
}

Summary

As I have shown, when using the Okra App Framework navigation support you can simplify app development by using a convention based approach to defining pages and view-models for the MVVM pattern.

A sample application demonstrating this is available from the Okra CodePlex downloads.

Monday, August 27, 2012

Okra App Framework v0.9.4 Released

Version 0.9.4 of the Okra App Framework is now available via CodePlex and NuGet. Since the core functionality of the framework has been in testing for some time now I have removed the ‘beta’ suffix from the version number, with the benefit that the framework should show in the default NuGet feed.

Minimal changes and bug fixes were made in this release, with the key change being updating the Okra App Framework to work against the RTM version of MEF (v1.0.15).

Sunday, August 12, 2012

Cocoon is now the Okra App Framework

Today I would like to announce that the Cocoon framework is now know as the ‘Okra App Framework’. It still includes the great features previously available in the Cocoon framework, but from now onwards will be developed under the new name.

How to Get The Okra App Framework

The ‘Okra App Framework’ CodePlex site is available at http://okra.codeplex.com/ (all previous code/downloads/discussions have been migrated from the old site, and any links to the previous URLs will redirect to their new location).

In addition there are two new NuGet packages,

If you are using the Cocoon NuGet packages and wish to get future releases then you should use the NuGet package manager to uninstall Cocoon and then install the new Okra App Framework package.

Okra App Framework Release 0.9.3-beta

Along with the name change a new version of the framework has been released via NuGet and the Okra App Framework CodePlex downloads page. The changes include,

  • Namespace changes from ‘Cocoon’ to ‘Okra’ and from ‘CocoonBootstrapper’ to ‘OkraBootstrapper’ (a simple find-and-replace in your project should solve any errors occurring from this).
  • Addition of a SearchManager that allows an easy, view-model centric, implementation of the Windows 8 Search contract (I will aim to detail this in a future blog post).
  • The ActivationManager class allows extensible handling of application activation (you can write activation handlers to handle any of the activation types).
  • Upgraded to MEF version 1.0.13-rc.
  • Removal of the previous obsoleted VirtualizingVector with the recommendation that VirtualizingVectorBase is used going forward (although if you still require VirtualizingVector it can be downloaded as part of any of the previous source releases and copied into your own projects).

Why the Name Change?

I recently received a message from a member of the Apache Software Foundation, informing me that they also have a web application framework named Apache Cocoon. To avoid any confusion that may arise between the two frameworks the best approach going forward was a name change.

Monday, August 06, 2012

Shell Based Navigation in Cocoon

I recently had a query in the Cocoon CodePlex forums regarding how to support an application shell when using the Cocoon framework’s navigation support. By default the Cocoon navigation framework will display pages full screen, with each navigation replacing the previous page with the next. There are some occasions however where it makes sense to have an application shell that takes up the full screen, with the page navigation occurring in a region within this.

A typical example would consist of a fixed region dedicated to navigation at the top of the screen, with the page content filling below. The end result looks like,

image

Creating an Application Shell in Cocoon

The key to creating an application shell in Cocoon is the INavigationTarget interface. This has only a single method named NavigateTo(…). When implemented by an application, any calls to the navigation framework will result in a call to this method with the page to display. The framework itself will handle the creation and wiring up of views and view-models, the navigation stack, persistence and other aspects of navigation.
In our example application we will use the MVVM pattern to define our application shell, hence we have a ShellViewModel,

   1: [Export(typeof(INavigationTarget))]
   2: [Shared]
   3: public class ShellViewModel : NotifyPropertyChangedBase, INavigationTarget
   4: {
   5:     // *** Fields ***
   6:  
   7:     private object content;
   8:     private ShellPage shellPage;
   9:  
  10:     // *** Properties ***
  11:  
  12:     public object Content
  13:     {
  14:         get
  15:         {
  16:             return content;
  17:         }
  18:         set
  19:         {
  20:             if (content != value)
  21:             {
  22:                 content = value;
  23:                 OnPropertyChanged();
  24:             }
  25:         }
  26:     }
  27:  
  28:     // *** INavigationTarget Methods ***
  29:  
  30:     public void NavigateTo(object page)
  31:     {
  32:         // If this is the first navigation then create the shell view and bind to this view model
  33:  
  34:         if (shellPage == null)
  35:         {
  36:             shellPage = new ShellPage();
  37:             shellPage.DataContext = this;
  38:         }
  39:  
  40:         // Set the content for the shell to the specified page
  41:  
  42:         this.Content = page;
  43:  
  44:         // Set the shell view as the window content
  45:  
  46:         Window.Current.Content = shellPage;
  47:     }
  48: }

The ShellViewModel exposes a single property named ‘Content’ that will contain the page to display and will be bound to in the view. In our NavigateTo(…) method we firstly determine if we have created the associated view and create this is necessary. We then set the ‘Content’ property to the supplied page and this ensure that the view is displayed in the window. Finally we mark the class as a shared export of INavigationTarget using the MEF attributes. Note that since we will never be navigating explicitly to the shell then we do not need to decorate this with a ViewModelExport attribute.

In the sample code the shell view model also exposes a ‘GoBackCommand’ that allows you to include a back navigation button within the shell region.

The ShellPage.xaml file contains the view for the application shell. This simply contains the required elements for the upper portion of the screen, with a ContentControl bound to the view models ‘Content’ property. It is within this ContentControl that the pages will be displayed. The key elements are shown below,


   1: <Grid Style="{StaticResource LayoutRootStyle}">
   2:     ...
   3:  
   4:     <!-- Back button and page title -->
   5:     <Grid>
   6:         <Grid.ColumnDefinitions>
   7:             <ColumnDefinition Width="Auto"/>
   8:             <ColumnDefinition Width="*"/>
   9:         </Grid.ColumnDefinitions>
  10:         <Button x:Name="backButton" .../>
  11:         <TextBlock x:Name="pageTitle" .../>
  12:     </Grid>
  13:     <ContentControl Content="{Binding Content}" .../>
  14: </Grid>

When the application is run the NavigationManager will automatically locate the INavigationTarget through the MEF export and direct all navigation through this.

Summary

I have shown above how you can implement an application shell using the Cocoon framework. The sample application with full source code is available from the Cocoon CodePlex downloads.