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.

Tuesday, July 24, 2012

Cocoon Framework v0.9.2 Released

As I discussed in my previous post on NuGet support in the Cocoon framework, I will be distributing major updates within the framework as new releases. Today I am pleased to say that version 0.9.2 is available from both the Cocoon CodePlex site and downloadable directly from NuGet.

New Features in This Release

This release has mainly focussed upon updates to the Cocoon data framework. In particular,

  • Significant improvements in how the data framework handles caching of list items.
  • Infrastructure added to support change notifications for data lists.
  • The ‘PagedDataListSource’ class now includes a ‘PageCacheSize’ property that allows you to specify the maximum number of pages to hold in memory at any one time (by default all pages are stored).
  • Introduction of an ‘IncrementalLoadingDataList’ class. This supports the Windows 8 Metro ISupportIncrementalLoading interface. This allows a data bound UI to download a small subset of a large list of items, with further items being retrieved and added when the user scrolls to the end of the list.
  • A Refresh() method has been added to SimpleDataListSource and PagedDataListSource. This allows you to clear the internal cache and re-fetch any data that may have changed. Any attached data lists will automatically update to reflect the changes.

Some improvements to the navigation framework include,

  • Updated to support MEF version 1.0.11-rc.
  • Changes to the ‘CocoonBootstrapper’ to help with a convention based approach to exporting pages and view models (I will write a blog post on this in the future).
  • The navigation manager now exposes a ‘CurrentPage’ property so that you can programmatically determine the currently displayed page and associated information.
  • Pages and view-models can now be named by specifying a type as an alternative to a string page name.
  • A MEF sharing boundary (named “page”) has been placed around each page and view model pair (see here for more information on MEF sharing boundaries).
  • Some common MVVM base classes have been included. Whilst you are not restricted to using these to take advantage of the Cocoon framework they provide basic functionality that is common to many applications. These classes include,
    • DelegateCommand and DelegateCommand<T> – implementations of the ICommand interface that allow you to bind UI interactions to methods on your view models.
    • NotifyPropertyChangedBase – provides a simple base class for view models that supports property change notification.
  • A number of other bug fixes.

Breaking Changes

Unfortunately there are a small number of breaking changes in this release. For most developers however the changes should be minimal.

  • ‘SpecialPageNames.HomePage’ has been renamed ‘SpecialPageNames.Home’.
  • The contract for IDataListSource has changed. Note that this should only affect developers who are writing custom IDataListSource implementations. If you are using SimpleDataListSource or PagedDataListSource then existing code should not be affected. In particular the changes are,
    • Addition of an IndexOf(…) method to the IDataListSource interface.
    • The data list source implementations are now fully responsible for caching of data.
  • The ‘InternalList’ property of ‘DataListSourceBase’ has been removed (derived classes should create their own internal cache) and the corresponding property in ‘SimpleDataListSource’ and ‘PagedDataListSource’ has been made private.
  • VirtualizingVector<T> is now marked as Obsolete – it is recommended that you use the data list support or the new VirtualizingVectorBase<T>.

Getting the Latest Version of Cocoon

To get the latest release of the Cocoon framework the best place to start is using the NuGet package manager to download the “Cocoon Framework” package (see here for more information). If you are already using Cocoon via NuGet then you should be able to update your solution to the latest version directly through the NuGet package manager.

Alternatively the source code is available via the Cocoon CodePlex downloads page. As always the latest interim code drops are also available from CodePlex under the source code tab.

Tuesday, June 26, 2012

Cocoon Now Available on NuGet

Update : The 'Cocoon' framework is now named the 'Okra App Framework'. For information on how to obtain the framework via NuGet then see the documentation here.
I am very pleased to announce that the Cocoon framework is now available via NuGet (thanks to Brendan Forster for helping to get this off the ground). Going forward this will be the recommended source when using the framework in your own projects.

Getting Cocoon Via NuGet

With the release of Visual Studio 2012, the NuGet package manager is included within the product. This means that to reference the Cocoon framework all you need to do is to right-click on the project’s “References” folder and select “Manage NuGet Packages…”

Note that since the Cocoon framework is currently pre-release then you should select “Include Prerelease” in the box highlighted in red below. You can then search for “Cocoon”.


Note that there are currently two packages for the Cocoon framework. In general you should select the package named “Cocoon Framework” as this includes the complete framework including the MEF based bootstrapper. Clicking install will then download Cocoon along with any dependencies and add these to your project.

Updating Your Project to the Latest Version Of the Cocoon Framework

One of the advantages of using NuGet to distribute the Cocoon framework is that it makes it very easy to upgrade projects to the latest version of the framework. To do this simply open the package manager for a project that you have previously added Cocoon via NuGet and select the “Updates” tab. Any updated packages will be displayed and can be upgraded with a single click.


Note: Making the Cocoon Framework Independent of Composition Container

I have had a number of queries from developers who wish to use alternative composition containers with the Cocoon framework. Whilst it is recommended for most projects that you use the provided MEF composition implementation, with this latest release the Cocoon framework can now be used with any other composition container. The project has been split into two assemblies,
  • Cocoon – contains the core framework independent of composition container.
  • Cocoon.MEF – contains the MEF dependencies (most importantly the MEF based “CocoonBootstrapper”).

How Will Cocoon be Released in the Future?

Going forward there will be three ways to obtain the Cocoon framework,
  • NuGet: This is the recommended source and will contain the latest stable versions. If I discuss any functionality on this blog then it will be implemented in the latest NuGet release unless otherwise stated.
  • CodePlex Downloads: I will also provide a zipped package of the source code via CodePlex in the Cocoon downloads section. This will be kept in sync with the NuGet releases.
  • CodePlex Source Control: For those interested in the very latest versions of Cocoon then this will be available as always via the “Source Code” tab of the Cocoon CodePlex site. Note however that this may include experimental functionality and may not be stable.

Wednesday, June 06, 2012

Cocoon Updated for Windows 8 Release Preview

You will be pleased to hear that I have just pushed an updated version of the Cocoon framework onto CodePlex that supports the Windows 8 Release Preview.

As usual the code is freely available for download from the Cocoon CodePlex site (to get the latest version go to the “Source Code” tab, select the first change set and use the “Download” link).

Using MEF in the Release Preview

As many of you will be aware, the Cocoon framework uses the Managed Extensibility Framework (MEF) by default for locating and composing applications. With the release of the Windows 8 Release Preview, MEF is not being distributed separately – for more details see the announcement on the BCL team blog.

You will therefore need to add MEF as a reference to your application via NuGet. The above link has more details however the steps are,

  1. Right click on your projects ‘References’ folder and select “Manage NuGet Packages…”
  2. Select “Online” in the left-hand pane and make sure that you have “Include Prerelease” selected rather then “Stable Only” at the top.
  3. Use the search box to search for “MEF”
  4. Select “MEF for web and Metro style apps” and click “Install”

Changes in tHis Release of Cocoon

In general most applications should not be affected by the changes in this version of Cocoon (apart for the fact that they will run on the Release Preview!). Changes of interest include,

  • All use of MEF has been modified to support the new version
  • The ‘CocoonBootstrapper’ no longer has an overridable GetPartCatalog() method and is replaced with GetContainerConfiguration().
  • The ISupportPlaceholder interface has been removed in the Release Preview. The VirtualizingVector<T> implementation has been updated to reflect these changes and now returns ‘null’ as a placeholder (as now expected by the standard XAML controls).
  • Many other updates and bug fixes

Tuesday, May 29, 2012

Cocoon Navigation – Making Your App “Always Alive”

Over the last few posts I have discussed the navigation framework that is included as part of the freely available Cocoon framework for developing Metro-style Windows 8 applications in .Net languages. I have shown how to annotate pages to be discovered by the framework and how to pass arguments between pages.

In this post I will discuss one of the benefits of using the Cocoon framework to manage your application’s navigation.

Making Your Application “Always Alive”

One of the challenges when writing Windows 8 Metro-style applications is to manage the application lifecycle. So that Windows is able to ensure a great experience for users running on battery powered devices, Metro style apps are suspended as the user moves to other applications. Furthermore, your application may be terminated to free more memory if this is required. However for the end user great Metro-style applications will give the impression that they are “always alive” in the background. It is up to you, the developer, to ensure that this illusion is maintained. For more background Microsoft’s Windows 8 Application Developer blog has a great post on this topic.

One aspect of making your application feel “always alive” is to ensure that if it is terminated and later relaunched then the user is taken to exactly the same point that they were previously viewing. To do this you must persist the navigation stack, currently viewed page and any page state then subsequently restore this.

Persisting Navigation With the Cocoon Framework

The great news is that if you are using the Cocoon navigation framework then this is all handled automatically for you. All you have to do is enable this by setting the INavigationManager.NavigationStorageType property. Typically you would set this by overrinding the SetupNavigationManager() method in your application bootstrapper (see this post for more information on the bootstrapper),

public class AppBootstrapper : CocoonBootstrapper
{
    // *** Overriden base methods ***
 
    protected override void SetupNavigationManager()
    {
        NavigationManager.NavigationStorageType = NavigationStorageType.Local;
    }
}

There are currently three possible NavigationStorageType values,

  • None – Your navigation state will not be persisted and your application will always launch to your home page.

  • Local – Your navigation state will be persisted to the current machine only.

  • Roaming – Your navigation state will be persisted between all devices that the user logs into using their Microsoft Account.

That’s all you need to do, Cocoon will handle everything else – persisting the navigation stack, restoring to the correct page, storing the arguments passed to each page.

Preserving Page State

In some cases you may want to go a step further and store some page state. Imagine for example you are half way through writing a comment in a social networking app, then change app to do something else. When you return you should expect that you can continue from where you left off. Other things you may want to preserve are selected search filters, selected items, position in a view, etc.

Preserving page state can be done by the view model implementing the IActivatable<TArguments, TState> interface that I discussed last time for passing arguments to pages. The TState generic type can be set to the data type you would like to persist (TArguments can be set to ‘string’ if it is not required).

public interface IActivatable<TArguments, TState>
{
    // *** Methods ***
 
    void Activate(TArguments arguments, TState state);
    TState SaveState();
}

On first navigation to the page the Activate(…) method will be called passing the default value of TState (‘null’ for string or reference types). When Cocoon determines that it should preserve page state then it will call the SaveState() method and your implementation should return the current state. If the application is later terminated and relaunched then a new instance of the view model is created and activated by calling the Activate(…) method with the preserved state.

For example, if as part of a hypothetical photo browsing app we allow the user to comment on a photo we could implement the view model as,

[ViewModelExport("ViewPhoto")]
public class ViewPhotoViewModel : IActivatable<string, ViewPhotoState>
{
    // *** Properties ***
 
    public string Comment
    {
        get { ... }
        set { ... }
    }
 
    ...
 
    // *** IActivatable Methods ***
 
    public void Activate(string arguments, ViewPhotoState state)
    {
        this.Photo = GetPhoto(arguments);
        
        if (state != null)
        {
            ViewPhotoState viewState = (ViewPhotoState)state;
            this.Comment = viewState.Comment;
        }
    }
 
    public ViewPhotoState SaveState()
    {
        return new ViewPhotoState() { Comment = this.Comment };
    }
 
    // *** Sub-classes ***
 
    [DataContract]
    private class ViewPhotoState
    {
        [DataMember]
        public string Comment;
    }
}

Note that we store the state as a custom ‘ViewPhotoState’ object that is decorated to allow serialization by the DataContractSerializer.

Summary


I have shown above how we can easily make our applications feel “always alive” by using the Cocoon navigation framework.

As usual the code is freely available for download from the Cocoon CodePlex site (to get the latest version go to the “Source Code” tab, select the first change set and use the “Download” link).

Sunday, May 20, 2012

Cocoon Navigation – Passing Arguments Between Pages

Over the last couple of posts I have introduced the navigation framework that is included as part of the freely available Cocoon framework for developing Metro-style Windows 8 applications. I have previously shown how to annotate pages with the PageExport and ViewModelExport attributes, and to navigate to these using the INavigationManager.

Passing Arguments to ViewModels

Whilst navigating between pages is a common pattern for modern applications, often you wish to pass some state during page navigation. As an example, imagine a photo browsing application. The “BrowsePhotos” page may show a number of images, which when clicked on navigates to a “ViewPhoto” page. In this case there needs to be some way to pass the image to display as an argument to the “ViewPhoto” page.

This is made simple in the Cocoon navigation framework by a second overload of the INavigationManager.NavigateTo(…) method that takes both a page name and an argument to pass between the pages.

public interface INavigationManager
{
    ...
 
    void NavigateTo(string pageName);
    void NavigateTo(string pageName, object arguments);
}

The ‘arguments’ parameter can be of any type, however there are a number of restrictions that should be observed in practice,
  • The type should be able to be serialized via a DataContractSerializer

  • The type should not rely on a reference to any particular object (for example if the value is from a shared cache it may be better to pass the key rather than the actual object to ensure that multiple versions are not created)

In our photo application example we are caching the image details, so pass the photoID from the “BrowsePhotos” view model,

[ViewModelExport("BrowsePhotos")]
public class BrowsePhotosViewModel
{
    // *** Fields ***
 
    private readonly INavigationManager navigationManager;
 
    // *** Constructors ***
 
    [ImportingConstructor]
    public BrowsePhotosViewModel(INavigationManager navigationManager)
    {
        this.navigationManager = navigationManager;
    }
 
    // *** Command Methods ***
 
    public void ViewPhoto(Photo photo)
    {
        navigationManager.NavigateTo("ViewPhoto", photo.PhotoId);
    }
}

Activating Destination Pages

The destination view model is able to accept parameters by implementing the IActivatable<TArguments, TState> interface where the type of the argument is designated by TArguments. The TState generic type will be discussed in a later blog post and if not required can be set as ‘string’.

public interface IActivatable<TArguments, TState>
{
    // *** Methods ***
 
    void Activate(TArguments arguments, TState state);
    TState SaveState();
}

After creating the new view model the Cocoon framework will call the Activate(…) method passing in the argument passed from the call to INavigationManager.NavigatedTo(…). This method will only be called once and prior to display of the view.

In our example photo browsing application the “ViewPhoto” view model will therefore be implemented as (Note that the unused SaveState() method simply returns ‘null’),

[ViewModelExport("ViewPhoto")]
public class ViewPhotoViewModel : IActivatable<string, string>
{
    ...
 
    // *** IActivatable Methods ***
 
    public void Activate(string arguments, string state)
    {
        this.Photo = GetPhoto(arguments);
    }
 
    public string SaveState()
    {
        return null;
    }
 
    // *** Private Methods ***
 
    private Photo GetPhoto(string photoId)
    {
        ...
    }
}

Summary


I have describe above how the Cocoon framework makes passing arguments between pages simple to implement. Over the next posts I will discuss some of the added value when using the Cocoon navigation framework, including how to make your application seem “always alive”.

As usual the code is freely available for download from the Cocoon CodePlex site (to get the latest version go to the “Source Code” tab, select the first change set and use the “Download” link).

Tuesday, May 15, 2012

Getting Started with Cocoon Navigation – The Cocoon Bootstrapper

In my last post I introduced the navigation framework that is included as part of the freely available Cocoon framework (open source on CodePlex). This framework is designed to make page based Metro-style applications easy to construct in managed languages on Windows 8.

I previously discussed how easy it was to implement the Model-View-ViewModel (MVVM) pattern with Cocoon by simply annotating your view and view models with the ‘PageExport’ and ‘ViewModel’ export attributes respectively. Any view model can then navigate to another page by calling the INavigationManager.NavigateTo(…) method.

Since the Cocoon navigation framework is built on top of the Managed Extensibility Framework (MEF), the application is composed with the required dependencies as the user navigates through the application. MEF is a composition framework that is built into the .Net framework, that enables the construction of loosely-coupled, easily maintainable and testable applications to be composed automatically at run time. An introductory guide for those who are not familiar with MEF is available here.

What I have not covered previously however was how to navigate to the application’s first page when it is launched,

Launching Navigation Using The Cocoon Bootstrapper

To simplify the initialization of Cocoon based applications the framework includes the ‘CocoonBootstrapper’ class that can be used at startup. This manages the configuration of MEF for the most common scenarios, initialization of services and activation of the application.

To use the Cocoon bootstrapper you must first create an application specific class derived from the abstract ‘CocoonBootstrapper’ as shown below. For basic applications this class can be left empty, although the base implementation provides a number of extensibility points to enable more advanced features.

public class AppBootstrapper : CocoonBootstrapper
{
}


The next stage is to edit your application’s ‘App.xaml.cs’ file. Much of the code included with the Visual Studio templates can be removed (since this is handled by Cocoon) and the newly created bootstrapper is initialized as part of the constructor.


sealed partial class App : Application
{
    public App()
    {
        this.InitializeComponent();
 
        // Create and initialize the application bootstrapper
 
        AppBootstrapper bootstrapper = new AppBootstrapper();
        bootstrapper.Initialize();
    }
}


Defining the Application Home Page

The final step is to define the view and (optionally) the view model that is to be shown when your application is launched. Whilst the home page name can be modified the default value defined by the ‘SpecialPageNames.HomePage’ constant is generally all that is required.

Therefore the home page view is annotated as,

[PageExport(SpecialPageNames.HomePage)]
public sealed partial class HomePage : LayoutAwarePage
{
    public HomePage()
    {
        this.InitializeComponent();
    }
}

and the view model annotated as,

[ViewModelExport(SpecialPageNames.HomePage)]
public class HomeViewModel
{
    ...
}


The Cocoon navigation framework will then automatically locate, create and wire-up the home page on application launch.

Summary

Over the last two posts I have shown how easy the Cocoon navigation framework makes launching and navigating around Metro-style Windows 8 applications using the MVVM pattern. In the upcoming posts I will discuss some of the more advanced features you get when adopting Cocoon for navigation.

As usual the code is freely available for download from the Cocoon CodePlex site (to get the latest version go to the “Source Code” tab, select the first change set and use the “Download” link).