Wednesday, November 27, 2013

MVVM – Windows 8 Store App using HTML5/WinJS Primer

MVVM – Windows 8 Store App using HTML5/WinJS Primer
 
Purpose: The purpose of this document is to illustrate how to how to apply MVVM (Model-View-ViewModel) architectural pattern when developing Windows 8 Store Product catalog App using HTML5/WinJS
 
Challenge: You may need to develop a modern application integrated with Microsoft Dynamics AX 2012 for the purposes of demonstration, POC or to be deployed in production environment. The question is what technology and architectural pattern to use in order to facilitate application development and maintenance efforts  
 
Solution: In this scenario we'll develop Windows 8 Store App using HMTL5/WinJS
 
Walkthrough
 
First off let's create a new project using Other Languages > JavaScript > Windows Store > Blank App template
 
New Project
 
 
Then we'll apply MVVM (Model-View-ViewModel) architectural pattern for development of Product catalog app
 
Solution Explorer
 
 
Please note that Windows provides two sets of APIs for building Windows Store apps: the Windows Runtime and the Windows Library for JavaScript. Windows Runtime JavaScript, C#, Visual Basic, and C++ APIs provide access to all core platform features. WinJS JavaScript APIs provide controls, CSS styles, and helper functions that help you write object-oriented code. The WinJS namespace covers functionality that is similar to the Windows.UI.XAML namespaces in the Windows Runtime.
 
By other words WinJS is essentially JavaScript library developed by Microsoft which greatly facilitates your efforts in building authentic Windows 8 apps
 
Now let's review how I implemented Model, View and ViewModel
 
The model encapsulates business logic and data. Please see below how I define Product class (define) which has 2 attributes: ID and Name as a part of the model. For this purpose I introduce WinJS Namespace "Products" and declare Product class. Please find more info about WinJS Namespaces here: http://msdn.microsoft.com/en-us/library/windows/apps/hh967793.aspx
 
The view model encapsulates presentation logic and state. Please see below how I introduce another WinJS Namespace "ProductsViewModel", declare products variable and assign the list of products to it
 
Model and ViewModel: WinJS
 
// For an introduction to the Blank template, see the following documentation:
// http://go.microsoft.com/fwlink/?LinkId=232509
(function () {
    "use strict";
 
    WinJS.Binding.optimizeBindingReferences = true;
 
    var app = WinJS.Application;
    var activation = Windows.ApplicationModel.Activation;
 
    app.onactivated = function (args) {
        if (args.detail.kind === activation.ActivationKind.launch) {
            if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                // TODO: This application has been newly launched. Initialize
                // your application here.
            } else {
                // TODO: This application has been reactivated from suspension.
                // Restore application state here.
            }
            args.setPromise(WinJS.UI.processAll());
        }
    };
 
    app.oncheckpoint = function (args) {
        // TODO: This application is about to be suspended. Save any state
        // that needs to persist across suspensions here. You might use the
        // WinJS.Application.sessionState object, which is automatically
        // saved and restored across suspension. If you need to complete an
        // asynchronous operation before your application is suspended, call
        // args.setPromise().
    };
 
    WinJS.Namespace.define("Products", {
        Product: WinJS.Class.define(function (id, name) {
            this.id = id;
            this.name = name;
        })
    });
 
    var productsList = new WinJS.Binding.List();
    productsList.push(new Products.Product("X", "AlexProductX"));
 
    WinJS.Namespace.define("ProductsViewModel", { products: productsList });
 
    app.start();
})();
 
 
Please note that Model and ViewModel definition is done using WinJS Namespaces
MVVM (Model-View-ViewModel) pattern implementation using WinJS conceptually will look similar to classic object-oriented languages such as C#.NET because we can introduce Namespaces and define necessary Classes. Please note that pure JavaScript (JS) does not have a notion of class, but it does have a notion of object
 
Now let's review a view
 
Important to mention is that in order to link view and view model by means of binding I used standard capabilities of WinJS library (data-win-bind property). Please find more info about data-win-bind property here: http://msdn.microsoft.com/en-us/library/windows/apps/hh440968.aspx
You will also notice that I'm using more WinJS properties such as data-win-control, data-win-options, etc. For example, using data-win-control property I define that <div> will behave as ListView (WinJS.UI.ListView). ListView is one of standard controls in WinJS library for Windows 8 apps. Please find more info about ListView control here: http://msdn.microsoft.com/en-us/library/windows/apps/br211837.aspx
 
The view encapsulates the UI and any UI logic (specifically binding details). Please see below how easy it is to bind appropriate view model elements with UI controls for display. All I had to do was to specify the data source using win-data-options property and then implement binding using win-data-bind property. You will also notice that I applied a template to display catalog products in a form of grid
 
View: HTML
 
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Products</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>
 
    <!-- App3 references -->
    <link href="/css/default.css" rel="stylesheet" />
    <script src="/js/default.js"></script>
</head>
<body>
    <h1>Products</h1>
    <div id="mediumListIconTextTemplate" data-win-control="WinJS.Binding.Template">
        <div style="width: 282px; height: 70px; padding: 5px; overflow: hidden; display: -ms-grid;">       
            <div style="margin: 5px; -ms-grid-column: 2">
                <h4 data-win-bind="innerText: id"></h4>
                <h6 data-win-bind="innerText: name"></h6>
            </div>
        </div>
    </div>
    <div id="basicListView" data-win-control="WinJS.UI.ListView"
        data-win-options="{itemDataSource : ProductsViewModel.products.dataSource,
        itemTemplate: select('#mediumListIconTextTemplate'),
        layout : {type: WinJS.UI.GridLayout}}">
    </div>
</body>
</html>
 
Please note that I also did one small change to CSS file to define background color (darkgrey)
 
Style: CSS (Default.css)
 
body {
    background-color: darkgrey;
}
 
@media screen and (-ms-view-state: fullscreen-landscape) {
}
 
@media screen and (-ms-view-state: filled) {
}
 
@media screen and (-ms-view-state: snapped) {
}
 
@media screen and (-ms-view-state: fullscreen-portrait) {
}
 
 
Please note that for each product I display its product ID and Name, and the style of ListView elements is pre-defined by WinJS library that's why I didn't even need to style ListView in CSS
As the result our Product catalog application will look like below
 
Result
 
 
Please review the following article to learn how to quickly connect your application to Microsoft Dynamics AX 2012 Demo VM to test out the integration: http://ax2012aifintegration.blogspot.com/2013/04/microsoft-dynamics-ax-2012-windows-8.html
 
In case you are developing a mobile application for production please review the best practice guidance on Developing Mobile apps for Microsoft Dynamics AX 2012 here: http://www.microsoft.com/en-us/download/details.aspx?id=38413
 
Summary: This document describes how to apply MVVM (Model-View-ViewModel) architectural pattern when developing Windows 8 Store Product catalog sample App using HTML5/WinJS.
 
Author: Alex Anikiev, PhD, MCP
 
Tags: MVVM, Model-View-ViewModel, Windows 8 Store App, HTML5, WinJS, JavaScript, JS, Microsoft Dynamics AX 2012.
 
Note: This document is intended for information purposes only, presented as it is with no warranties from the author. This document may be updated with more content to better outline the concepts and describe the examples.

No comments:

Post a Comment