Corrado's Blog 2.0

Online thoughts of a technology funatic

MvvmStack for WinJS: Command support

A Command represents an abstraction over an action, the command can also indicate whether the action is available or not and, normally, UI elements tied to a command disables themselves when command is not available, if you’re new to MVVM’s commanding I recommend this article.

While more a .NET concept than a Mvvm pattern core feature, i decided to add support for it with latest checkin since its wide popularity and to keep the stack aligned with other .NET based libraries.

In  .NET a Command depends upon the ICommand interface and it is generally implemented by generic classes like RelayCommand or DelegateCommand, for MvvmStack I’ve used a simpler implementation available in relayCommand.js

(function (winjs) {
    "use strict";

    var RelayCommand = WinJS.Class.define(function(execute) {
        this.execute = execute;
        this.execute.supportedForProcessing = true;
        this.canExecute = winjs.Binding.as({value:true});
    },
        {
            execute: null,
            canExecute: null
        });

    winjs.Namespace.define("MvvmStack", {
        RelayCommand: RelayCommand
    });

})(WinJS)

To use it all you need is to expose instances of RelayCommand from your viewmodels, sample code exposes them in sectionViewModel.js

firstCommand: new mvvmStack.RelayCommand(function (element) {
            this.currentPage.value = 0;
            this.firstCommand.canExecute.value = false;
            this.lastCommand.canExecute.value = true;
        }),
        lastCommand: new mvvmStack.RelayCommand(function (element) {
            this.currentPage.value = this.images.length - 1;
            this.firstCommand.canExecute.value = true;
            this.lastCommand.canExecute.value = false;
        }),

then we wire the commands with application bar commands in section.html page

<div data-win-control="WinJS.UI.AppBar">
            <button
                data-win-control="WinJS.UI.AppBarCommand"
                data-win-bind="onclick:firstCommand Binding.Mode.command"
                data-win-options="{icon:'home', id:'', label:'Home', section:'global', type:'button'}">
            </button>
            <button
                data-win-control="WinJS.UI.AppBarCommand"
                data-win-bind="onclick:lastCommand Binding.Mode.command"
                data-win-options="{icon:'next', id:'', label:'Last', section:'global', type:'button'}">
            </button>
        </div>

In order to keep button state in sync with commands availability we use a new Binding.Mode.command initializer, also note how click event binds to command and not to its execute function.

As usual the binding initializer is defined inside binding-extensions.js, you can update it in case you need to handle other enable/disable scenarios.

Binding.Mode.command automatically adds a mvvm-disabled class to invoking element (app bar buttons in our case) so that you can use a css class to change the look of the control while in disabled state.

To see commands in action, run the sample, navigate to section page and click application bar’s buttons or navigate through images to see how buttons follow current’s image position.

Hope you like it Smile

PS: In order to simplify dev life I’ve added a watch function to viewModelBase that allows to invoke a function when an observable property changes (just a simple wrapper around bind function indeed Winking smile)

MvvmStack for WinJS: Services persistence

While refactoring MvvmStack for WinJS code i noticed that I did not show how to persist the state of the services when the app get suspended, so i checked in a new version that persist the data contained inside imageService.js (in a real world app, the data will probably come from a remote server).

The strategy I use is to let the services that need to keep their state add themselves to a services collection exposed by applicationControllerBase object that is passed to each service instance:

(function (winjs, applicationController) {
    var images = [];
    var cachedId;
    var imageService = {
        load: function (id) {
            return new winjs.Promise(function (c, e) {
                //Returns cached images when available
                if (cachedId == id && images.length > 0) {
                    c(images);
                } else {
                    cachedId = id;
                    if (id == 1) {
                        images = [
                            { uri: "/images/data/Photo1.jpg", title: 'Photo 1' },
                            { uri: "/images/data/Photo2.jpg", title: 'Photo 2' },
                            { uri: "/images/data/Photo3.jpg", title: 'Photo 3' },
                            { uri: "/images/data/Photo4.jpg", title: 'Photo 4' },
                            { uri: "/images/data/Photo5.jpg", title: 'Photo 5' }];
                    } else {
                        images = [
                            { uri: "/images/data/Photo6.jpg", title: 'Photo 6' },
                            { uri: "/images/data/Photo7.jpg", title: 'Photo 7' },
                            { uri: "/images/data/Photo8.jpg", title: 'Photo 8' }];
                    }

                    c(images);
                }
            });
        },
        serialize: function () {
            return {
                images: images,
                id:cachedId
            };
        },
        hydrate: function (state) {
            images = state.images;
            cachedId = state.id;
        }
    };

    winjs.Namespace.define("Demo.Services", {
        imageService: imageService
    });

    applicationController.services.push(Demo.Services.imageService);

})(WinJS, Demo.Application.ApplicationController)

As you see in code above the service also exposes the same methods serialize and hydrate we met when speaking about viewmodels that serialize and deserialize service state to/from a json object.

Once we registered and added these functions, the task of invoking them when needed is contained inside Mvvm Stack’s common peristenceService.js

Here’s a fragment of serializaion code:

 //De-Serializes services that implements serialize function
            var j = 0;
            applicationController.services.forEach(function (service) {
                if (service.hydrate !== undefined) {
                    var serviceKey = "service" + j;
                    var serviceState = winjs.Application.sessionState.app[serviceKey];
                    service.hydrate(serviceState);
                }
            });

No rocket science, but it makes stack more complete and usable in real production code.

MvvmStack for WinJS Part#5

In this last post about MvvmStack I’m going to cover two aspects: Binding and Blendabilty.

Binding

I’m not going into WinJS Binding since MSDN documentation provides a lot of material, i just want to describe some binding extensions available into binding-extension.js file that extends WinJS binding capabilities.

image

Inside Binding.Extensions namespace you find:

twoWay: I’ve described it here

eventToProperty: Allows you to update a viewmodel property when a control event occurs, you can also specify a two-way mode so that when viewmodel’s property changes the control’s property is updated with new value. The demo uses it to notify the viewmodel that user flipped the image on flipview control (on section.html page) and to move to fist or last image on set using application bar’s buttons.

Here’s how is declared inside section.html page:

        <div id="flip"
            data-win-control="WinJS.UI.FlipView"
            data-win-bind="winControl.itemDataSource:images.dataSource; winControl.onpagecompleted$currentPage.value:winControl.currentPage$two Binding.Extensions.eventToProperty"
            data-win-options="{ itemTemplate : select('.flipItemTemplate') }">
        </div>

The syntax is [triggerEvent]$[viewModelProperty]:[controlProperty][$two], previous html snippet shows how, when FlipView’s onPageCompleted triggers, we update viewmodel’s currentpage.value property using control’s currentPage property in two way mode.

invokeOnEvent: Invokes a viewmodel’s method when an event occurs, passing event source as parameter to target function (sort of ‘sender’ parameter C# counterpart) if you don’t need sender, just use standard WinJS binding.

arrayBind: Allows binding to viewmodel’s properties exposed as arrays using this syntax: [sourceProp]:[property][index][property] e.g: data-win-bind="src:dataTile[0].image"

Blendability

If you, like me, use Blend for HTML tool to design the views you know that it offers an interesting interactive mode.

By clicking following button:

image

your app is run, you can play with it, then exiting from interaction mode, start modifying the live DOM acting on current live state.

Sometimes running the app and reaching the page you want to edit is tedios, that’s why i prefer to use an alternative way.

Inside defaul.html you’ll see that there’s a commented PageControlNavigator definition, this is the one i use to start app from a specific page, let’s change default.html markup this way.

<body>
    <!--<div id="contenthost" data-win-control="Application.PageControlNavigator" data-win-options="{home:'/pages/home/home.html'}"></div>-->

    <!--Uncomment this when you want to design a specific application page, dont forget to create fake data inside ViewModelLocator-->
    <div id="contenthost" data-win-control="Application.PageControlNavigator" data-win-options="{home:'/pages/section/section.html'}"></div>
</body>

Next we need to create some design-time data for editing purposes, so we uncomment the call to createDesignTimeViewModels line inside viewModelLocator.js

  //Uncomment this to create a fake design time viewmodel to use with the page associated with default.html's page navigator
    viewModelLocator.createDesignTimeViewModels();

what the function does is create some fake data when the page is loaded inside Blend.

Opening default.html in Blend now shows the page populated with fake data so you can start editing it.

image

Closing

Think I’ve covered everything you need to know to play with sample code, as stated initially there’s room for improvements and modifications. My goal was to provide an example of how to use MVVM patter in WinJS based applications.

Hope you enjoyed reading. Winking smile

MvvmStack for WinJS Part #4

In part3 we learned how to customize the components tied to our application, it is now time to investigate the ViewModels associated with each view.

Lets’ start seeing how a viewmodel is declared, inspecting homeViewModel.js, the one paired with demo application home view.

(function (winjs, mvvmStack, target) {
    "use strict";

    var HomeViewModel = winjs.Class.derive(mvvmStack.ViewModelBase, function (applicationController) {
        var data = [{ name: "Section 1", id: 1, description: "My color photos", image: "/images/phones/lumia920.jpg" },
            { name: "Sezione 2", id: 2, description: "My b/w photos", image: "/images/phones/lumia820.jpg" }];

        this._appController = applicationController;
        this.sections = new winjs.Binding.List(data).dataSource;
        this.processAll();
    },
        {
            sections: null,
            templateRenderer: function (itemPromise) {
                return itemPromise.then(function (item) {
                    // Select either normal product template or on sale template
                    var itemTemplate;
                    if (item.data.id == 1) {
                        itemTemplate = document.getElementsByClassName("productTemplate1")[0];
                    } else {
                        itemTemplate = document.getElementsByClassName("productTemplate2")[0];
                    }

                    // Render selected template to DIV container
                    var container = document.createElement("div");
                    itemTemplate.winControl.render(item.data, container);
                    return container;
                })
            },
            itemInvoked: function (e) {
                var self = this;
                e.detail.itemPromise.then(function (item) {
                    var selectedItem = item.data;
                    self._appController.selectedHomeSection = selectedItem.id;
                    //Navigates to detail page
                   mvvmStack.Navigation.navigate(target.section)
                });
            }
        });


    winjs.Namespace.define("Demo.ViewModels", {
        HomeViewModel: HomeViewModel
    });

})(WinJS, MvvmStack, Demo.Navigation.target)

As you see, it is a class inheriting from ViewModelBase that receives some external dependencies like other MvvmStack references, target urls object and, obviously, WinJS namespace.

Inside constructor we create the sections that are going to appear in home page using static data (in real world they might come from an injected external service), in this case we have section 1 and section 2, each one has its own characteristics, also note that at the end we invoke base class function processAll that marks all function exposed by the class “safe for databinding” and ensures that ‘this’ inside any instance functions safely points to class instance (if this sounds weird to you read here) please note that, at the moment, processAll doesn’t handle functions exposed by class within nested objects.

Then we have instance properties:

sections: The sections we’re going to bind to homepage listview.

templateRenderer: Since we want each section to appear differently, we created a couple of listview templates and render them through this function depending on item’s Id value.

invoked: Is the function that gets invoked when user taps a listview item, as you see, we store section id value into shared applicationcontroller object then we use mvvmstack navigation infrastructure to navigate to section page, this will create sectionViewModel first, then navigates to section.html page.

How do we pair this viewModel to homepage view?

(function (winjs,viewModels) {
    "use strict";

    WinJS.UI.Pages.define("/pages/home/home.html", {
        // This function is called whenever a user navigates to this page. It
        // populates the page elements with the app's data.
        ready: function (element, options) {
            winjs.Binding.processAll(element, viewModels.homeViewModel);
        }
    });
})(WinJS,Demo.ViewModelLocator.viewModels);

The code is quite simple, it just uses WinJS.Binding.ProcessAll to set homeViewModel as datacontext for current view, nothing more, nothing less.

Mapping viewmodel to View elements, databinding to the rescue!

Connection of HomeViewModel properties to view elements is done exclusively via databinding, as any other MVVM implementation, here’s a homepage.html fragment:

<div class="fragment homepage">
        <header aria-label="Header content" role="banner">
            <button class="win-backbutton" aria-label="Back" disabled type="button"></button>
            <h1 class="titlearea win-type-ellipsis">
                <span class="pagetitle">MVVMStack demo...</span>
            </h1>
        </header>

        <div data-win-control="WinJS.UI.ListView"
            class="homeListView"
            data-win-bind="winControl.itemDataSource:sections; winControl.itemTemplate:templateRenderer; winControl.oniteminvoked:itemInvoked"
            data-win-options="
        {
            layout: {type: WinJS.UI.GridLayout},
            tapBehavior: 'directSelect',
            selectionMode: 'none'
        }">
        </div>
    </div>

please note the use of winControl property to bind listview control’s property with viewmodel’s.

ViewModel class naming convention

In order to let the infrastructure know what are the viewmodels to persist when a suspend event occurs, viewmodel class name must be [pageName]+”ViewModel”, so if you add an “about.html” page, associated viewmodel class must be named “aboutViewModel”.

ViewModel Persistence

homeViewModel is made of static data so it is not necessary to persist it when a suspension event occurs, let’s see instead what happens inside sectionViewModel.js using following snippet:

{
        sectionTitle: null,
        images: null,
        currentPage: null,
        id: 0,
        load: function () {
            var self = this;
            this._imageService.load(self.id).then(function (photos) {
                photos.forEach(function (photoInfo) {
                    self.images.push(photoInfo);
                });
            });
        },
        first: function () {
            this.currentPage.value = 0;
        },
        last: function () {
            this.currentPage.value = this.images.length - 1;
        },
        serialize: function () {
            return {
                currentPage: this.currentPage.value
            };
        },
        hydrate: function (bag) {
            this.currentPage.value = bag.sectionViewModel.currentPage;
        }
    }

In this case the ViewModel exposes two functions: serialize and hydrate, former is invoked by persistenceService when it needs to save viewmodel’s status, latter when it is time to rehydrated it using saved informations. If your viewmodel requires state persistance just implement both functions, persistenceService.js will take care of the rest.

Closing

Once you have setup all infrastructure, here are the step required to add new page to a project:

  • 1-  Add a new pagecontrol to the project
  • 2- Add a new viemodel class named “pagenameViewModel
  • 3- Add a new property “pagenameViewModel” to ViewModelLocator’s  viewModels object
  • 4- Add a new entry to navigationTargets.js
  • 5- Add a new switch entry into ViewModelLocator’s createViewModelForUrl function.
  • 6- Modify page code behind to set ViewModel instance as page datacontext

[note] Step 3 no longer required, see here.

MvvmStack for WinJS Part #3

In this 3rd episode of the MvvmStack saga I’m going to describe how to use the set of core mvvm modules we saw in previous posts describing application dependent modules.

image

Let’s start describing navigationTargets.js

(function (winjs) {
    "use strict";

    winjs.Namespace.define("Demo.Navigation", {
        target: {
            home: "/pages/home/home.html",
            section: "/pages/section/section.html",
            noConnectivity: "/pages/noconnectivity/noconnectivity.html"
        }
    });
    
}(WinJS))

It’s a simple object, nested into Demo.Navigation namespace (use your own namespace in production code) that exposes a set of uri pointing to application pages, this allows us to centralize pages uri and pass these infos to various modules. As soon as you add new pages this object must be updated with new properties.

applicationController.js represents an optional application object shared among viewmodels, it can be used as a general data cache and it’s also persisted during suspend/resume events.

(function (winjs,mvvmStack) {
    "use strict";

    var ApplicationController = WinJS.Class.derive(mvvmStack.ApplicationControllerBase,null,
        {
            selectedHomeSection: 0,
            serialize: function () {
                return {
                    selectedHomeSection: this.selectedHomeSection
                };
            },
            hydrate: function (applicationState) {
                this.selectedHomeSection = applicationState.selectedHomeSection;
            }
        });

    var applicationController = new ApplicationController;

    winjs.Namespace.define("Demo.Application", {
        ApplicationController: applicationController
    });

})(WinJS,MvvmStack)

As you see in previous code, the object inherits from ApplicatioControllerBase class and exposes a selectedHomeSection that is used by homepageViewModel to inform sectionViewModel about what section has been selected by the user.

serialize and hydrate are functions invoked by persistence service when object must be persisted and lately rehydrated.

ApplicationController class is nested inside Demo.Application namespace.

networkService.js

While not mandatory, it is a service that monitors network connection status and using messenger object it posts messages when network connectivity status changes. The message is subscribed and handled inside connectivityService.js module

(function (winjs, messenger) {

    var _networkInfo = Windows.Networking.Connectivity.NetworkInformation;
    _networkInfo.addEventListener("networkstatuschanged", onNetworkStatusChange);
    var notifiedStatus = isInternetAvailable();

    //Handles network status changes
    function onNetworkStatusChange() {
        var mes = messenger.networkStatusChanged();
        mes.isInternetAvailable = isInternetAvailable();
        if (mes.isInternetAvailable != notifiedStatus) {
            notifiedStatus = mes.isInternetAvailable;
            messenger.send(mes);
        }
    }

    //Gets a value indicating whether internet connection is available
    function isInternetAvailable() {
        var connectivityLevel = Windows.Networking.Connectivity.NetworkConnectivityLevel.none;
        var profile = _networkInfo.getInternetConnectionProfile();
        if (profile != null) connectivityLevel = _networkInfo.getInternetConnectionProfile().getNetworkConnectivityLevel();
        return connectivityLevel === Windows.Networking.Connectivity.NetworkConnectivityLevel.internetAccess;
    }

    winjs.Namespace.define("Demo.Application.Services.Network", {
        isInternetAvailable: isInternetAvailable
    });

})(WinJS, Demo.Application.Messenger)

connectivityService.js is a completely optional component that in the demo application handles connectivity changes messages navigating to a static noConnectivity.html pagecontrol. Your application can freely ignore this module and handle connectivity changes in a total different way, all you need to do is to subscribe the message as connectivityService does.

viewModelLocator.js takes care of creating the viewModels associated with application pages, it’s a class that derives from viewModelLocator base and overrides createViewModelForUrl function.

createViewModelForUrl is the core function that take care of creating a viewModel before page gets loaded, depending on target url.

 createViewModelForUrl: function (uri) {
                switch (uri) {
                    case target.home:
                        this.viewModels.homeViewModel = this.viewModels.homeViewModel || new Demo.ViewModels.HomeViewModel(applicationController);
                        break;
                    case target.section:
                        this.viewModels.sectionViewModel = new Demo.ViewModels.SectionViewModel(applicationController, services.imageService);
                        this.viewModels.sectionViewModel.load();
                        break;
                }
            },

The snippet demonstrates how a single instance viewModel is creates for home page, while when user navigates to section page, a SectionViewModel instance is instantiated and related images loaded.

Since each viewModel becomes a property of viewModels object, when a new ViewModel is added the object must be updated adding a property that matches ViewModel name.

this.viewModels = {
            homeViewModel: null,
            sectionViewModel: null
        };

Note: I’m sure code can be refactored to avoid this step, maybe in a future release… Smile

The code also includes a createDesignTimeViewModels function, I’ll describe it in a forthcoming post regarding Blendability.

Closing

In next post we’ll analyze pages ViewModels, how to create and pair them with related View.

MvvmStack for WinJS Part #2

Following part 1, let’s now see how the code is structured:

image

Inside mvvm folder there are all the files that provides core functionality, this means that you can reuse this files in different apps without modification.

Inside pages folder there are, as usual, the PageControls representing application pages, as you see in this case there’s a new actor: the associated viewmodel (e.g homeViewModel.js)

Infrastructure bootstrapping

The demo is based around HTML Navigation Application template, if you need to create a new app, just select it and let Visual Studio 2012 create all required files for you, then delete navigator.js file since it is already included inside mvvm folder in a slightly modified version.

Dependencies

Looking at the code you’ll see that I like to explicitly indicate what are each file dependencies passing them to module self-invoking function, that implies that modules must be loaded using a prefixed sequence otherwise dependency would become unresolved.
The sequence is available inside default.html file that represents application master page:

<head>
    <meta charset="utf-8" />
    <title>MvvmStack</title>

    <!-- WinJS references -->
    <link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" />
    <script src="//Microsoft.WinJS.1.0/js/base.js"></script>
    <script src="//Microsoft.WinJS.1.0/js/ui.js"></script>


    <link href="default.css" rel="stylesheet" />
    
    <!--MVVM-->
    <script src="../../js/mvvm/applicationControllerBase.js"></script>
    <script src="../../js/mvvm/viewModelLocatorBase.js"></script>
    <script src="../../js/mvvm/viewModelBase.js"></script>
    <script src="../../js/mvvm/binding-extensions.js"></script>
    <script src="../../js/mvvm/messenger.js"></script>
    <script src="../../js/mvvm/navigator.js"></script>

    <script src="default.js"></script>
    <script src="../../js/applicationController.js"></script>
    <script src="../../js/navigationTargets.js"></script>
    <script src="../../converters/converters.js"></script>

    <!--core services-->   
    <script src="../../js/networkService.js"></script>

    <!--data services-->
    <script src="../../js/imageService.js"></script>

    <!--Viewmodels-->
    <script src="../home/homeViewModel.js"></script>
    <script src="../section/sectionViewModel.js"></script>

    <!--services-->
    <script src="../../js/ViewModelLocator.js"></script>
    <script src="../../js/mvvm/persistenceService.js"></script>
    <script src="../../js/mvvm/navigationService.js"></script>

</head>

As evident mvvm core modules are loaded first, then modules that depends/inherits from core modules then other optional core services like networkService (a service that monitors network connection status) followed by page viewmodels and ending with modules that require all modules accessibility like ViewModelLocator, PersistenceService and NavigationService.

Core Mvvm modules

Let’s now see what are the core mvvm modules:

  • ApplicationControllerBase.js

  • Is the base class for ApplicationController, an object that can be shared among ViewModels that I use as a quick way to pass informations among them, it’s state is normally persisted when app gets suspended. Obvisouly it is an optional part but demo shows how you can use it to share parameters from home page to section page.

  • binding-extensions.js

  • This is a general binding helper module an not tied to Mvvm, it contains helper functions that add two-way binding, two-way binding triggered by an event and a event to method invoker. If you want to extend WinJS binding this file would help you.

  • messenger.js

  • This represents a generic message broker allowing you to send messages among loaded modules, app uses it to navigate to a “no connectivity” page when connection drops. (try it running the app then activating flight mode) It includes a couple of predefined messages: networkStatusChanged and navigatedBack.

  • navigationservice.js

  • This is the modules that handles page navigation, it uses WinJS navigation infratructures but it takes care of instantiating the page viewmodels when required.

  • navigator.js

  • This is the same navigator objects that you get when you choose a WinJS navigation template as starting Javascript template in Visual Studio 2012, it has been slightly modified to send a navigatedBack message when uses navigates back from a page, the message instruct the infrastructure that associated viewmodel should not be persisted in case of suspension.

  • persistenceService.js

  • This is the service that, when a suspension request occurs, serializes applicationController and all viewModels implementing serialize method. It also re-instantiate viewmodels and rehydrates them when application resumes.

  • viewModelBase.js

  • Base class for all viewmodels, it includes a processAll function that marks all viewmodel’s function as ‘safe for processing’ and set ‘this’ context to viewmodel instance.

  • viewModelLocatorBase.js

  • Base class for ViewModelLocator, a class that takes care of creating/deleting page viewModels.

Closing

That’s all for now, on next episode we’ll see what you need to customize to use the stack in your app.

MvvmStack for WinJS Part #1

At recent Community Days 2013 conference i had a talk about WinJS development where, at the end, i introduced a demo about MVVM development in HTML 5/Windows Store app, since i found near to zero documentation about this, i decided to share some personal experience.

I’m not going to explain what MVVM (Model-View-ViewModel) is, there is a lot of documentation in Internet, if you need a starting point have a look Laurent Bugnion’s article here, but, as seasoned XAML developer, i admit that I can no longer create production apps without it.

In this first post I’m going to describe what you get when you download the code from http://mvvmstack.codeplex.com.

Running the sample from Visual Studio 2012 open this starting page:

image

This is just a basic page that lets you navigate to anoter section passing a param depending on which choice you select, in both cases you land to a page where you can ‘flip’ some images

image

image

This section also includes an application bar with a couple of buttons that let you to select first and last image on set (not really helpful indeed, but it shows how to bind app bar commands to page ViewModel)

Demo also includes suspend and resume functionality, in any moment you can use Visual Studio 2012 Suspend command to trigger app Termination and Resume it to the exact point it was left.

image

Another interesting aspect is that it supports Expression Blend interactive mode: just open the default.html page in Expression Blend and click Turn on Interactive Mode to start interacting with the app.

image

navigate to the page you wish to edit, press the button again to exit interactive mode and start editing the live DOM.

image

Since navigating to a page from the start might be a cumbersome in some cases, the demo lets you generate some design time data and edit a page without navigation.

image

In previous screenshot you see section.html opened in Expression Blend with some dummy data.

Closing

Get the code from http://mvvmstack.codeplex.com and start playing with it, while far from complete and without presuming to be the best MVVM implementation, i hope you’ll find interesting hints for your next HTML5 Windows Store Application.

I’ll dig into more detail in coming posts…

 

The code is provided “as is”, without warranty of any kind, feedbacks are welcome!