Showing posts with label Metro. Show all posts
Showing posts with label Metro. Show all posts

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.

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.

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).

Monday, April 30, 2012

Navigation in Cocoon – MVVM for Metro-style apps

Over the next series of posts I’m going to introduce a new subsystem within the Cocoon framework for Metro-style applications written in managed languages.
Modern rich client applications often consist of a number of interconnected pages or views. For example consider the Windows 8 “Store”. This has a home page that acts as a hub the links to a number of category pages, which in turn link to the individual application detail pages. The user navigates forward through the application flow by clicking images, buttons or links. They can also navigate backwards by using a back button that is placed in the top left hand corner of each page. In addition there are ‘special pages’ such as search, or even the settings panes available from the settings charm.

There are a number of challenges for developers who wish to correctly implement such a navigation structure.

Navigation in Cocoon

Although not limited to this, the Cocoon framework is designed to work great with the Model-View-ViewModel (MVVM) pattern that has become common when designing XAML based applications. One problem when using this pattern is that you need some way of associating a view with a view-model. Often this is done by navigating directly to a page, and using a “ViewModelLocator” to identify and wire up the respective view-model.

In Cocoon a slightly different approach is used. Here, rather than navigating directly to a view, you navigate to a named page. Although the behaviour is extensible, by default Cocoon will use MEF (the built in composition framework included in .Net) to locate both the view and view-model associated with this page name, create and initialise instances of these and wire them together.

You can export any XAML view (for example the pages created by any of the Visual Studio templates) by adding the ‘PageExport’ attribute to the code-behind file,

[PageExport("BrowsePhotos")]
public sealed partial class BrowsePhotosPage : MyPhotoApp.Common.LayoutAwarePage
{
    public BrowsePhotosPage()
    {
        this.InitializeComponent();
    }
}

And similarly you can export the view-model using the ‘ViewModelExport’ attribute,


[ViewModelExport("BrowsePhotos")]
public class BrowsePhotosViewModel
{
    ...
}

The Navigation Manager

In order to navigate between pages, Cocoon includes a navigation manager that can be accessed by importing the INavigationManager interface through MEF (simplified by the fact that all views and view models in Cocoon are themselves are composed by MEF).


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

The most interesting methods are the two overloads of ‘NavigateTo(…)’ that both take the page name to navigate to. The navigation manager will also keep track of the current navigation stack so that you can easily use the ‘CanGoBack’ property and ‘GoBack()’ method to traverse backwards through the previously visited pages.

For example we could add methods to our BrowsePhotos view model as such,


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

Summary


I have shown above how the Cocoon navigation framework allows you to easily construct a page based navigation structure for applications based upon the MVVM pattern. I have of course glossed over how you navigate to the first page of your application. I will discuss this further next time.

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).