Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια

C# and .NET Tips and Tricks

Quests in programming in .NET

Παρουσίαση με Ετικέτες

Danae White Label test 2
Danae White Label test

 

//
Slow Performance. Is it the Entity Framework or you?

A lot of times, I get claims and concerns from colleagues and partners that EF is slow and it cannot compare to writing your own SQL queries for the database directly. In this post, we will try to clarify to what extent the above statement is true.

Suppose that you have the following simple schema in your database:

Let's examine some EF queries and approaches that affect performance:

Querying the data in the Locations table

Suppose you want to get some data from the Locations table. You may use the following:

using (LocationsContext ctx = new LocationsContext())
{
	var Locations = ctx.Locations.ToList();
}

Several runs of the above query yield approximately 3600ms to retrieve 80000 records. But wait a minute. Since we want only to display those data and not process them we do not need the proxies created for monitoring those objects by EF so we can effectively disable them as follows:

using (LocationsContext ctx = new LocationsContext())
{
	ctx.Configuration.ProxyCreationEnabled = false;
	var Locations = ctx.Locations.ToList();
}

Now the new time for 80000 records is approximately 3300ms that is 300ms faster than the previous case. But wait a minute again. We probably do not need all the fields from the table, just the ones we want to display. So we switch the above to a projection, by selecting only the properties we need:

using (LocationsContext ctx = new LocationsContext())
{
	ctx.Configuration.ProxyCreationEnabled = false;
	var Locations = ctx.Locations.select(x=>new{...}).ToList();
}

Now the new time for 80000 records is approximately 1300ms that is 2000ms faster than the previous case. If this is still to slow for us, now is the time to create a stored procedure in the SQL Database and see the result.

using (LocationsContext ctx = new LocationsContext())
{
	ctx.Configuration.ProxyCreationEnabled = false;
	var Locations = ctx.spDemo().ToList();
}

Now the new time for 80000 records is approximately 700ms that is 600ms faster than the previous case.

The whole idea in the example above is about "iterative refinement". If we would monitor the process with steps it would be as follows:

  • First you prototype with just plain LINQ. It is ultra fast, you do not need to change the database in any way and you get the results you want
  • Then you disable the proxies to have some performance increase
  • As the specs settle and you know which fields you need you create the projection
  • If the result is still to slow for you then you may end up creating a stored procedure in the database and using it

In all of the above the "key point" is that the change is localized in the query itself and does not affect any code surrounding it. This means that is can be done in any part of the development process.

Posted: Τρίτη, 17 Ιουνίου 2014 11:02 πμ από iwannis | 0 σχόλια
Δημοσίευση στην κατηγορία: ,
ITProDevConnections 2013 Presentation and Material

Thank you all for coming.

The presentation (in greek) about the common/different parts of Web and Windows 8.1 Applications is available through the following:

 From Web development ro Windows 8 development and Vice-Versa(in greek).

Make sure you also check the following blog posts (in English) related to the presentation:

Data binding in Windows 8.1 Apps with Knockout

Data binding in Windows 8.1 Apps with WinJS

Windows 8 Apps with HTML and Javascript successful workflow

WinJS ListView - The most important features and how to use them

Implementing a JSON REST service with ASP.NET MVC

An introduction to creating scalable Single Page Applications with Knockoutjs and SASS

(Windows8) WinJS single page navigation and ViewModels

(Windows8) WinJS Basic Javascript Objects and the ViewModel pattern

See you all next year!!

 

Data binding in Windows 8.1 Apps with Knockout

During the implementation of a Windows 8 application and especially in the process of implementing the functionality of a single Page Control, one is faced with the question on whether to use the WinJS data-binding engine for his ViewModel or resort to a "web" solution such as Knockoutjs. This post is about data-binding using Knockoutjs (see the one for WinJS).

The page control (our view) will be as simple as possible to illustrate the most important aspects of each approach. The corresponding ViewModel to support the view in its "clean" form (without any structures added to support the binding requirements) is like that:

function VMClean() {
        this.listOfValues = [{ text: '-' }, ...];
        this.textValue = "-";
        this.inputValue = "-";
        this.buttonInvoked = function () {
            for (var i = 0; i < this.listOfValues.length; i++)
                this.listOfValuesIdea.text = (Math.random() * 100).toFixed(2);

            this.textValue = (Math.random() * 100).toFixed(2);
        };
        this.itemInvoked = function (item) {
            var md = new Windows.UI.Popups.MessageDialog(item.text);
            md.showAsync();
        }
    };

Below is the image of the view along with pointers of the properties/methods that are bound to specific elements:

Requirement: When I add/remove items from the list I need the change to be reflected in the UI.
Solution: (WinJS) Wrap the list in a ko.observableArray method

// this.listOfValues = [{ text: '-' }, ...];
this.listOfValues = ko.observableArray([{ text: '-' }, ...]);

Binding is: <div class="listView" data-bind="foreach:listOfValues">

Requirement: I need to be able to change the properties of the elements in the list and have the change reflected in the UI.
Solution: Wrap the JSON elements in ko.mapping.fromJS

// this.listOfValues = [{ text: '-' }, ...];
// this.listOfValues = ko.observableArray([{ text: '-' }, ...]);
this.listOfValues = ko.observableArray([ko.mapping.fromJS({ text: '-' }),...]);

Binding is in the listView item template as: <span data-bind="text:text">

Requirement: I need to bind the buttonInvoked method to the click event of the button.
Solution: No changes in the initial ViewModel (see the binding):

this.buttonInvoked = function () {
	// Your code here
};

Binding is: <button data-bind="click:buttonInvoked">

Requirement: Whenever the value of the input element changes we want the data bound value to change (TwoWay binding support)
Solution: No changes in the initial ViewModel (supported out of the box)

Requirement: When a value is displayed we need to add some extra characters in the end (for example a € symbol in prices)
Solution: Expressions are supported in the binding with no extra effort.

Binding is: <div data-bind="html:(textValue()*100).toFixed(2)+' €'">

Requirement: When you change a value in code you need the change to be reflected in the UI in an ordinary object and not in a JSON object through the use of ko.mapping.
Solution: Declare the property as ko.observable

function VM() {
    ...
    //this.textValue="-";
    this._textValue =ko.observable("-");
    ...
};

Requirement: Apply the ViewModel to a given element and its children
Solution: Execute the ko.applyBindings().

WinJS.UI.Pages.define("/pages/MVVMWinJS/MVVMWinJS.html", {
    ready: function (element, options) {
        ko.applyBindings(new VM(), element.querySelector(".dataBinding"));
    },
    ...

The final code of the ViewModel is:

WinJS.Namespace.define("Converters", {
    demoConverter: WinJS.Binding.converter(function (value) {
        return value + " €";
    })
}); // Converter required to manipulate the binding value

WinJS.Namespace.define("Binding.Mode", {
    TwoWay: WinJS.Binding.initializer(function (source, sourceProps, dest, destProps) {
        WinJS.Binding.defaultBind(source, sourceProps, dest, destProps);
        dest.onchange = function () {
            var d = dest[destProps[0]];
            var s = source[sourceProps[0]];
            if (s !== d) source[sourceProps[0]] = d;
        }
    })
}); // Required to enable two way binding

function VM() {
    this.listOfValues = ko.observableArray([ko.mapping.fromJS({ text: '-' }), ...]);
    
    this.textValue = ko.observable("-");
    this.inputValue = ko.observable("-");
    this.buttonInvoked = function () {
        for (var i = 0; i < this.listOfValues().length; i++)
            this.listOfValues()Idea.text(Math.random());

        this.textValue(Math.random());
    };
    this.itemInvoked = function (item) {
        var md = new Windows.UI.Popups.MessageDialog(item.text());
        md.showAsync();
    }
};


WinJS.UI.Pages.define("/pages/MVVMWinJS/MVVMWinJS.html", {
    ready: function (element, options) {
        ko.applyBindings(new VM(), element.querySelector(".dataBinding"));
    },
    ...
});

Wow. From 14 lines of code we went to 16 lines. But do have we lost something?

ListView considerations

The new listView in knockoutjs is created with the foreach binding and although usable does not reflect the UI characteristics of the WinJS.UI.ListView. Therefore we need to find a way to support the ListView and binding in its items with knockoutjs. To achieve that we take advantage of the fact that we can provide the item template to the listview from a function. The trick is to apply the ko.applyBindings command prior to delivering the template.

The change is as follows: Initially the template is defined in HTML as follows: <div class="listView" data-win-control="WinJS.UI.ListView" data-win-options="{ itemTemplate: select('.template')...>. This will be done in code through the function:

WinJS.UI.Pages.define("/pages/MVVMWinJS/MVVMWinJS.html", {
    ready: function (element, options) {
    	element.querySelector(".listView").winControl.itemTemplate = function (itemPromise) {
		    return itemPromise.then(function (item) {
		        var itemTemplate = document.querySelector('.template');
		        var container = document.createElement("div");
		        itemTemplate.winControl.render(item.data, container).then(function () {
		            ko.applyBindings(item.data, container); // THIS LINE DOES THE MAGIC
		        });;
		        return container;
		    });
		};

        ko.applyBindings(new VM(), element.querySelector(".dataBinding"));
    },
    ...

In the case that you want to provide declarative databinding the the ListView's itemDataSource you need to create a new binding attribute as follows and then use is as you do with the other attributes (text:,html:...) - that is itemDataSource:ListOfValues.dataSource :

ko.bindingHandlers.itemDataSource = {
    init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {        
    },
    update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
        element.winControl.itemDataSource = valueAccessor();
    }
};

If you want to see the exact same example with pure WinJS binding click here

Posted: Σάββατο, 7 Δεκεμβρίου 2013 3:32 μμ από iwannis | 2 σχόλια
Δημοσίευση στην κατηγορία: , ,
Data binding in Windows 8.1 Apps with WinJS

During the implementation of a Windows 8 application and especially in the process of implementing the functionality of a single Page Control, one is faced with the question on whether to use the WinJS data-binding engine for his ViewModel or resort to a "web" solution such as Knockoutjs. This post is about data-binding using WinJS (see the one for knockout).

The page control (our view) will be as simple as possible to illustrate the most important aspects of each approach. The corresponding ViewModel to support the view in its "clean" form (without any structures added to support the binding requirements) is like that:

function VMClean() {
        this.listOfValues = [{ text: '-' }, ...];
        this.textValue = "-";
        this.inputValue = "-";
        this.buttonInvoked = function () {
            for (var i = 0; i < this.listOfValues.length; i++)
                this.listOfValuesIdea.text = (Math.random() * 100).toFixed(2);

            this.textValue = (Math.random() * 100).toFixed(2);
        };
        this.itemInvoked = function (item) {
            var md = new Windows.UI.Popups.MessageDialog(item.text);
            md.showAsync();
        }
    };

Below is the image of the view along with pointers of the properties/methods that are bound to specific elements:

Requirement: When I add/remove items from the list I need the change to be reflected in the UI.
Solution: (WinJS) Wrap the list in a WinJS.Binding.List object

// this.listOfValues = [{ text: '-' }, ...];
this.listOfValues = new WinJS.Binding.List([{ text: '-' }, ...]);

Binding is: <div class="listView" data-win-control="..." data-win-bind="winControl.itemDataSource:listOfValues.dataSource">

Requirement: I need to be able to change the properties of the elements in the list and have the change reflected in the UI.
Solution: Wrap the JSON elements in WinJS.Binding.as

// this.listOfValues = [{ text: '-' }, ...];
// this.listOfValues = new WinJS.Binding.List([{ text: '-' }, ...]);
this.listOfValues = new WinJS.Binding.List([WinJS.Binding.as({ text: '-' }),...]);

Binding is in the listView item template as: <span data-win-bind="textContent:text">

Requirement: I need to bind the buttonInvoked method to the click event of the button.
Solution: Wrap the function in WinJS.Utilities.markSupportedForProcessing and change the context to this (the same applies to any function that you need to bind such as the itemInvoked method to the winControl.oniteminvoked event of the listview):

//this.buttonInvoked = function () {
	// Your code here
//};
this.buttonInvoked = WinJS.Utilities.markSupportedForProcessing((function () {
	// Your code here
}).bind(this));

Binding is: <button data-win-bind="onclick:buttonInvoked">

Requirement: Whenever the value of the input element changes we want the data bound value to change (TwoWay binding support)
Solution: Create a generic binding initializer and use it.

WinJS.Namespace.define("Binding.Mode", {
    TwoWay: WinJS.Binding.initializer(function (source, sourceProps, dest, destProps) {
        WinJS.Binding.defaultBind(source, sourceProps, dest, destProps);
        dest.onchange = function () {
            var d = dest[destProps[0]];
            var s = source[sourceProps[0]];
            if (s !== d) source[sourceProps[0]] = d;
        }
    })
});

Binding is: <input type="text" data-win-bind="value:inputValue Binding.Mode.TwoWay">

Requirement: When a value is displayed we need to add some extra characters in the end (for example a € symbol in prices)
Solution: You cannot use expression directly in data-win-bind and therefore you have to declare a binding converter and use it

WinJS.Namespace.define("Converters", {
    demoConverter: WinJS.Binding.converter(function (value) {
        return value + " €";
    })
});

Binding is: <div data-win-bind="innerHTML:textValue Converters.demoConverter">

Requirement: When you change a value in code you need the change to be reflected in the UI in an ordinary object and not in a JSON object through the use of WinJS.Binding.as
Solution: You need change your field in the object to property first (say you want to do this for the textValue field)

function VM() {
    ...
    //this.textValue="-";
    this._textValue = "-";
    ...
};

Then define property that has getters/setters and is enumerable and use the notify method in the setter. The notify method is provided by a mixin - see below

Object.defineProperty(VM.prototype, "textValue", {
    get: function () {
        return this._textValue;
    },
    set: function (value) {
        this._textValue = value;
        this.notify("textValue", value);  
    }, enumerable: true
});

You will not use the VM class to create your object but the VMObservable class which will be returned from the following mixin.

var VMObservable = WinJS.Class.mix(VM, WinJS.Binding.mixin);

Requirement: Apply the ViewModel to a given element and its children
Solution: Execute the WinJS.Binding.processAll() after the mixin.

WinJS.UI.Pages.define("/pages/MVVMWinJS/MVVMWinJS.html", {
    ready: function (element, options) {
        var VMObservable = WinJS.Class.mix(VM, WinJS.Binding.mixin); 
        WinJS.Binding.processAll(element.querySelector(".dataBindingRoot"), new VMObservable());
    },
    ...

The final code of the ViewModel is:

WinJS.Namespace.define("Converters", {
    demoConverter: WinJS.Binding.converter(function (value) {
        return value + " €";
    })
}); // Converter required to manipulate the binding value

WinJS.Namespace.define("Binding.Mode", {
    TwoWay: WinJS.Binding.initializer(function (source, sourceProps, dest, destProps) {
        WinJS.Binding.defaultBind(source, sourceProps, dest, destProps);
        dest.onchange = function () {
            var d = dest[destProps[0]];
            var s = source[sourceProps[0]];
            if (s !== d) source[sourceProps[0]] = d;
        }
    })
}); // Required to enable two way binding

function VM() {
    this.listOfValues = new WinJS.Binding.List([WinJS.Binding.as({ text: '-' }),...)]);
    this._textValue = "-";
    this._inputValue = "-";
    this.buttonInvoked = WinJS.Utilities.markSupportedForProcessing((function () {
        for (var i = 0; i < this.listOfValues.length;i++)
            this.listOfValues.getAt(i).text = (Math.random()*100).toFixed(2);

        this.textValue = (Math.random() * 100).toFixed(2);
    }).bind(this)); // markSupportedForProcessing required for "safe" binding

    this.itemInvoked = WinJS.Utilities.markSupportedForProcessing((function (ev) {
        var item =this.listOfValues.getAt(ev.detail.itemIndex);
        var md = new Windows.UI.Popups.MessageDialog(item.text);
        md.showAsync();
    }).bind(this)); // markSupportedForProcessing required for "safe" binding
};
Object.defineProperty(VM.prototype, "textValue", {
    get: function () {
        return this._textValue;
    },
    set: function (value) {
        this._textValue = value;
        this.notify("textValue", value);    
    }, enumerable: true
});
Object.defineProperty(VM.prototype, "inputValue", {
    get: function () {
        return this._inputValue;
    },
    set: function (value) {
        this._inputValue = value;
        this.notify("inputValue", value); 
    }, enumerable: true
});

WinJS.UI.Pages.define("/pages/MVVMWinJS/MVVMWinJS.html", {
    ready: function (element, options) {
        var BindableVM = WinJS.Class.mix(VM, WinJS.Binding.mixin);
        WinJS.Binding.processAll(element.querySelector(".dataBinding"), new BindableVM());
    },
    ...
});

Wow. From 14 lines of code we went to 52 lines. If you want to see how knockout does it go to this post

Posted: Κυριακή, 1 Δεκεμβρίου 2013 3:30 μμ από iwannis | 0 σχόλια
Δημοσίευση στην κατηγορία: , ,
Windows 8 Apps with HTML and Javascript successful workflow

It is claimed a lot that whoever knows how to develop web applications is also ready to develop Windows 8.1 applications. And this is definitely true in terms of the language used. In this post we will explore how we can set our VS2013, Expression blend IDE and use specific frameworks in order to also work as fast as we do when developing Web applications.

First of all lets describe what we want today in our web development workflow:

  • We need a way to write faster HTML by using some shorts of shortcuts that will enable us to free ourselves from all the "HTML" syntactic sugar. This is solved in VS2013 by installing the Web Essentials extension that comes equipped with "Zen Coding". "Zen Coding" will allow you to write ul>li*8, press tab and have it expanded to a fully blow unordered list with 8 list elements.
  • We need a way to keep our CSS stylesheets DRY. The CSS language is not DRY ("Do not Repeat Yourself" principle). You tend to repeat the names of the selectors when you define their full paths, you cannot declare variables or define mathematical expressions in the calculation of the sizes and so on. SASS helps a lot in this process and you can use it in VS2013 by installing the Mindscape Web Workbench plugin.
  • Automatic browser refresh is another important issue solved in VS2013 using the BrowserLink technology.
  • Javascript intellisense is also crucial in development speed and it is handled in VS2013 by using the _reference.js file with the javascript file definitions or by inserting commented-out references of js files (see the Reference Directives section).
  • Typescript or Coffescript support coming out of the box by installing the Typescript addon and the Mindscape Web Workbench or the Web Essentials extension.

So how do all those fit in the Windows8 development workflow. Can I take advantage of them?

The answer is yes provided that you follow some simple guidelines in order to make your life easier.

  • Automatic browser refresh In the Windows8 development workflow, your browser equivalent is Expression blend. You will find yourself a lot of times annoyed by having to press the "Reload" button on blend whenever you make some change in an html-css file in VS2013. To avoid this and have this "automatic refresh" experience you need to go to Tools/Options/Project in Blend and enable the "Always reload files modified outside of Blend" option.
  • We need a way to keep our CSS stylesheets DRY You want to use SASS but you usually perform all your CSS changes in Blend. Having enabled automatic reloads in the previous step you do not need to use Blend for editing your CSS files anymore. So having installed the Mindscape Web Workbench extension and using VS2013 to code in SASS, whenever you save, your css is created automatically and Blend is also automatically refreshed to reflect your changes.
  • We need a way to write faster HTML. Zen coding works like a charm in Windows8 development (Web Essentials plugin) and therefore VS2013 is the "natural" place to write HTML for your Windows8 project. The only problem here is when Blend refreshes due to a change in an HTML file it looses its current state( meaning that if you used it to navigate to a specific part of you app and then started working in that state this state will be lost). Therefore the recommendation here is to use VS2013 for your "heavy-duty" HTML creation and then use Blend to perform smaller changes in the html file since changing those files in blend preserves the application's state.
  • Javascript intellisense Unfortunately a _reference.js file cannot be used in Windows8. But there are other things you can do. First use IDs for your HTML elements that will become winControls. By doing so you get out of the box full intellisense support for those controls in the js files and you do not need to use querySelector to select them. That is document.querySelector("#demoControl").winControl now becomes demoControl.winControl with intellisense after the dot targeted to the specific control. You can also use commented-out references of js files (see the Reference Directives section) and also keep in mind that js files declared in the same HTML file share intellisense suggestions to each other.
  • Typescript or Coffescript support coming out of the box by installing the Typescript addon and the Mindscape Web Workbench or the Web Essentials extension. Especially for TypeScript after you install the addon make sure to go to Tools/Options/Text Editor/TypeScript/Project an check the "Automatically compile Typescript files which are part of the project" option. Additionally, if you want intellisense support in Typescript for libraries that are not written in Typescript such as (WinJS, JQuery etx) you can download the .d.ts files from nuget, include them in your projects and then reference them using the above Javascript intellisense techniques.
Posted: Σάββατο, 30 Νοεμβρίου 2013 11:17 πμ από iwannis | 3 σχόλια
Δημοσίευση στην κατηγορία: , ,
Be careful of compile time code changes

In my top ten list of difficult bugs I had to solve in C# in my professionali carreer reside two that both had to do with compile time code changes that I was not aware of. In this post I will describe both of them in detail in the hope that it will help someone out there searching for a solution to his own issue.

Difference between properties with public accessors and public fields.

What is the difference between declaring a property with public default accessors:

public string demo {get;set;}

Compared to declaring the same variable as a field?

public string demo;

It seems that there is none and we can use any one of the two with not much difference. Actually, one may argue that the usage of a "field" may be a littler faster since it does not lead to the generation of a method call as the usage of a "property" does. In other words if we are to disassemble the generated code (using ildasm) you will see that the "field" declaration produces just a field (Class2) while the "property" variable results in a field and two methods (Class1) :

While the "property" declaration results in a method call

Now consider the following case. Say you have in a solution two projects. A "class library" project for your application's logic and a "console application" project which is the executable of your application. Now, let's suppose that the variable in question (named demo) resides in a class (DemoClass) in the "class library" project.The "demo" variable is used in the "console application".

We initially declare our "demo" variable as a field and we deploy the .dll and .exe files. Everything works fine.

Now a requirement comes that leads us to change the "demo" variable in the .dll from a "field" to a "property" since we need to implement some logic in its accessors (get and set). So we perform the change, test the project in Visual Studio and verify that it works and since we have not made any changes in the "console application" we just redeploy the .dll and not the .exe file. We will soon realize that the application will stop working. So while we test it in VS it works and when we deploy the .dll it does not.

The reason behind this lies in the fact that initially when the demo variable was implemented as a field, the code that was using the field demo in the "console application" was created as follows (note the stfld assembly command that you can interpret as "store in field"):

If the variable was implemented as a property then the code would be different for the same action (callvirt actually means call the function set_demo:

So changing the field to a property and deploying just the .dll will not change the code in the user of the field/property and most definitely lead to a difficult to locate That is the reason why public default accessors exist and why you should most definitely use them.

Creating a method with default arguments

Say now that you have a method in your .dll that you use in another project (.dll or whatever) numerous times in various places. Let's suppose that this method is as follows:

public void Add(int op1,int op2){
	// Your logic here
}

You compile the project and deploy the .dll and the other .dll,.exe or whatever modules in the client.

A requirement comes that leads you to need to add another argument in the "Add" method. Since there are many place where this method is used in most frequently this extra argument will not be needed in those cases you resort to an argument with a default value, that is (the argument "extra" with the default value of 0):

public void Add(int op1,int op2,int extra=0){
	// Your logic here
}

And you redeploy the whole project. Everything works well. Now an extra requirement comes that leads you to conclude that the default value of extra should not be 0 but 1. So you change the default value and since you have not made any other change you just deploy that single .dll. You will soon realize that the default value has not changed even if you verify that you did it in your code.

The reason behind this is the fact that during "compilation" the default values of arguments are injected to the callers. Therefore if the caller is in another dll, you change the default value of the argument and just deploy the method's dll, the code of the caller will not change and therefore will still be carrying the old value! Beware that this is an even worse bug since it does not lead to a program crash rather to an unwanted and possibly unnoticed behavior. The screenshot below proves that the default value is injected to the caller (this code is taken from the caller's dll where you see that the ldc.i4.0 caused by the default value of the argument has been injected here).

So in this case the moral of the story is to never use default values in your method's arguments or if you do be extremely careful with such scenarios.

WinJS ListView - The most important features an how to use them

The WinJS.UI.ListView control is one of the most important in Window Store Applications. It is the basis of the application's UI and the one most familiar to users. In this post will explore the features/tweaks available for the control that are most needed to the developer when used. This post can serve as a cheatsheet to anyone wishing to use the WinJS.UI.ListView control in his applications.

Adding a ListView, its Data Template, its Data Items and styling it

In the part of the page you want the list to be displayed just add a div element with the data-win-control attribute set to WinJS.UI.ListView.

<div id="demolistview" data-win-control="WinJS.UI.ListView"></div>

The ListView by default will have a height of 400px and a width of 100%. Next, we need to add a data template for the list elements. This is done by creating a div element and setting its data-win-control attribute to WinJS.Binding.Template. Then we can use the data-win-bind attribute to bind to specific properties of the elements in the data list used for the ListView. One representative example of a data template is the following:

<div id="dataTemple" data-win-control="WinJS.Binding.Template">
    <div class="dataTemplateContainer">
        <div class="title" data-win-bind="textContent:title;style.backgroundColor:backColor"></div>
        <img src="#" class="image" data-win-bind="src:image" />
    </div>
</div>

We also need some demo data list that will hydrate the ListView. We can use a javascript Array for this purpose but it is better to create a WinJS.Binding.List for our data. This kind of list provides notifications to the ListView control toget automatically updated when items are inserted/removed. Below is an example of such a list with demo data for our purpose. Note that the properties of the elements of the list match the names that are used in the "data-win-bind" attributes of the elements in the data template.

var dataBindingList = new WinJS.Binding.List();
for (var i = 0; i < 100; i++) {
    dataBindingList.push({ 
    	title: 'Item ' + i.toString(), 
    	image: '/images/demo.jpg', 
    	backColor: 'rgba(255,0,0,0.5)' 
    });
}

Next we need to bind the data template and the data list with the ListView. This is done using the code below:

var listViewControl = document.querySelector("#demolistview").winControl;
listViewControl.itemDataSource = dataBindingList.dataSource;
listViewControl.itemTemplate = document.querySelector("#dataTemple");

That is we get the ListView object (listViewControl) and then associate the data list (dataBindingList) and the data template. There is a last think necessary to specify which is the default size of each element in the list. This is set for the div element of the list item with class name "win-item". This element gets generated for you by the framework. So for our example this should be elements of 100x100 pixels size:

#demolistview .win-item{
	width:100px;
	height:100px;
}

One thing to keep in mind is that when styling the list elements you should not be using the id of the element defined as the template (in our case #dataTemplate) since this will not work. Insted use an element within the template (and this is the reasong why in our case we define the element with the dataTemplateContainer class name). For example, here is a possible styling for the example's template:

.dataTemplateContainer {
	display:-ms-grid;
	height:100%;
	-ms-grid-columns:1fr;
	-ms-grid-rows:50px 1fr;
}
.dataTemplateContainer .title {
	-ms-grid-row:1;
}
.dataTemplateContainer .image {
	-ms-grid-row-span:2;
}

Populating the ListView with data from a service

In this case you create the ListView as stated above and also the dataList as before but you do not fill it with data. You can then perform an asynchronous request (WinJS.xhr) to get some data from a web service and once you get them you push the items to the data list as follows (the following example uses the Web API )

WinJS.xhr({ url: 'SERVICE URL' }).then(function (data) {
    var responseJSON = JSON.parse(data.response);
    var items = responseJSON.results;
    for (var i = 0; i < items.length; i++)
        dataBindingList.push({
            title: itemsIdea.aliases,
            image: itemsIdea.image ? itemsIdea.image.medium_url : '/images/listview/noImage.png',
            backColor: 'rgba(255,255,255,0.5)'
        });
});

Note that the respose is contained in data.response and you need to convert it to a JSON object using JSON.parse. You then cycle through the results an map them one to one to the elements of the list. Since the list is of WinJS.Binding.List type the moment you push the items, they appear to the UI.

Changing the layout

The default list layout is grid layout. This means that items will first occupy all their container height and then, they will start expanding to the right. You can also set the layout to list layout which will expand your items top to bottom like an ordinary list making them occupy all the available horizontal space. The layout is chosen by setting the listViewControl.layout property to either "new WinJS.UI.GridLayout()" or "new WinJS.UI.ListLayout()".

Creating a grouped view

One of the features of the ListView is its ability to group its items and display them to the user as groups with a title. For this to work each item in the list needs to carry a property that will serve as the group definition for the item. Say for example that you have 3 groups with the following data:

var groups = [
    {id:1,title:'Group 1'},
    {id:2,title:'Group 2'},
    {id:3,title: 'Group 3' }
];

Each item in the list has a group property that points to one of those groups. Next, you execute the following, which creates your grouped datasource:

dataBindingList = dataBindingList.createGrouped(function getKey(item) {
    return item.group.id;
}, function getGroup(item) {
    return item.group;
}, function sortGroup(groupKey1,groupKey2) {
    if (groupKey1 > groupKey2) return 1;
    return -1;
});

Which means that you change your initial WinJS.Binding.List with the createGrouped method to which you supply three functions. One that returns the group key for each item, one that returns the group object for each item and one that helps in the sorting of the groups. The last needs you to return for each two group key combinations a,b, 1 if a>b and -1 if a<b.

The last step is associating the new datasource with the ListView as follows:

listViewControl.itemDataSource = dataBindingList.dataSource;
listViewControl.groupDataSource = dataBindingList.groups.dataSource;

If you do all this and execute the app you will notice that the list items are getting grouped but the group title displays the group object itself serialized as a JSON string. This is due to the fact that your ListView does not have a template to use in order to diplay the group. So you need to define one, for example:

<div id="groupTemplate" data-win-control="WinJS.Binding.Template">
    <div class="groupTemplateContainer">
		<div class="title" data-win-bind="textContent:title"></div>
    </div>
</div>

To be able to use this template you need to declare it in javascript as follows:

 listViewControl.groupHeaderTemplate = document.querySelector("#groupTemplate");

List items with different sizes

So what if you want to support different dimensions for your tiles? Say for each group you have one "featured" element which you want to reside in a bigger tile. With the ListView this is possible provided that the two different sized tiles are both divisible with the same "minimum" grid size that you define. In mathematical terms the two (or more sizes) should have the same GCD for each one of their dimensions which will be used as the "minimum" grid size (you also need to consider the margin as you will see in the following example).

Let's say we want to support an 130x130 dimension for the items and a dimension around 390x390 for the featured item. Then the "GCD" for both dimensions is 130x130 but since we also have a 10 pixels margin between tiles in both directions the small tile should be 130 by 130 and the big one 390+20 by 390+20 due to the margins (3 times the small tile plus 2 times the margins between them). In javascript we need to define the GCD (130 by 130) as follows:

listViewControl.layout = new WinJS.UI.GridLayout({
    groupHeaderPosition: "top",
    groupInfo: {
        enableCellSpanning: true,
        cellWidth: 130,
        cellHeight: 130
    }
});

We also define the template for the featured item:

<div id="dataTemplateFeatured" data-win-control="WinJS.Binding.Template">
    <div class="dataTemplateContainer featured">
		<img src="#" class="image" data-win-bind="src:image" />
        <div class="title" data-win-bind="textContent:title;style.backgroundColor:backColor"></div>  
    </div>
</div>

Finally we specify a function that gives the appropriate template based on the tile's data:

listViewControl.itemTemplate = function (itemPromise) {
    return itemPromise.then(function (item) {
        var itemTemplate = getTemplateForItem(item);
        var container = document.createElement("div");
        itemTemplate.winControl.render(item.data, container).done();
        return container;
    });
}

The getTemplateForItem() function is the one deciding which template will be sent to the view. In our case it is implemented as follows:

function getTemplateForItem (item) {
        var itemData = item.data;

        if (itemData.isFeatured)
            return document.querySelector('#dataTemplateFeatured');

        return document.querySelector('#dataTemplate');;
    }

Get the item pressed

This is an easy one. You just put a callback on the oniteminvoked event. To get the element that was pressed use the index provided to you by the event.detail.index property to search in the list as follows:

listViewControl.oniteminvoked = function (event) {
    var index = event.detail.itemIndex;
    var item = dataBindingList.getAt(index);
    // ...
}

Get the group item that was pressed

This is more tricky and in my opinion it is kind of a hack. You bind to a click event on the group title element itself and you provide the argument you need to know which group was invoked. For example you specify a global method named groupHeaderInvoked which accepts as the first argument the group's key as follows:

ipplos.groupHeaderInvoked = function (key) {
    // ...
}

You then bind to the click event in the group's template. The ony thing you need is to be able to pass the key value. This is done by attaching an extra attribute to the element via data-wind-bind:

<div id="groupTemplate" data-win-control="WinJS.Binding.Template">
	<div class="groupTemplateContainer">
		<div class="title" data-win-bind="textContent:title;groupKey:id" onclick="ipplos.groupHeaderInvoked(event.srcElement.groupKey)"></div>
    </div>
</div>

Note this method which may come in handy in many other situations. In the case where your groupHeaderInvoked method is in a page cotnrol you can refer to it by the Application.navigator.pageControl property which holds the current active page control.

Posted: Σάββατο, 31 Αυγούστου 2013 7:58 πμ από iwannis | 0 σχόλια
Δημοσίευση στην κατηγορία: ,
Visual Studio 2012 tips that will improve your coding speed - Web developers

Disable "Start Page"

There is no reason to wait every time for the "Start Page" to load its contents from the internet and display. So the best thing to do is disable it using the checkbox at the left, bottom of it

Switch between/Execute programs on taskbar without the mouse

You can use the Win + Number to switch between the open programs in the taskbar. If the program is not running it will execute, otherwise it will get the focus. Win + Shift + Number will open a new instance of the progam on the taskbar. Those are extremely useful especially when you are doing web development and want to be able to switch between browser windows and VS. Finaly, the most important Win + Ctrl + Shift + Number will run the program as administrator.

Associate "Open Containing folder to a shortcut

Go to "Quick Launch" and start typing "Keyboard...". Select "Environment -> Keyboard". In the "Show command containing" write "OpenContaining" and select the match at the list below. Assign the shortcut key (eg press "Ctrl + Shift + O" and then assign).

Install useful extensions

For each one of the following go to VS2012 -> Tools -> Extensions and Updates and write their name in the "Search box".

  • Indent Guides: Provide lines to show you indentation and where blocks of code open/close.
  • Web Essentials 2012: Toolbox that provides a lot of useful features for web developemnt such as CSS3 editor enhancements and Typescript support. For more info see here.
  • Mindscape Web Workbench: Support for new web frameworks such as SASS,LESS and Coffescript . For more info see here.
  • Hide Main Menu: Save those extra pixels by hiding the menu. It can be displayed by pressing the "Alt" key.
  • Color Theme Editor: Change the VS2012 color theme.
  • TroutZoom: Automatically applies the zoom level you specify to one window to all.
  • Zen Coding: Super fast HTML writing (similar to the popular package for Sublime) more info.

Stop going up and down in the same file

You are writing code in a big file and you find yourself going up and down within the file to see some definitions and keep coding. You can select the file you work and then click "Window" -> "Split" and you have two windows open with the same file so that you can have each one in a different position within the file. When you are donw "Window" -> "Remove Split"

Useful shortcuts

  • Ctrl+Alt+L Focus to the solution explorer.
  • Ctrl + -/ Ctrl + Shift + - Backward/Forward to the places I have been with my cursor in a file with code
  • Ctrl + , Very intelligent search within the solution (it also searches camelcase like for MainWindowViewModel you can search from MWVM
  • Ctrl + >/ Ctrl + Shift + < Zoom in and out
  • Ctrl + Alt + Space Switch between suggestion and completion mode in intellisense
  • Ctrl + ] + s Selects the active file in the "Solution Explorer"

New solution explorer view

In big solutions sometimes you need to constantly navigate between two different locations in the solution explorer. Well not any more. Right click on the folder containing some code files in solution explorer and select "New Solution Explorer View". You will get a second view with only those files.

For more information check out this very good presenation from Teched 2013 Europe.

Posted: Δευτέρα, 8 Ιουλίου 2013 7:40 πμ από iwannis | 0 σχόλια
Δημοσίευση στην κατηγορία:
Implementing a JSON REST service with ASP.NET MVC

Two years ago, I have written a post about implementing a REST service using WCF. Back then, I didn't know that I was referring to services over the HTTP protocol which are not necessarily REST. Nevertheless, since it seems (from my blog analytics point of view) that people out there when they search for REST services actually imply services over the HTTP protocol or not SOAP more generally I kept the same title in this post.

The point is that you have some kind of client code in javascript and you need to implement in ASP.NET MVC a bunch of services that support getting/putting data from/to your database. In this post we will see how to take advantage of ASP.NET MVC 3 to implement such a JSON service and explore how you can pass data back and forth. I could write this post for ASP.NET MVC4 but in many ways I believe that knowning how to do that in ASP.NET MVC3 helps you understand a lot of the automations that the new MVC version has brought to the picture. Taking also advantage of the WebAPI in ASP.NET MVC4 is an option as long as you realize that the WebAPI supports and sometimes enforces some rules related to the pure "REST" protocol which are not always required.

So in this blog post, simplicity and crude direct appoach are the two motivators behind the proposed solution.

Create a new empty ASP.NET MVC 3 project (empty). Get rid of all the "Contents" folder and leave only the "jquery.min" definition in the Scripts folder (we are keeping this for testing our service)

Create a Controller named "ServicesController" for the services and a controller named "TestingController" for the tests.

Getting .NET objects as JSON (Demo1 Action)

Create and action named in both the "Services" and the "Testing" controllers. Create a view for the "Demo1" action in the "Testing" controller as follows:

    $(document).ready(function () {
        $.get('@Url.Action("Demo1","Services")', {Param1:12,Param2:'John'}, function (data) {
            console.log(data);
        });
    });				
				

In order to support this king of request the passes the parameters "Param1,Param2" to the service and has the JSON object in the "data" parameter the "Demo1" action in the "Services" controller is as follows:

public class Demo1Class
{
    public string Name { get; set; }
    public string Surname { get; set; }
    public List<int> SomeList { get; set; }
}

public JsonResult Demo1(int? Param1,string Param2)
{
    Demo1Class Obj = new Demo1Class();
    Obj.Name = Param2;
    Obj.Surname = Param2;
    Obj.SomeList = new List<int>();
    Obj.SomeList.Add(Param1.GetValueOrDefault());
    return Json(Obj, JsonRequestBehavior.AllowGet);
}
				

Note that with define the parameters as nullable so the action can run even if the client has not supplied them. Also note that there is no need to define the return class. We could just write the code below and still get the required result:

public JsonResult Demo1(int? Param1,string Param2)
{
	List<int> SomeList=new List<int>();
	SomeList.Add(Param1.GetValueOrDefault());
	return Json(new{Name=Param2,Surname=Param2,SomeList=SomeList}, JsonRequestBehavior.AllowGet);
}
				

Sending .NET objects (Demo2 Action)

Now let's say you have the following BLOCKED SCRIPT

$(document).ready(function () {
    var client = {
        name: 'John',
        surname: 'Panagopoulos',
        age: 37,
        values:[11,22,111,2,87]
    };
    $.get('@Url.Action("Demo2","Services")', { id: 11, client: client }, function (data) {
        console.log(data);
    });
});			
				

Developing the following service action (Demo2) will not work.

public class Demo2Class
{
    public string name { get; set; }
    public string surname { get; set; }
    public int age { get; set; }
    public List<int> values { get; set; }
}
public JsonResult Demo2(int? id, Demo2Class client)
{
    // Some server side logic
    return Json(new { result=true }, JsonRequestBehavior.AllowGet);
}

				

This maps the names of the parameters and the properties of the object one by one with the ones passed from the javascript. But it does not work well with the object due to a limitation in the ASP.NET MVC model binder. There are many solutions to that. For me the most straightforward is to include a small jquery extension called $.toDictionary (see also this post) in your html and wrap the parameters with this as follows:

$(document).ready(function () {
    var client = {
        name: 'John',
        surname: 'Panagopoulos',
        age: 37,
        values:[11,22,111,2,87]
    };
    $.get('@Url.Action("Demo2","Services")',$.toDictionary({ id: 11, client: client }), function (data) {
        console.log(data);
    });
});			
				

Note that this can work even if you have nested objects.

Alternatively, you can send the previous request via POST as follows (the ajax command is used in this case so you can also set the cache parameter)

$.ajax({
    url: '@Url.Action("Demo2Post","Services")',
    type: "POST",
    data: $.toDictionary({ id: 11, client: client }),
    success: function (data) {
        console.log(data);
    },
    cache: false
});
				

Your service method in this case is the same as the previous one with the only difference that you need to decorate the action with the [HttpPost] attribute.

And this is it. Now you know how to send,get results from actions that return JSON data using either GET or POST. The demo project can be downloaded here

Posted: Τετάρτη, 26 Ιουνίου 2013 10:26 πμ από iwannis | 0 σχόλια
Δημοσίευση στην κατηγορία:
An introduction to creating scalable Single Page Applications with Knockoutjs and SASS

Everyone who develops web applications (or websites in general) knows that the basic tools for creating simple "Single Page Applications" are HTML5, CSS3, JQuery and a server side framework (such as ASP.NET MVC) for serving data to AJAX requests. Although those are sufficient for implementing SPAs, they tend to lead to implementations that violate basic software design principles, leading to designs that are not easily scalable, difficult to debug and overly complicated.

In this post we will see how we can take advantage of the Knockoutjs and Syntactically Awsome StyleSheets - SASS frameworks in order to design SPAs that respect:

  • The "Single Responsibility Princile - SRP" that states that each software module should be responsible for only one thing in your code. In our case, we will implement the Model-View-View-Model pattern using the Knockoutjs framework to clearly separate the logic that drives the workings of UI from the logic that provides the data/behavior for the UI
  • The "Do not Repeat Yourself Principle - DRY" that states that there should not be any repetition in the implementation of any behavior/logic in your code (or for the fun of it, your implementation should be dry). We will see how "wet" CSS3 stylesheets are becoming and we will use the SASS Framework in order to make them as dry as possible

We will implement a simple SPA of a calculator that performs basic operations (+,-,/,*) and also has one extra operation that requests the calculation to be performed "server side" thus needing the use of an AJAX request in order to get the results.

The initial implementation

Our HTML5 will be as follows:

<div class="container">
    <div class="header">
        <div class="text">
            Demo Calculator Engine
        </div>
    </div>
    <div class="display">
        <input class="operand1 operand" type="text" value="0" />
        <div class="operator">+</div>
        <input class="operand2 operand" type="text" value="0" />
        <div class="result">0</div>
    </div>
    <div class="actions">
        <button class="addition actionButton">+</button>
        <button class="subtraction actionButton">-</button>
        <button class="division actionButton">/</button>
        <button class="multiplication actionButton">x</button>
        <button class="serverOp1 actionButton">o</button>
        <button class="equals actionButton">=</button>
    </div>
    <div class="footer">
        <div class="text">
            (c) 2013 - Ioannis Panagopoulos
        </div>
    </div>
</div>
				

We have separated the "container" div into four zones. The first has the header of the SPA, the second holds the two input boxes for the operands ("operand1","operand2"), shows the operator ("operator") and the result ("result"). The third zone has the buttons that define the operations and change the "operator" in the UI accordingly and the "=" button that performs the operation and updates the result. The last zone is the footer. The CSS3 that beautifies the HTML above is as follows (only some fragments are shown here):

.container{
    width:500px;
    height:280px;
    font-family:Helvetica, Arial, 'DejaVu Sans', 'Liberation Sans', Freesans, sans-serif;
    font-size:14px;
}
.container .header{
    height:60px;
    background-color:#cccccc;
}
.container .header .text{
    font-size:24px;
    text-align:center;
    padding-top:13px;
    color:black;
    font-weight:700;
}	
...		
.container .footer{
    border-top:1px solid #cccccc;
    padding-top:5px;
}
.container .footer .text{
    text-align:center;
}	
...
				

The logic expressed in jQuery is as follows:

$(document).ready(function () {
    $(".container").css('font-size', '30px');
    var operation = undefined;
    var operand1 = 0;
    var operand2 = 0;
    var result = 0;
    function selectOperation(op) {
        operation = op;
        $(".operator").html(operation);
    }
    $(".addition").click(       function () {selectOperation("+");});
    $(".subtraction").click(    function () { selectOperation("-"); });
    $(".division").click(       function () { selectOperation("/"); });
    $(".multiplication").click( function () { selectOperation("x"); });
    $(".serverOp1").click(      function () { selectOperation("o"); });

    $(".equals").click(function () {
        operand1 =parseFloat($(".operand1").val());
        operand2 = parseFloat($(".operand2").val());
        if (operation == "+") result = operand1 + operand2;
        if (operation == "-") result = operand1 - operand2;
        if (operation == "x") result = operand1 * operand2;
        if (operation == "/") result = operand1 / operand2;
        if (operation == "o") {
            $.get('@Url.Action("SOp1","Demo")', {operand1:operand1,operand2:operand2}, function (data) {
                result = data;
                $(".result").html(result);
            });
        }
        $(".result").html(result);
    });
});				

The problems

Is our CSS3 DRY? Not at all. First, the CSS rules repeat the class and id names again and again for each rule (see how the "container" class name is repeated again and again in the CSS). Also, if we want to have a specific property value that we want to use in many rules we have to repeat it in every rule (see the "#cccccc" color value in the CSS file of the example). Moreover, if you want to use ems instead of pixel units to make your view easily scalable, you need to have all your dimensions expressed in ems by using a calculator to convert every value expressed in pixels based on the current font size in each element. But this is obviously a nightmare since, first you are accustomed to work with pixels not ems and second because if you decide to change the font size you have to perform all the em calculations all over again! All the above statements prove that your CSS design, no matter how hard you try, will always be wet.

How about the logic expressed in javascript? Well here you have other issues. First, we will all agree that if someone reads the logic, it is not obvious right away tha this is a calculator. The fact that the user "clicks" a button is a UI concern. The operation performed when the user clicks the button is not a UI concern. But both are mixed in our implementation. Element class and id names are a UI concern and not the application logic's concern. If a designer changes a class name to suit his/her needs the logic will break. Also, we spend a lot of code getting and putting values to our UI elements. All the above also prove that our logic does not obey the SRP principle.

The solutions

To make our CSS stylesheed dry we just need to use the SASS framework. The three powerful features that will come handy for our needs are shown in the following SASS code:

$width:960;
$backcolor: #cccccc;
$baseFont:14;

@function em($target, $context: $baseFont) {
    @return ($target / $context) * 1em;
}

.container{
    font-family:Helvetica, Arial, 'DejaVu Sans', 'Liberation Sans', Freesans, sans-serif;
    font-size:$baseFont * 1px;

    width:em(500);
    height:em(280);

	.header{
		background-color:$backcolor;
		height:em(60);
		.text{
			font-size:em(24);
			text-align:center;
			padding-top:em(13,24);
			color:black;
			font-weight:700;
		}
	}
	...					
				

First, we can define variables for the property values that will get repeated within our CSS ($width,$backcolor) soliving the problem of repeating them again and again. Second, we can nest our rules avoiding the repetition of the selector names (.header is in the .container now so the .container selector is not repeated twice). Third we can define functions that will be executed to provide the property values. Here we have implemented the em function that gets a pixel value and converts it to em based on the supplied font size in pixels. Therefore we can keep working with pixel values with just enclosing them in the em function and the SASS will convert them to ems when needed.

Those three small changes have just made our CSS dry! But wait a minute. How is this converted to CSS? The conversion is not done online but during deployment therefore you do not need to worry about your client having to install something or about any impact in performance. A very useful addin that does that on the fly while you develop in VS2012 is Mindscape's Web Workbench. You write your rules say in a demo.scss file (the SASS code file), you include the demo.css file in your HTML and the tool does the conversion whenever you save the .scss file effectively recreating the actual .css file.

Now let's move to the logic of the application.

Knockoutjs is a framework that lets us implement the MVVM pattern. Therefore we can create a javascript object where all the logic of the UI will reside as follows:

	
var ipplos = ipplos || {};
(function () {
    "use strict";

    ipplos.calculatorViewModelFactory = function (viewModelParameters) {
        return {
            operation: ko.observable(''),
            operand1: ko.observable('0'),
            operand2: ko.observable('0'),
            result: ko.observable(0),
            selectOperation: function (op) {
                this.operation(op);
            },
            performOperation: function () {
                var operand1F = parseFloat(this.operand1());
                var operand2F = parseFloat(this.operand2());

                if (this.operation() == "+") this.result(operand1F + operand2F);
                if (this.operation() == "-") this.result(operand1F - operand2F);
                if (this.operation() == "x") this.result(operand1F * operand2F);
                if (this.operation() == "/") this.result(operand1F / operand2F);
                if (this.operation() == "o") {
                    var _this = this;
                    $.get(viewModelParameters.sop1ServiceURL, { operand1: this.operand1(), operand2: this.operand2() }, function (data) {
                        _this.result(data);
                    });
                }
            }

        }
    }
})();
				

We create a factory (calculatorViewModelFactory) in the "ipplos" namespace that returns an object which is our viewmodel. As you can see this model conveys much more clearly the purpose of the logic by defining the properties and the functions that are used. This factory is thus highly reusable. The only artifacts that we can detect in its code, are those strange ko.observable wrapper functions which are the knocknoutjs way of defining a property that will provide notifications for the UI that it has changed value in order for the latter to update itself.

Having defined that class, then we just need to create an object of that class passing some parameters if needed (usually the ones that will be created server side by some Razor syntax) and attach it to a toplevel element of our view (the HTML5 file) using the ko.applyBindings function as follows (the parameter in this example is the URL of the server side operation endpoint):

	
var viewModelParameters = {
    sop1ServiceURL: '@Url.Action("SOp1","Demo")'
};

var VM = ipplos.calculatorViewModelFactory(viewModelParameters);
ko.applyBindings(VM, $(".container")[0]);
				

Now from within our HTML we can specify "bound" elements to the properties of this object. For example:

<div class="display">
    <input class="operand1 operand" type="text" data-bind="value:operand1" />
    <div class="operator" data-bind="text: operation"></div>
    <input class="operand2 operand" type="text" data-bind="value: operand2" />
    <div class="result" data-bind="text: result"></div>
</div>
<div class="actions">
    <button class="addition actionButton" data-bind="click: function () { selectOperation('+'); }">+</button>
    <button class="subtraction actionButton" data-bind="click: function () { selectOperation('-'); }">-</button>
    <button class="division actionButton" data-bind="click: function () { selectOperation('/'); }">/</button>
    <button class="multiplication actionButton" data-bind="click: function () { selectOperation('x'); }">x</button>
    <button class="serverOp1 actionButton" data-bind="click: function () { selectOperation('o'); }">o</button>
    <button class="equals actionButton" data-bind="click: performOperation">=</button>
</div>
					
				

All the "data-bind" attributes tie a property of the element with the value of the property of the object viewmodel. For example "data-bind='value:operand1'" states that the value of the input element should reflect always the value of the property "operand1" of the viewmodel and vice-versa. Or the "data-bind='click:performOperation'" means that when the event click is produced by the element, the function "performOperation" should be called from the viewmodel.

And this is it! With just the use of the knockoutjs framework we have eliminated all element class,id names from our logic, have clearly specified the behavior of the system in a reusable javascript class and do not have to write any code to transfer data from or to the UI elements. Thus, we can safely say that our implementation now obeys the "Single Responsibility Principle".

And this is it. Two frameworks, the knockoutjs and the SASS framework have helped as reach a much more better implementation in terms of code quality. The resulting code is much more resuable, less prone to bugs and easier to change. The full code of this demo can be downloaded here.

A simple way to detect memory leaks in C# and how to create one with events :)

In this post we will see a simple code fragment that can be used to detect memory leaks (more specific objects that are not cleaned by the garbage collector) and we will do it in the context of an interesting memory leak that can be created when using event delegates.

The memory leak with event delegates

Suppose you have an application in WPF with a single window that presents some money values in a specific currency (say EURO). At a specific instance you may have more than one such windows open.

Now a requirement comes that defines that you need to be able to change the currency (say from euro to dollar) and have this change be reflected immediately to any currently open window displaying the money value. One easy way to tackle this is shown in the following figure:

The "settings" object is static with a static property "Currency" with the current currency and an event called "OnCurrencyChanged" that is fired when the currency is changed. The "Window" class ("window1" nad "window2" objects) defines a method "currencyChanged". When a window is opened it attaches the "currencyChanged" method to the "OnCurrencyChanged" event. This method will be called whenever the event is fired and will be responsible for converting the money values in the windows. Let's see some code for that. First the "settings" class:

public static class settings
{
    public static event Action OnCurrencyChanged;

    public static void ChangeCurrency(string newCurrency)
    {
        //...
        if (OnCurrencyChanged != null)
            OnCurrencyChanged(newCurrency);
    }

}				

The code for the window with the money values has the "currencyChanged" method:

public partial class MoneyWindow : Window
{
    public MoneyWindow()
    {
        InitializeComponent();
    }

    public void currencyChanged(string newCurrency)
    {
        // Change the view to reflect the change here
    }
}				

The initializer of the window with the money values will be as follows:

MoneyWindow dlg = new MoneyWindow();
dlg.Show();
settings.OnCurrencyChanged += dlg.currencyChanged;	

Which in other words defines that when the window is created it will be listening to the "OnCurrencyChanged" event.

And you have your memory leak right there! Even if you close the window in some time, the event you have attached still keeps it "connected" to your application and therefore it will never be garbage collected. Just for a reminder, the objects are destroyed by the garbage collector when there are no other objects pointing to them. But in this case you have an "implicit" connection with the event. If you execute the demo application (here) you will see that opening and closing the window keeps consuming more and more memory which never gets freed (it helps to have the "Task Manager" open to test that). The solution is simple and it just requires you to unsubscribe from the event with "-=" when the window is closed. But say you are in a large application you are not sure whether an object gets garbage collected or not and wanna check that then what can you do?.

Detecting memory leaks

Or better checking whether an object will get garbage collected. Implement in your project a class like the following:

public static class MemoryLeak
{
    public static WeakReference Reference { get; private set; }

    public static void CheckObject(object ObjToCheck)
    {
        MemoryLeak.Reference = new WeakReference(ObjToCheck);
    }

    public static void IsItDead()
    {
        GC.Collect();
        GC.WaitForPendingFinalizers();
        if (MemoryLeak.Reference.IsAlive)
            Debug.WriteLine("Still here");
        else
            Debug.WriteLine("I 'm dead");
    }
}				

The code creates a weak reference to an object. The "weak reference" means that while it keeps a reference to the object this does not prevent the garbage collector from cleaning it (in other words this reference does not count in terms of collecting the object when not referenced). So we create the reference and then by calling "IsItDead" we just force the GC to collect any unneeded objects. If the object in question still persists then we have a memory leak.

For our example above, when we create the window we create a weak reference to the window object. Then we create a button that calls the "IsItDead" method. If we do not have a memory leak then the method should return "Still here" while the window is open and "I 'm dead" a while after the window is closed.

You can download the demo project here

Posted: Κυριακή, 26 Μαΐου 2013 5:31 μμ από iwannis | 0 σχόλια
Δημοσίευση στην κατηγορία: ,
Handling errors and internet connectivity problems in Windows 8 Apps with navigation (WinJS)

In this post we will explore a generic way of handling unpredicatble errors/lost connectivity in our Windows 8 Apps developed with HTML5 and Javascript. The two requirements we need to tackle are as follows:

  • There is a chance that while our application is running, internet connectivity will be lost. We need to know when this happens in order to inform the user and possibly handle the problem while preserving application state.
  • Unpredicatble errors may occur that will cause a general exception. We need to "catch" those errors, informing the user with a generic (and apologetic) error message and maybe transmit some useful details about the error to a service we have implemented for this purpose.

Handling internet connectivity problems

First we need a way to verify whether the app has connectivity to the internet. This can be done by using the following function:

utilities.isConnected=function() {
	var connectivity=Windows.Networking.Connectivity;
	var profile = connectivity.NetworkInformation.getInternetConnectionProfile();
	if (profile) {
		return (profile.getNetworkConnectivityLevel() != connectivity.NetworkConnectivityLevel.internetAccess);
	}
	else {
		return false;
	}
}					

The function returns true if the application is connected to the internet and false if it is not. This function can be used in a page whenever the user clicks on a button or in general an action will be invoked that will trigger a WinJS.xhr or something similar and if it returns false the application should prevent the action from being executed.

The same can be applied when the user navigates to a page that uses the internet in its "onload" event. But in this case what can you do? Meaning that the user reaches the page/pages that to fetch data "on load", the connection is down so nothing is fetched and then you need to display a button or something or start a timer that checks the coneectivity and at some time refreshes the page.

Or you could easily and with a few lines of code handle this case generally as follows: The idea is to use a "nointernet" page and lead the user there when you detect there is no internet. Then you prompt the user to hit the back button or a button you provide when he feels that the connection has been re- established. So let's see how this works:

First you need to implement a simple "no internet" page. A snapshot of the page is given below.

demo nointernet page

In the navigator.js file that handles the navigation, we find the _navigated function that is called whenever a user goes from one page to another before the load event of the new page and we add the following lines at the top:

_navigated: function (args) {
	if (args.detail.location.indexOf("nointernet") == -1 && !utilities.isConnected()) {
		nav.navigate("/pages/nointernet/nointernet.html");
		return;
	}	
	// ...rest of the function			

This means that if we are not already in the "nointernet" page and the internet connectivity has been lost instead of going wherevere the user chose to go we navigate to the "nointernet" page.

In the "nointernet" page the click event handler of the "Retry" button calls WinJS.Navigation.back();

And this is it. With just a few lines of code you can handle with dignity all connectivity issues that may occur during the user's navigation in all application pages

Handling unpredicatble erros

The second requirement states that the app should be able to handle unpredictable errors in a graceful manner. We will follow a similar approach with an "error" page dedicated just for that.

demo nointernet page

The "Retry" button with just call again WinJS.Navigation.back() hoping that ther error was temporar. But how do we send the user to this page upon an unpredictable error?

We just need to handle the onerror event in the default.js file (or in some other file) as follows:

app.onerror = function (customEventObject) {
    var errorMessage = '';
    var errorName = '';
    if (customEventObject.detail.error) {
        errorMessage = customEventObject.detail.error.message;
        errorName = customEventObject.detail.error.name;
    }
    else {
        errorMessage = customEventObject.detail.exception.message;
        errorName = 'Exception';
    }
    var optionsObject = { errName: errorName, errMsg: errorMessage };
    nav.navigate("/pages/error/error.html", optionsObject);
    return true;
}				

Now if you want to take this one step further and have some private service listening for those errors (so you know what your users are experiencing) you can implement a simple ASP.MVC 3 application (empty), add just one controller (say ServicesController) with a single Action called Error:

public class ServicesController : Controller
{
    public JsonResult Error(string errName,string errMsg)
    {
        // Store the data in the database or whatever 
        return Json(new {stored=true},JsonRequestBehavior.AllowGet);
    }

}				

You host this service in the net and then in the "error" page (on ready event) you write something similar to the following:

ready: function (element, options) {
    element.querySelector("#buttonRetry").onclick = function (ev) {
        WinJS.Navigation.back();
    }

    WinJS.xhr({ url: 'http://localhost:10162/Services/Error?errName=' + 
                options.errName + '&errMsg=' + options.errMsg }, function (data) {

    });
}				

Now you have a personal bug reporting tool so you know the problems that occur for each one of the deployed application instances out there.

Posted: Παρασκευή, 24 Μαΐου 2013 3:57 μμ από iwannis | 0 σχόλια
Δημοσίευση στην κατηγορία: ,
Drag and Drop in WinJS.UI.ListView for repositioning items in Windows Store Apps

After hours of searching in the documentation in order to implement a decent drag and drop behavior in WinJS.UI.ListView (like the one we see on the “start” screen) I have finally managed to make it happen and in this post I am sharing the way it can be done. During this post there are also answers about:

How to provide multiple templates for the ListView items.

How to “gesture enable” your DOM elements.

The main requirement is simple.

You have a WinJS.UI.ListView control on your Windows Store app and need to allow the user move some elements in the list (usually to allow the user to define via drag and drop their order in the list).

We will start with a very simple project where a demo list (dataList) is defined as follows:


var groups = [
    { key: 'group1', title: 'Group 1' },
    { key: 'group2', title: 'Group 2' }
];
var dataList = new WinJS.Binding.List();
dataList.push({ group: groups[0], data: { id: 1, name: 'one' } });
...
dataList.push({ group: groups[0], data: { id: 7, name: 'seven' } });

dataList = dataList.createGrouped(
        function (item) {
            return item.group.key;
        },
        function (item) {
            return item.group;
        });
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }


That is we create a WinJS.Binding.List object with 7 elements all having their property group pointing to groups[0] (which means that they will belong to the same group.Later we will change that) and some demo object in their data property. We then use the createGrouped method passing as arguments the function that defines the id of the group each item belongs to and the function that returns the actual group object for each item. Now our dataList is ready to be the source of a WinJS.UI.ListView control. The control in HTML is defined with two templates (one for the group items with class name “.groupTemplate” and one for the list items with class name “.itemTemplate”).


<div class="groupTemplate" data-win-control="WinJS.Binding.Template">
    <span data-win-bind="textContent: title"></span>
</div>
<div class="itemTemplate" data-win-control="WinJS.Binding.Template">
    <div style="width:200px;height:200px;background-color:green">
        <div data-win-bind="textContent:data.name" style="padding:20px"></div>
    </div>
</div>
<div data-win-control="WinJS.UI.ViewBox">
    <div class="fixedlayout">
        <div id="demoListView" style="width:100%;height:100%;" data-win-control="WinJS.UI.ListView"></div>
    </div>
</div>
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

Note that although we could declarative define the templates in the div element of the ListView control, we choose not to do so since for the implementation of drag and drop we will have to add some code to the “item from template generation logic”. Therefore we initialize the templates via code as follows:


var demoListView = document.querySelector("#demoListView");
var demoListViewControl = demoListView.winControl;
demoListViewControl.layout = new WinJS.UI.GridLayout({
    groupHeaderPosition: "top",
    groupInfo: {
        enableCellSpanning: true,
        cellWidth: 100,
        cellHeight: 100
    }
});
demoListViewControl.groupHeaderTemplate = document.querySelector('.groupTemplate');
demoListViewControl.itemTemplate = function (itemPromise) {
    return itemPromise.then(function (item) {
        var itemTemplate = document.querySelector('.itemTemplate');
        var container = document.createElement("div");
        itemTemplate.winControl.render(item.data, container).done();
        return container;
    });
}
demoListViewControl.itemDataSource = dataList.dataSource;
demoListViewControl.groupDataSource = dataList.groups.dataSource;
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

The layout property is defined as a GridLayout object and we provide the enableCellSpanning, cellWIdth and cellHeight properties to allow multiple sizes for the item templates if needed (only remember that their size needs to be a multiple of the cellWidth and cellHeight properties taking into consideration the margins between them). We define a fixed header template for the display of the current group and then a function that returns the required template for the item. Usually the function is provided if we need to support multiple item template but in our case we use it to gain access to the items’ DOM elements.

Let’s first “gesture enable” our DOM Elements so that they can understand user gestures (meaning different “kinds” of mouse or touch interactions such as tap, hold, swipe). To do this we need to run a function like the following for the DOMElement:


prepareDOMElementForGestures:function (DOMElement) {
    var msGesture = new MSGesture();
    msGesture.target = DOMElement;
    DOMElement.gesture = msGesture;

    DOMElement.addEventListener("MSGestureStart", _gestureHandler, false);
    DOMElement.addEventListener("MSGestureEnd", _gestureHandler, false);
    DOMElement.addEventListener("MSGestureChange", _gestureHandler, false);
    DOMElement.addEventListener("MSInertiaStart", _gestureHandler, false);
    DOMElement.addEventListener("MSGestureTap", _gestureHandler, false);
    DOMElement.addEventListener("MSGestureHold", _gestureHandler, false);
    DOMElement.addEventListener("MSPointerDown", _gestureHandler, false);
}

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }


This adds the appropriate event handlers and assigns the MSGesture object to the DOM element. The handler “_gestureHandler” is as follows:
_gestureHandler :function (event) {
    if (event.currentTarget.gesture.target == null)
        event.currentTarget.gesture.target = event.currentTarget;
    if (event.type == "MSPointerDown") {
        event.currentTarget.gesture.addPointer(event.pointerId);
    }
    if (event.type == "MSGestureStart") {
        if (this._inDragAndDrop) {
            // initializations here
        }
    }
    if (event.type == "MSGestureHold") {
        this._inDragAndDrop = true;
    }
    if (event.type == "MSGestureChange") {
        if (this._inDragAndDrop) {
            // respond to mouse movement
        }
    }
    if (event.type == "MSGestureEnd") {
        if (this._inDragAndDrop) {
            // finalize
            this._inDragAndDrop=false;
        }
    }
    if (event.type == "MSGestureTap") {
    }
}

Some important points here is the you should not erate the MSPointerDown if block since it is needed for the handler. Also the highlighted in yellow part is a hack since sometimes the DOMElement looses its gesture object when added to the list and by doing this we reassign it in the first call of the handler. The other is straightforward. On Hold we set the drag and drop is ready to start. On Start we initialize, on Change we move and on End we will be checking what has happened. The tap gesture is needed since by enabling gestures on the DOMElement we are effectively “stealing” its click event.

Therefore to enable gestures in our list item’s DOM Elements we change the rendering line of the template generation function (and this is why we need it even though we only have one template) as follows:


demoListViewControl.itemTemplate = function (itemPromise) {
        ...
        itemTemplate.winControl.render(item.data, container).done(function (ev) {
            setTimeout(function () {
                dragAndDrop.prepareDOMElementForGestures(container.parentElement, true);
            }, 100);
        });
        ...
}
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

The whole idea lies at the fact that as we generate the DOM element for the list item, we enable it for the gestures. The timeout is needed to allow some time for the ListView to render the item in the document so we get the complete DOMElement. Now when the hold gesture is detected we set the boolean of drag and drop to true and then when gesture start is detected. So in “MSGestureStart” if block:


if (this._inDragAndDrop) {
    event.target.style.zIndex = 10000;
    WinJS.UI.Animation.dragSourceStart(event.currentTarget).done();
    this._initPos.left = parseInt(event.target.style.left.replace("px",""));
    this._initPos.top = parseInt(event.target.style.top.replace("px", ""));

    var listToScrollElement = this._listViewDOM.querySelector(".win-viewport.win-horizontal");
    this._offset.left = event.clientX + listToScrollElement.scrollLeft - this._initPos.left;
    this._offset.top = event.clientY - this._initPos.top;
}


We set the zIndex of the element to a big value to make it appear on top of everything else. We then animate the element to show that drag has started. We then store the initial position of the element (to return it if drop is cancelled) and we also calculate the offset of the mouse-touch position in relation to the top left corner of the DOMElement (this is to keep moving the element at the point where our mouse-touch pointer was initially detected and it also takes into consideration the scroll position).

Now during the movement of the mouse-finger (MSGestureChange detected) we need to move the DOM element and also detect which items are under it in order to animate them also to give the user some feedback on where the item will be placed if dropped. Finally we need to detect the bounds of the display in order to scroll the list if needed.

We will tackle those issues one by one but note that all the code mentioned in the following paragraphs actually belongs to the “MSGestureChange” if block. Dragged item movement is the simplest of all:


var x = event.clientX;
var y = event.clientY;
var listToScrollElement = this._listViewDOM.querySelector(".win-viewport.win-horizontal");
event.currentTarget.style.left = (x - this._offset.left + listToScrollElement.scrollLeft).toString() + "px";
event.currentTarget.style.top = (y - this._offset.top).toString() + "px";
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

Then we need to know what element is under the mouse (not the dragged but the other below). This is achieved by temporarily hiding the dragged element to reveal through document.elementFromPoint the element underneath.


// get the DOM element currently under the mouse-finger
event.currentTarget.style.display = 'none';
var DOMElement = document.elementFromPoint(x, y);
event.currentTarget.style.display = '';
// get the index of the actual list item that the DOMElement belongs to (if none –1 will be returned)
var idx = this._listViewControl.indexOfElement(DOMElement);
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

Now the whole idea is to know which two elements need to be moved as the item is being dragged

drag

Using the above code we know the currentOverElement1(named DOMElement) and if idx is not –1 we know that this is actually a part of the ListView and not something that does not participate in the drag and drop action. So if we detect an idx change and this change gives as an idx that is not –1 then we know that currentOverElement1=DOMElement and we need to figure out what the currentOverElement2’s value will be. Of course this applies when we move to the right of the list. When we move left then we know currentOverElement2 and we need to find currentOverElement1. We also need to check for limit conditions at the start – end of the list and revert the previous currentOverElements.All of the above are implememented right after the previously mentioned code block in (MSGestureChange)


if (this._idxOfcurrentOverElement != idx) { // this means that the element has changed since the last event
    // if there were any previous elements animated
    if (this._currentOverElement1) WinJS.UI.Animation.dragBetweenLeave(this._currentOverElement1);
    if (this._currentOverElement2) WinJS.UI.Animation.dragBetweenLeave(this._currentOverElement2);

    var draggedItemIdx = this._listViewControl.indexOfElement(event.currentTarget);
    this._idxOfcurrentOverElement = idx;
    // if there are some elements to be animated below the mouse-finger
    if (this._idxOfcurrentOverElement != -1) {
        if (draggedItemIdx > this._idxOfcurrentOverElement) { // we are moving to the left
            this._currentOverElement1 = undefined;
            this._currentOverElement2 = this._listViewControl.elementFromIndex(this._idxOfcurrentOverElement);
            if ((this._idxOfcurrentOverElement - 1) >= 0)
                this._currentOverElement1 = this._listViewControl.elementFromIndex(this._idxOfcurrentOverElement - 1);
        }
        else { // we are moving to the right
            this._currentOverElement1 = this._listViewControl.elementFromIndex(this._idxOfcurrentOverElement);
            this._currentOverElement2 = undefined;
            if ((this._idxOfcurrentOverElement + 1) < this._listViewControl.itemDataSource.getCount()._value)
                this._currentOverElement2 = this._listViewControl.elementFromIndex(this._idxOfcurrentOverElement + 1);
        }
        if (this._currentOverElement1)
            WinJS.UI.Animation.dragBetweenEnter(this._currentOverElement1, { left: this._movementOffset.left, top: '0px' });
        if (this._currentOverElement2)
            WinJS.UI.Animation.dragBetweenEnter(this._currentOverElement2, { left: this._movementOffset.right, top: '0px' });
    }
}
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }


When the user drops the item since we know currentOverElement1 and 2 we know where the item is being dropped. If those are undefined we just restore the initial element’s position. Otherwise we call a method with the currentOverElement1,2 indexes as parameters that will manipulate the list and will return true if it has handled the placement or false if based on the logic the insertion should not be performed (MSGestureEnd if block).


this._inDragAndDrop = false;
event.target.style.zIndex = "";

if (this._currentOverElement1) WinJS.UI.Animation.dragBetweenLeave(this._currentOverElement1).done();
if (this._currentOverElement2) WinJS.UI.Animation.dragBetweenLeave(this._currentOverElement2).done();
WinJS.UI.Animation.dragSourceEnd(event.target, undefined, this._allDOMElements).done();

var idxOfLeftItem = this._listViewControl.indexOfElement(this._currentOverElement1);
var idxOfRightItem = this._listViewControl.indexOfElement(this._currentOverElement2);

var itemPlaced = false;
if (idxOfLeftItem != -1 || idxOfRightItem != -1)
    itemPlaced = this._dropCallback(this._listViewControl.indexOfElement(event.target), idxOfLeftItem, idxOfRightItem);
if (!itemPlaced) {
    event.target.style.left = this._initPos.left.toString()+"px";
    event.target.style.top = this._initPos.top.toString()+"px";
}
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }


A possible implementation of the dropcallback can be as follows:


function (itemIdx, leftItemIdx, rightItemIdx) {
    var dropAfterItem;
    if (leftItemIdx != -1)
        dropAfterItem = dataList.getAt(leftItemIdx);

    var item = dataList.getAt(itemIdx);
    var result = false;
    if (!dropAfterItem) { //Insert at the beginning
        dataList.move(itemIdx, 0);
        result = true;
    }
    else {
        var desiredPos = leftItemIdx < itemIdx ? leftItemIdx + 1 : leftItemIdx;
            dataList.move(itemIdx, desiredPos);
            result = true;
    }
    return result;
}

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }


Where we just check the indexes and perform some movements between the items in the list.

The only thing left to be added is the scrolling of the list while an item is being dragged. This is a matter of detecting the bounds of the displayed list and scrolling the view area while the mouse – finger remains in those bounds via a setTimeout. At the end of the drag and drop or when the mouse – cursor leaves those bounds you should remember to cancel the timeout. The implementation of the scrolling can be found in the demo project.

So this is what it takes to have drag and drop in WinJS.UI.ListView. A minor note to remember is that you will notice that dragBetweenLeave leaves a scale(0.95) transform to the element which I consider to be a library’s bug. If you find any solution to this please do contact me.

Download the demo project.

Posted: Τρίτη, 18 Δεκεμβρίου 2012 12:19 μμ από iwannis | 0 σχόλια
Δημοσίευση στην κατηγορία: , ,
Push Notifications in Windows 8 with ASP.NET MVC

In the previous post we have seen how we create scheduled and periodic tile notifications with Javascript for metro applications.

In this post we will cover push notifications. Push notifications do not require from your app to tell the OS that it has to query a service at specific time intervals as periodic notifications do. They rely on the fact that an external service can actually change the tile when it sees fit (hence the “push” name).

Such notifications cover scenarios like having an application that monitors stock prices and the user specifying that he wants to be informed when the price of a stock falls under a specific value. The push notification will change the tile’s appearance when the premise is fulfilled. Note that a periodic notification would not suit in this case unless the user could accept a possible maximum half hour delay of the delivery of the notification.

Push notifications work as follows:

 

  1. Your metro app requests from the device a specific URI which uniquely defines the combination app/device.
  2. Your metro app then transmits this URI to the server application you have implemented (in our case you will see that this is a ASP.NET MVC project). Your metro app can also transmit any other information specific to the logic of the notification required from the user.
  3. Your server application receives and saves the URI and it also receives and saves the logic for the push notification (when and under what circumstances the metro app desires to be notified).
  4. In order for your server application to send the push notification to that URI, it has to tell the Windows Push Notification Service (WNS-simply a server application offered for free from Microsoft) and this service will contact the actual device based on the supplied URI with the desired notification. So prior to doing so, your server application needs to authenticate itself with that service.

 

Before doing anything else you need to register your app. Full instructions can be found here and differentiate on whether you are a registered developer for the store or you just want to play around to see how things work. We will choose the second approach and therefore the short version of the registration instructions (in the document of the link above this is located in the Remarks section). So proceed as follows::

 

  1. Navigate to this link.
  2. Follow the instructions by supplying the application’s name and the publisher as required and click next.
  3. You will get a bunch of items that you will need to put in your application’s manifest file. This has connected the WNS with your application so they both know that each other exists via the keys. This has also given you all the appropriate stuff for your server application to use in order to communicate with the app on a user’s device (in a sense the URI will supply the exact machine/app and the security keys you obtained are an extra safety).

 

You can now start developing your server application. Create a new ASP.NET MVC project, create a ServicesController and provide a Register action as follows:

   1: public JsonResult Register(string uri)
   2: {
   3:     string[] parms = HttpContext.Request.RawUrl.Split(new string[] { "uri=" }, 
                                                    StringSplitOptions.RemoveEmptyEntries);
   4:     Subscribers.Uris.Add(parms[1]);
   5:     return Json(new { Success = true, Uri = uri }, JsonRequestBehavior.AllowGet);
   6: }

Note here that although we receive as a parameter the uri of the subscriber we prefer it to get it from the query string of the raw URL. This is because ASP.NET MVC decodes the encoded URL. The problem is that the uri you receive is partially encoded (the link is not encoded while the parameters are) and therefore it is not possible to get it in its decoded version adn  encode it again. Take good care of that cause otherwise you will be getting a 404 not found error when you try to send the notification and you will not be able to know the source of the error.

The Subscribers list is the one that will hold the URIs to be notified (metro apps). For our demo the class resides in the Models folder and is as follows:

   1: public static class Subscribers
   2: {
   3:     public static List<string> Uris = new List<string>();
   4: }

Of course in reality you would persist this information along with the notification predicates in a DB or file storage since the static list can be wiped out at any time! For our demo though we are just fine with this.

Having done that, if we deploy this simple ASP.NET MVC project and we provide in the metro app the following lines of code:

   1: Windows.Networking.PushNotifications.PushNotificationChannelManager
   2:     WinJS.xhr({ url: "http://server.application.address/Register?uri=" + channel.uri })
   3:         if (xhr.status < 200 || xhr.status >= 300) {
   4:             var dialog = new Windows.UI.Popups
   5:             dialog.showAsync();
   6:         }
   7:     });
   8: });
   9:  

We basically create a URI and then pass it to the server application (we can encrypt it for security but in this demo for simplicity we leave it as is).

So, we have managed to notify our server application that the metro app exists, with the URI it got from the Windows 8 device and is ready to receive Push Notifications. Of course, we have not supplied any predicates on when we require to receive such notifications (the logic and encoding of the way this will be communicated to the server app is up to the developer but will probably reside in some encoded string in a query string parameter (ie parameters) specified after the uri parameter: http://addres?uri=…&parameters=… This will be decoded by the server app along with the URI. In our case we will be generating the notification whenever we want from the server application.

Now all we have to do is write the code that will send the tile notification. This code can reside in any kind of application (windows service, WPF app) but in our case we will just provide an action in the ServicesController that exposes a view with an input box and a button. When the user clicks on the button, the text of the input box is sent as a tile notification to all subscriber URIs. The action in high level is as follows:

   1: WNSAuthorizer.OAuthToken Token = WNSAuthorizer.GetOAuthToken(<clientsecret>,<packageSID>);
   2: foreach (var uri in Subscribers.Uris)
   3: {
   4:     PushNotifier Notifier = new PushNotifier(uri, Token.AccessToken);
   5:     Notifier.SendNotification(PushNotifier.PushType.Tile, msg, "");
   6: }

Where in <clientsecret> and <packageSID> you provide the credentials you got from registering the application for push notifications. The code above uses a helper class to get authorization with the WNS (WNSAuthorizer) and then uses a helper class (PushNotifier) to send the push notification to all recipients. The correct format of the tile notification can be seen if you download the code for the helper classes at the end of this post. Note that this code is based on the code given in the article. Basically the notification for the tile has identical xml payload with the one presented in the previous post for periodic and scheduled notifications. Also the code allows you to send different kinds of push notifications tile and badge.

 

And this is it! You have managed to build an ASP.NET MVC application that will be able to send push notifications to windows 8 metro style apps. The ASP.NET MVC project can be downloaded

(for obvious reasons the credentials have been removed from the project and therefore you need to supply the ones that apply to your app. The project is in VS2012 but you can open the files in VS2010 and see the logic).
Tile Notifications in Windows 8 (Javascript)

This post will cover the main aspects of using Tile Notifications in a Metro-Style application. The only topic that will not be covered is “Push Notifications” since those deserve a post on their own and will follow in the near future.

So what are “Tile Notifications”? Well as you already know, each Metro-Style application has its own tile which appears in the start screen. This tile is either a “square” or a “wide” one as depicted in the following figure:

 

tiles

 

The user gets to choose from the “start menu” application bar which one of the two will be shown. You specify in your application that you support both by providing in the package.appxmanifest file (Application UI tab) a image for both the Logo and the Wide logo property:

 

LogoWide

 

It is important that you provide the wide version of the logo cause otherwise your application will not be able to appear as “wide” in the start menu and that option will not exist for the user in the application bar. Having done this, you may use the tile to make it “alive”, that is to provide some meaningful information (related to your app) to the user. The way this information will be delivered, defines the type of the notification:

 

Scheduled: Your application, when it is executed, schedules for some tile notification in the future. A possible scenario for this is when you have for example a calendar app, the user adds an appointment and defines that he would like to get notified. Then your app may schedule a notification to appear in the tile when the time comes.

Periodic: Your applications, at specific time intervals, asks from the operating system to make a request to a web service and display in the application’s tile the content it receives from the service. A possible scenario for this is when for example your app displays news of some kind and you want your tile to always present the latest news.

Push: Those are notifications that are initiated from a web service outside of your app which instructs the OS to change your tile with the content the service provides. As stated before this kind of notification and the way to create a web server capable of delivering such notification will be explained in a future post.

 

Apart from the type of notifications you may also define a notifications queue. That is you can define whether a newer notification will overwrite the current one displayed on the tile or the new notification will be inserted in a queue of the five most recent ones to be cycled on the tile. So let’s get started with the following code that schedules for a notification after 10 seconds:

   1: var notifications = Windows.UI.Notifications;
   2: var currentDate = new Date();

The following lines create the tile appearance for its “wide” version. The version is defined by the template (highlighted in yellow). The list of available templates may be found here. Basically the content provided for the tile is nothing more than a simple xml document with the information required for each tile type.

   1: var tileXMLWide = notifications.TileUpdateManager.getTemplateContent
                                               (notifications.TileTemplateType.tileWideText03);
   2: var tileAttributesWide = tileXMLWide.getElementsByTagName("text"); 
   3: tileAttributesWide[0].appendChild(tileXMLWide.createTextNode("First Notification"));

The following lines create the tile appearance for its “square” version (of course we may only create one of the two but it is good practice if we support both versions to support both versions in the notifications also):

   1: var tileXMLSquare = notifications.TileUpdateManager.getTemplateContent
                                               (notifications.TileTemplateType.tileSquareText01);
   2: var tileAttributesSquare = tileXMLSquare.getElementsByTagName("text"); 
   3: tileAttributesSquare[0].appendChild(tileXMLSquare.createTextNode("1st"));

Finally the two versions “square” and “wide” are packed in a single XML document:

   1: var node = tileXMLWide.importNode(tileXMLSquare.getElementsByTagName("binding")[0], true); 
   2: tileXMLWide.getElementsByTagName("visual").item(0).appendChild(node);

And the tile update is ready to be scheduled

   1: var futureTile = new notifications.ScheduledTileNotification(tileXMLWide, 
                                                       new Date(new Date().getTime() + 10 * 1000));
   2: futureTile.id = "Tile1"; 
   3: notifications.TileUpdateManager.createTileUpdaterForApplication().addToSchedule(futureTile);

If we want to add more scheduled notifications we just create them as above and add them to the Schedule with the previous (last) line. Now because we have not specified any "”queue” the next notification will overwrite the current. Therefore the tile’s id, tag does not play an role. If we don’t provide a new notification the current one will remain visible for ever unless we provide an expiration date for the notification. Adding the following line to the notification we have created before adding it to the schedule will make the notification disappear after 10secs from its appearance:

   1: futureTile.expirationTime = new Date(new Date().getTime() + 20 * 1000);

Now for periodic notifications we need to create a basic service (web service) that returns the XML required for updating the tile. The XML to generate is the same as before and taken from the possible templates here. Again we main combine the two tile versions square and wide to support both. An example of possible XML generated from the service is given in this link. So how can you create first of all such a service? One way to go is to use an ASP.NET MVC project. Go ahead and create one. Then erase the Content, Script etc folders. Create a class in the Models folder as follows:

   1: public class TileData
   2: {
   3:     public string Image1 { get; set; }
   4:     public string Image2 { get; set; }
   5:     public string Image3 { get; set; }
   6:     public string Image4 { get; set; }
   7:     public string Image5 { get; set; }
   8:  
   9:     public List<string> Text { get; set; }
  10: }

Then write the following code in the HomeController’s Index action (you basically need to populate with data the model you have created in the Models folder and pass it to the view). In the following example we just populate the model with random values:

   1: public ActionResult Index()
   2: {
   3:     TileData Model = new TileData();
   4:     // Popullate the model with your data here
   5:     return View(Model);
   6: }

Finally your view (for the index action) will be something like the following:

   1: @{
   2:     Layout = null;
   3:     Response.ContentType = "text/xml";
   4: }
   5: @model MetroStylePullNotificationDemo.Models.TileData 
   6: <tile>
   7:     <visual lang="en-US">
   8:         <binding template="TileSquarePeekImageAndText03">
   9:             <image id="1" src="@Model.Image1" />
  10:             @for (int i=0;i<Model.Text.Count;i++)
  11:             {
  12:                 @:<text id="@(i+1)">@Model.TextIdea</text>
  13:             }
  14:         </binding>
  15:         <binding template="TileWideImageCollection">
  16:             <image id="1" src="@Model.Image1" />
  17:             <image id="2" src="@Model.Image2" />
  18:             <image id="3" src="@Model.Image3" />
  19:             <image id="4" src="@Model.Image4" />
  20:             <image id="5" src="@Model.Image5" />
  21:         </binding>
  22:     </visual>
  23: </tile>

You then deploy your service and you are “good to go” server-side. In your metro-style app it is very easy to tell the OS that you need it to query that service to update your tile with the following code:

   1: var recurrence = notifications.PeriodicUpdateRecurrence.halfHour; 
   2: var url = new Windows.Foundation.Uri("http://www.progware.org/windows8/tiles/"); 
   3: notifications.TileUpdateManager.createTileUpdaterForApplication().
                                      startPeriodicUpdate(url, recurrence);

Note that the period is an enumeration and can be of specific values only (30min, 1hour, 6hour, 12hour,24hour) and that is expected since the OS will handle the requests and your app lives in an ecosystem with hundreds of other apps that will compete for the same resources and bandwidth.

 

No matter the notification type (scheduled or periodic) you can activated the queue for holding the last ones and recycling them in a random order that favors the most recent ones. This is done with a single directive:

   1: notifications.TileUpdateManager.createTileUpdaterForApplication().enableNotificationQueue(true);

Having the queue means that your notification may live more than you want them to or you may need to update an already present notification in the queue. For this reason in this case it is important to tag your notifications by setting their tag property (for scheduled notifications). In periodic notifications this tag is inserted at the response header (see here– the Remarks section). Actually, in the header, we also store the notification’s expiration time.

So this was a brief overview on using tile notifications in metro-style apps with Javascript.We have seen scheduled and periodic notifications. I n the near future there will be a post for push notifications.

Posted: Τετάρτη, 27 Ιουνίου 2012 8:51 πμ από iwannis | 0 σχόλια
Δημοσίευση στην κατηγορία: ,
Welcome to BlogEngine.NET 2.6

If you see this post it means that BlogEngine.NET 2.6 is running and the hard part of creating your own blog is done. There is only a few things left to do.

Write Permissions

To be able to log in to the blog and writing posts, you need to enable write permissions on the App_Data folder. If your blog is hosted at a hosting provider, you can either log into your account’s admin page or call the support. You need write permissions on the App_Data folder because all posts, comments, and blog attachments are saved as XML files and placed in the App_Data folder. 

If you wish to use a database to to store your blog data, we still encourage you to enable this write access for an images you may wish to store for your blog posts.  If you are interested in using Microsoft SQL Server, MySQL, SQL CE, or other databases, please see the BlogEngine wiki to get started.

Security

When you've got write permissions to the App_Data folder, you need to change the username and password. Find the sign-in link located either at the bottom or top of the page depending on your current theme and click it. Now enter "admin" in both the username and password fields and click the button. You will now see an admin menu appear. It has a link to the "Users" admin page. From there you can change the username and password.  Passwords are hashed by default so if you lose your password, please see the BlogEngine wiki for information on recovery.

Configuration and Profile

Now that you have your blog secured, take a look through the settings and give your new blog a title.  BlogEngine.NET 2.6 is set up to take full advantage of of many semantic formats and technologies such as FOAF, SIOC and APML. It means that the content stored in your BlogEngine.NET installation will be fully portable and auto-discoverable.  Be sure to fill in your author profile to take better advantage of this.

Themes, Widgets & Extensions

One last thing to consider is customizing the look of your blog.  We have a few themes available right out of the box including two fully setup to use our new widget framework.  The widget framework allows drop and drag placement on your side bar as well as editing and configuration right in the widget while you are logged in.  Extensions allow you to extend and customize the behaivor of your blog.  Be sure to check the BlogEngine.NET Gallery at dnbegallery.org as the go-to location for downloading widgets, themes and extensions.

On the web

You can find BlogEngine.NET on the official website. Here you'll find tutorials, documentation, tips and tricks and much more. The ongoing development of BlogEngine.NET can be followed at CodePlex where the daily builds will be published for anyone to download.  Again, new themes, widgets and extensions can be downloaded at the BlogEngine.NET gallery.

Good luck and happy writing.

The BlogEngine.NET team

Posted: Παρασκευή, 20 Απριλίου 2012 12:00 μμ από iwannis | 5 σχόλια
Δημοσίευση στην κατηγορία:
(Windows8) WinJS single page navigation and ViewModels

In the previous post, we have seen simple data-binding scenarios using WinJS and got a glimpse on the way a ViewModel can be created (following the MVVM pattern). In this post, we will build and application where there are more than one views (pages - simple page navigation app) with simple html elements and ListViews with real data. The question we need to answer is:

 

How do the ViewModels and MVVM can be applied in a single page navigation WinJS application?”

(FOR .NET Developers: if you are coming from the .NET world and especially XAML you will also get a chance to see how things like INotifyPropertyChanged and ObservableCollections apply to the WinJS world. The ViewModel presented here is as close as possible to the one that would be applied in a WPF-Silverlight window)

 

We will create a simple app that displays the births and deaths of celebrities in today’s date. Data will come from the RSS feeds provided by IMDB. Clicking on a celebrity should lead us to a new page where we get the IMDB webpage of that celebrity. Within this application, ViewModels will be used for each page. The requirements we have for our ViewModels are as follows:

 

  • There should be one ViewModel for each page.
  • The ViewModel should hold all the variables and methods required to provide the data to the view (html page)
  • The view will connect to the ViewModel through data binding.
  • All events generated by the page should also fire methods of the ViewModel.

 

Open VS 2011 and create a “Navigation Application” project. The “default.html” file that is generated contains the following:

 

<div id="contenthost" data-win-control="BirthsDeaths.PageControlNavigator" 
data-win-options="{home: '/html/homePage.html'}">
</div>

That defines an area that will be loading your pages according to your application’s state. This area is initialized and loads the “homePage.html” page (VS has also generated for you a navigate.js file that handles the navigation. For an introduction to single page navigation you can read this article).

 

You should consider each page that will be loaded in this area as a separate window or view of your application. Therefore, each page should have its own ViewModel. In our case, we have two pages: one (homePage) that displays the births and deaths in two ListViews and one (actorDetails) that displays the actor’s details when the user clicks on an item in the lists.

 

Let’s start with the homePage view that will look like the one in the following figure:

 

image

 

That is, there should be two lists one showing the deaths and one showing the births. Also, just below the main header we need to display the date and time and a downloading message when the data are fetched from IMDB. The html that generates that view is (of course there is the .css that also does the layout magic):

 

<section aria-label="Main content" role="main">
<span id="dateSpan"></span>&nbsp;&nbsp;
<span id="downloadingSpan"></span>
<section class="listsContainer">
<h2 class="birthsHeader">born today</h2>
<h2 class="deathsHeader">died today</h2>
<div id="birthsListElement" data-win-control="WinJS.UI.ListView"></div>
<div id="deathsListElement" data-win-control="WinJS.UI.ListView"></div>
</section>
</section>

So for our ViewModel we will need: A property for the date/time, a property for the “downloading” message, two lists for the births and deaths, two methods to fetch the deaths and births and the event handler that will be invoked when the user clicks on a list item. In the “homepage.js” file, the process for creating this ViewModel is as follows:

Within the self executing function that is generated for us, we define a new class (WinJS.Class.define) that we name HomePageViewModelClass:

 

var HomePageViewModelClass = WinJS.Class.define(
function () {
this.onShowActorDetailsBirths = this.showActorDetailsBirths.bind(this);
this.onShowActorDetailsDeaths = this.showActorDetailsDeaths.bind(this);
},
{
_today: "",
today: {
get: function () {
return this._today;
},
set: function (value) {
this._today = value;
this.notify("today", value);
}
},

_downloading: "",
downloading: (...),

birthsList: new WinJS.Binding.List(),
deathsList: new WinJS.Binding.List(),
getBirths: function () {
this.downloading = "(downloading...)";
var that = this;
var syn = new Windows.Web.Syndication.SyndicationClient();
var url = new Windows.Foundation.Uri("http://rss.imdb.com/daily/born/");
syn.retrieveFeedAsync(url).then(
function (feed) {
for (var i = 0, len = feed.items.length; i < len; i++) {
var item = feed.itemsIdea;
var birth = {
title: item.title.text,
date: item.publishedDate,
content: item.summary.text,
link: item.links[0].nodeValue
}
that.birthsList.push(birth);
}
that.downloading = "";
});
},
getDeaths: (...),
showActorDetailsBirths: function (e) {
this._showActorDetails(this.birthsList.getAt(e.detail.itemIndex));
},
showActorDetailsDeaths: function (e) {
this._showActorDetails(this.deathsList.getAt(e.detail.itemIndex));
},

_showActorDetails: function (item) {
WinJS.Navigation.navigate("/html/actorDetail.html", item);
}

}
);


There are a few things to note here:

 

  • For the properties “today” and “downloading” we use accessors. The accessors get and set their corresponding private fields. Note that after they set their value they call a “strange” (for now) method which is called notify with the name of the property that has changed and the new value. You will see in just a minute where this method is defined but for now remember that this is what makes the data-bound part of the UI update when this property changes (for .NET Developers: the equivalent of PropertyChanged).

 

  • The “showActorDetailsBirths” and “showActorDetailsDeaths” methods are the ones that will be called when the user presses on a list item and therefore will be bound to the “oniteminvoked” event. Due to the javascript’s issues with the “this” keyword”, on the class constructor, we create two new methods from those ones (prefixed with “on”) using the bind method, that have the correct context for “this”, that is the object itself, and those will be the ones that will be bound to the events.

 

  • The two lists are of “WinJS.Binding.List” type in order to provide the necessary events for the UI to be updated when items are added to them (for .NET Developers” the equivalent to ObservableCollection).

 

Now just after the aforementioned class definition, we create from it a new class definition as follows:

 

var BindableHomePageViewModelClass = WinJS.Class.mix(HomePageViewModelClass, WinJS.Binding.mixin);

This actually uses the “WinJS.Class.mix” to add to our HomePageViewModelClass class all methods and properties that are contained in the “WinJS.Binding.mixin” class and guess what, those are the methods needed for providing change notifications of the data-binding (this is the source of the notify method). This also means that we should never use the HomePageViewModelClass but instead always use the BindableHomePageViewModelClass since this is the “complete” one after the application of the mix method.

 

Now we make our ViewModel public in the “ProgwareOrg” namespace as follows creating a new object. This is the object that will be bound to the view:

 

WinJS.Namespace.define("ProgwareOrg", {
HomePageViewModel: new BindableHomePageViewModelClass()
});

In the page’s functions that handle the basic events of our page we can bind the ViewModel to the View as follows (for .NET Developers: this code should be considered as the xaml.cs file and the binding to the ViewModel that occurs there):

 

WinJS.UI.Pages.define("/html/homePage.html", {
init: function init(element, options) {

var calendar = new Windows.Globalization.Calendar();
ProgwareOrg.HomePageViewModel.today = calendar.dayOfWeekAsString() + " " +

calendar.day + " " + calendar.monthAsString() + " " + calendar.yearAsString();
ProgwareOrg.HomePageViewModel.getBirths();
ProgwareOrg.HomePageViewModel.getDeaths();
},
ready: function ready(element, options) {
WinJS.Binding.processAll(home, ProgwareOrg.HomePageViewModel);
}
});


We initialize our ViewModel and in the ready function we bind it to the view via the “WinJS.Binding.ProcessAll” method (for .NET Developers: this would be the this.DataContext=ViewModel in XAML). This method takes as first parameter the root element where the ViewModel is applied and in our case is the one with the id=”home”.

 

The binding in the view is as follows:

 

<div class="homepage" id="home">
<section aria-label="Main content" role="main">
<span id="dateSpan" data-win-bind="innerText:today"></span>&nbsp;&nbsp;
<span id="downloadingSpan" data-win-bind="innerText:downloading"></span>
<section class="listsContainer">
(...)
<div id="birthsListElement"
data-win-control="WinJS.UI.ListView"
data-win-options="{itemDataSource:ProgwareOrg.HomePageViewModel.birthsList.dataSource,
itemTemplate:select('#template'),
layout:{type:WinJS.UI.ListLayout},
oniteminvoked : ProgwareOrg.HomePageViewModel.onShowActorDetailsBirths}"
>
</div>
<div id="deathsListElement" (...)></div>
</section>
</section>
</div>

First note that the top-level element (the one used in processAll) is the id=”home” element. Also note the “data-win-bind”  attributes that provide the binding for the HTML elements.

 

For the two ListViews note the following:

 

The itemDataSource is bound to our ViewModel but it is using the full qualified name. This means that it does not take into consideration the processAll method. I do not know why this happens and I think that this is something that needs to be fixed but for now the hack I found is that for the controls of WinJS for binding with the ViewModel we need to use the full access paths of our ViewModel. This also applies to the binding of the oniteminvoked event handler. The template set is defined in the page just above this code and not displayed here for simplicity.

 

And this summarizes the way the ViewModel can be bound to our view. The ViewModel for the actorDetails page is simpler:

 

(function () {
"use strict";

var ActoDetailViewModelClass = WinJS.Class.define(
function () {},
{
_pageToShow: "",
pageToShow: {
get: function () {
return this._pageToShow;
},
set: function (value) {
this._pageToShow = value;
this.notify("pageToShow", value);
}
}
}
);

var BindableActoDetailViewModelClass = WinJS.Class.mix(ActoDetailViewModelClass, WinJS.Binding.mixin);

WinJS.Namespace.define("ProgwareOrg", {
ActoDetailViewModel: new BindableActoDetailViewModelClass()
});

WinJS.UI.Pages.define("/html/actorDetail.html", {
ready: function ready(element, options) {
ProgwareOrg.ActoDetailViewModel.pageToShow = options.link;
WinJS.Binding.processAll(mainSection, ProgwareOrg.ActoDetailViewModel);
},
updateLayout: function updateLayout(element, viewState) { }
});
})();

And the view:

 

<div id="mainSection" class="actorDetail fragment">
...
<section aria-label="Main content" role="main">
<iframe id="actorsPage" data-win-bind="src:pageToShow" style="width: 100%;height: 100%" />
</section>
</div>

Data are passed between pages as the second parameter of the WinJS.Navigation.navigate("/html/actorDetail.html", item);. They can be retrieved from the navigated page through the options parameter of the ready function.

The “actorDetail” page uses an iframe to display the webpage. Because the page has ActiveX controls when you run the project from within VS you will be getting the error “JavaScript runtime error: Access is denied”.If you look at the Javascript Console you will see that the error is “Cannot load the ActiveX plug-in that has (…)” and that “Apps can't load ActiveX controls”. But if you compile and deploy in “Release” go to Windows8 start page and run the app this will not appear. This does not mean that the error disappears. It just means that in release mode the ActiveX will just don’t load which is fine with us.

 

So in this post we have seen an approach on how to create ViewModels in a single navigation application in Windows8.

Posted: Παρασκευή, 23 Μαρτίου 2012 6:43 πμ από iwannis | 2 σχόλια
Δημοσίευση στην κατηγορία: , ,
(Windows8) WinJS Basic Javascript Objects and the ViewModel pattern

When someone starts implementing small programs in Visual Studio 2011 and starts playing with the VS2011 templates for Metro applications in Javascript, he soon wonders about the differences that WinJS brings in Javascript object creation and what is the best practice of connecting the view (HTML) with the model (Javascript). he second relates to the functionality that WinJS brings and is similar to other data binding libraries like for example Knockoutjs.In this blog we will see a general overview of the object and ViewModel creation patterns using only WinJS via the implementation of a simple “Metro Style” application.

 

Please note that due to the lack of complete documentation for the WinJS library and its workings, some of the statements below are my assumptions and may not reflect 100% the reality. Of course every single line of code below is tested and works but bear in mind that there may be a better way of doing this and I will definitely keep researching for it.

 

How do I try the examples in this post?

If you do not have Windows8 – VS 2011 installed go ahead and download the Consumer Preview from here, then follow the steps given either here for running Windows8 on a VM or here (amazing and totally recommended) for running Windows8 on a virtual partition but directly on your “metal”. Then you may install VS 2011 Express which comes along with Expression Blend from the files downloaded from here.

 

How do I define classes with properties and fields in WinJS?

Properties are object variables that have setters and getters. Fields are object variables that do not have getters and setter. It is also preferable to define classes within namespaces to avoid naming collisions with other variables of other libraries. Let us define within the namespace “Progware”, a class named “DemoClass” with two public fields “string1”, “string2”, a public property “number” and a private field “_number”. We will be using WinJS.Namespace.define for the namespace definition and WinJS.Class.define for the class definition. To implement this class with its namespace, within a file named “DemoClass.js” we define a self executing function as follows:

 

(function () {
"use strict";

WinJS.Namespace.define("Progware", {
DemoClass: WinJS.Class.define(
function (string1, string2,number) {


this.string1 = string1;
this.string2 = string2;
this.number = number;
}
, {

string1: "",
string2: undefined,


number: {
set: function (value) {
if (isNaN(value) || value < 0)
throw new Error("Invalid number");
this._number = value;
},
get: function () {
return this._number;
}
},
incrementCool: function () {
this._privateIncrementCool();
},
getCoolValue: function () {
return Progware.DemoClass.staticPropertyNumber;
},


_privateIncrementCool:function(){
Progware.DemoClass.staticPropertyNumber++;
}

},


{
staticPropertyNumber: 1
}),
namespaceNumberVariable: 55
});
})();

WinJS.Namespace.define requires two parameters: The namespace name (Progware) and a list of the namespace’s classes, methods and/or variables. In this namespace a “namespaceNumberVariable” variable is declared (ie a global variable that can be referenced from anywhere in your code using the namepsace’s prefix – “Progware.namespaceNumberVariable”) and also a class is declared using the WinJS.Class.define method.

 

The WinJS.Class.define method requires 3 parameters: a function to act as the constructor of the class, a list of instance members of the class (those are the normal properties, fields, methods of each object of this class ) and a list of static members which are the equivalent of the properties, fields and methods declared as static in .NET and can be referenced from everywhere with the prefix of the namespace and the name of the class (in this example “staticPropertyNumber” is a static field and can be referenced from everywhere in the application using the “Progware.DemoClass.staticPropertyNumber” name).

 

The constructor of the class initializes the properties and fields. Note here that just the process of initializing a property on the constructor adds it to the list of properties of the class without having to declare it later. Those are the merits (and fallacies) of the loosely typed world! It is generally though good practice to declare them also in the appropriate place (second parameter) for “code consistency”.  Also note the number property and the way its setter and getter is defined. They both use a “private” field “_number” that is implicitly defined just by its use.  Of course there is no such thing as privates in Javascript but in our case just prefixing a field with the underscore “_” makes the field not enumerable and it also hides it from VS2011 intellisense (this is the IDE actually enforces a missing feature of the language which is also pretty handy). The same applies for the private method “_privateIncrementCool”. Also note how the classe’s methods manipulate the static field “staticPropertyNumber” and the naming convention they use to reference it.

 

In general, in the code above you have a full blown namespace with its global variables and its classes (with public, private properties, fields and methods). This I dare to say is the equivalent .cs file we would write for a class in C# apart from the namespace variables which cannot exist in .NET.

 

How do I create a ViewModel following the MVVM pattern in WinJS?

Now suppose you want to obey the MVVM principle in WinJS. That is you want to create a JavaScript class that implements all the view’s  functionality and data and bind that class to the view (that is the html page that displays the data and reacts to user events). The requirements for our simple example are as follows: We need to create a “DemoClass” object and display its contents. When a user click a button named “Add Prefix” we want to prefix the current value of the “string1” property of the class with the letter “A”. Here is a snapshot of the result:

 

image

 

Create a new Javascript/Blank Application project in VS 2011. You get a blank application with some primitive structure. In the “js” folder create a “DemoClass.js” file with the code mentioned above. This file defines your “DemoClass” class. Now go to your “default.html” page and write your DIVs for displaying the data and also implement a BUTTON so that your view reflects the image above.

 

Where do I put the JavaScript code to display the “DemoClass” object data to the view?

The first answer is everywhere you like! You can use the “default.html” itself if you like. It is pure plain JavaScript and the HTML world! Of course you need to make sure that the DOM is ready using well-known techniques. There is though a better suited space in Metro style application you can put your code where you are sure that your DOM will be ready. In the “default.js” file created for you you have the “app.onactivated” event that will be called when your app initializes. At that place the initial if checks to see whether your application is activated from a “terminated” state, that is it was not running before (more of this in a future post). Within that you can be sure that the DOM is ready and the “DemoClass" has been initialized. You first approach to display the data can be something like the following:

 

var class1 = new Progware.DemoClass("STRING1", "STRING2", 14);
document.querySelector(".string1Direct").innerText = class1.string1;
document.querySelector(".string2Direct").innerText = class1.string2;
document.getElementsByClassName("numberDirect")[0].innerText = class1.number;

 

That is, you create your “class1” object and then you either use WinJS’s querySelector (a structure that resembles the way you would query for DOM elements using JQuery) or the more traditional getElementsByClassName or getElementById to assign to the appropriate DOM elements the “class1”’s values.

 

All is good with that but you need to know that with this approach you make your code aware of the view (it has to know the id and class names of the HTML Page) which violates the separation we are trying to achieve with the MVVM pattern. The second approach described below solves this issue and brings you closer to the ViewModel pattern.

 

You initialize again the “class1” object but this time your view has the “data-win-bind” properties pointing the properties of the “class1” object:

 

<div id="boundDiv" style="margin-bottom:10px">
string1: <span data-win-bind="innerText: string1" style="color:green"></span><br/>
string2: <span data-win-bind="innerText: string2" style="color:green"></span><br />
number: <span data-win-bind="innerText: number" style="color:green"></span><br />
</div>

Now in the same place as before (the app.onactivated event) we initialize our object and then call WinJS.Binding.processAllfor the binding:

 

var class1 = new Progware.DemoClass("STRING1", "STRING2", 14);
var boundDiv = document.getElementById("boundDiv");
WinJS.Binding.processAll(boundDiv, class1);

 

Note that we specify the root element for our binding. All children of this element “see” the same data to which they bind (in our case class1). All is great apart from the  fact that if we change in code any of the values of string1,string2 or number, this change will not be reflected to the UI. To be able to achieve this we need o make a little change to the class1 we bind as follows:

 

var class1VM = WinJS.Binding.as(class1);
WinJS.Binding.processAll(boundDiv2Way, class1VM);

Thus we use WinJS.Binding.as to get a new “observable” class named “class1VM” and the new class is the one used for the binding. Note that this new class is just a wrapper. Changes to the properties of this class will affect the properties of “class1”. The opposite does not hold.

 

The only thing left to do is provide the functionality for the button. Again a way to go is to bind something to the click event of the button element as follows:

 

document.getElementById("prefixString1NoBinding").onclick = function () {
class1VM.string1 = "A" + class1VM.string1;
}
 
This will both change the value of “class1.string1” and reflect the change in the UI. But again to use the ViewModel pattern we need a way to bind the “click event” of the button to a method in the ViewModel. Actually why won’t we implement a general ViewModel class that will has this method but it will also have the “class1” for the data:
 
(function () {
"use strict";
WinJS.Namespace.define("Progware", {
ViewModel: WinJS.Class.define(
function () {
this.class1 = new Progware.DemoClass("", "", 0);
this.onAddPrefix = this.addPrefix.bind(this);
},
{
class1: undefined,

addPrefix: function (eventObject) {
this.class1.string1 = "A" + this.class1.string1;
}
}, {}
)
});
})();

The HTML now will look like this:
 

<div id="boundDivVM" style="margin-bottom:10px">
string1: <span data-win-bind="innerText: class1.string1" style="color:green"></span><br/>
string2: <span data-win-bind="innerText: class1.string2" style="color:green"></span><br />
number: <span data-win-bind="innerText: class1.number" style="color:green"></span><br />
    <button id="prefixString1BindingVM" data-win-bind="onclick:onAddPrefix" /><br/>

</div>

 
We can actually now initialize the ViewModel in app.onactivated handler and bind it to the UI:
 
var defaultVM=new Progware.ViewModel();
defaultVM.class1 = WinJS.Binding.as(class1);
var javascriptViewModelDiv = document.getElementById("boundDivVM");
WinJS.Binding.processAll(javascriptViewModelDiv, defaultVM);

But wait a second!
 
Why the data-win-bind (onclick) refers to the onAddPrefix method and not on the addPrefix one? And what the hell is this.addPrefix.bind(this)?
 
Well, those of you who are in Javascript for some time you will know that having the handler directly reference the addPrefix method will make the “this” keyword used in it to refer to the whole window and not the object itself. The this.<function>.bind(this) sets the correct reference for the “this” keyword  order to be used from within the function and this is exactly what we need to do here (quite easy and actually really helpful). So instead of binding to “addPrefix” we bind to the method returned by “this.addPrefinx.bind(this)”.
 
This was a first approach to the ViewModel pattern in WinJS. If you need the source code please feel free to write me a message.
Posted: Κυριακή, 11 Μαρτίου 2012 4:03 μμ από iwannis | 1 σχόλια
Δημοσίευση στην κατηγορία: ,
XNA and WP7–Simple Demos to get you started!

Below you can find a series of simple demos that can give you a nice insight on the XNA’s power for WP7. All of them are original. Feel free to use them in your code as you wish. There is also a PowerPoint presentation about those demos but unfortunately it is only in Greek. So let the games begin!

 

The basics

Initializes the game and draws a simple image on the display

Sprite rotation and movement, Frame rate calculation, writing strings on the display,

Same as Demo2 but now Frame Rate calculator and bouncing sprite are implemented as game components leading to a more reusable and readable code. Now we can add more bouncing balls in an instant! Parameters are passed to game components through the use of game services

Multi-touch. Understanding where are the user’s fingers and what they do. A line is drawn and follows each finger that touches the display. The information is passed through game services to the components.

Gestures. Extending the previous demo to accelerate the ball through flicking of the display.

Accelerometer. Using the device’s accelerometer to find out device orientation and calculate g.

Saving state, using the windows phone input,sending SMS and taking snapshots from the phone’s camera from within your game!

Basic 3D drawing with axis and a pyramid with different colors.

Loading a model from a 3D modeling tool. Moving the camera with gestures.

Textures and lighting in the previous models!

 

And some more complete demos.

A simple spaceship constantly shoots laser beams to its enemy.

Creates a terrain based on a heightmap provided by a color coded bmp. You can navigate in the terrain using the drawn HUD and its implementation!

Using the Farseer physics engine to make the world bounce. Demo is the one from this linkthat I totally recommend for you to read.

 

Custom collision detection

If you want to know when two objects of your 2D world collide check out the following link.

Also check this series for a more gentle introduction to XNA.

 

The complete presentation for all of the above (in Greek)

Part of it will be presented in Hackathon 2012 for WP7.5

 

An of course the App Hub main game development page.

Finally read about the exciting new feature of integrating Silverlight and XNA in a single application .

Posted: Κυριακή, 12 Φεβρουαρίου 2012 6:16 μμ από iwannis | 2 σχόλια
Δημοσίευση στην κατηγορία:
HTML5 Client Storage. An introduction on the new cookies.

Let’s talk about cookies. In fact let’s revisit cookies and see how we use them and what nightmares they bring along. Cookies are all about client storage. They are all about storing persistent information at client side.

The syntax for creating/reading them is as follows. Imagine that we want to store client side the value 17 in a cookie named id. This is done by the following BLOCKED SCRIPT document.cookie=”id=17;expires=Mon,6 Feb 2012 12:00:00”;

When we later want to read the value of the cookie named id we need to search within document.cookie for the string “id=” and fetch the value up to the next “;” character.

Based on the previous definitions we may come up with three nice Javascript functions that make our lives a littler easier:

Creating a cookie

function SetCookie(name, value, expirationInDays) {
    var now = new Date();
    var expire = new Date();
    var newCookie = name + "=" + value;
    if (expirationInDays != null && expirationInDays != 0) {
        expire.setTime(now.getTime() + 3600000 * 24 * expirationInDays);
        newCookie += ";expires=" + expire.toGMTString();
    }
    document.cookie = newCookie;
}

Reading the value of a cookie

function ReadCookie(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for (var i = 0; i < ca.length; i++) {
        var c = caIdea;
        while (c.charAt(0) == ' ') c = c.substring(1, c.length);
        if (c.indexOf(nameEQ) == 0) {
            return c.substring(nameEQ.length, c.length);
        }
    }
}

Or of course you can use a JQuery plugin which provides an implementation for the basic operations with cookies.

Now some basic facts:

 

  • To update a cookie you just create the same cookie with the updated value.
  • If you do not define an expiration date then the cookie will expire as soon as the browser’s window is closed. This cookie is also called a session-based cookie.
  • if you want to delete a cookie then you must call SetCookie for the cookie without providing an expiration date and by setting its value to blank. As a consequence the cookie will be removed when the browser’s window is closed (so it is actually an inferred delete!)
  • Cookies persist among tabs in a browser. So storing tab critical information in the cookie may result in unwanted behavior.

 

So we need a better and easier way to create/update/delete values that we store client-side, and easier way to handle expiration (values that persist even when the browser is closed or values that they don’t). And that is exactly what HTML5 offers us through the use of the following:

 

  • sessionStorage: Equivalent to session-based cookies. Is erased when the browser window is closed but also the values are not shared among browser’s tabs.
  • localStorage: Equivalent to cookies with expiration date but does not expire.

 

The API is native to Javascript and is as follows (for the same example with the value 17 called id). For sessionStorage just replace localStorage with sessionStorage:

 

  • Create: localStorage.setItem("id",17);
  • Read: localStorage.getItem(“id”);
  • Remove: localStorage.removeItem(“id”);
  • Clear all:localStorage.clear();

 

Finally don’t forget that like cookies in those values you can even store full Javascript objects as follows where we store the object Client in sessionStorage using JSON.stringify and retrieve it with :

var Client = {
    firstName:"John",
    lastName:"Panagopoulos",
    coolFactor:10
}
function storeClient() {
    sessionStorage.setItem("client", JSON.stringify(Client));
}
function getClient() {
    var retrievedClient = JSON.parse(sessionStorage.getItem("client"));
    console.dir(retrievedClient);
}

Well this is it. Of course there are some other sophisticated methods to store stuff client-side the “HTML5” way such as Web SQL Databases or the cache but we will cover those in a future post.

Posted: Δευτέρα, 6 Φεβρουαρίου 2012 2:22 μμ από iwannis | 0 σχόλια
Δημοσίευση στην κατηγορία:
ASP.NET MVC, HTML5, CSS3, JQuery templates, IEnumerable binding, knockoutjs and offline cache in a demo. A brave new world

In one of my previous posts(appox. a year ago) I have demonstrated how to bind to IEnumerables in ASP.NET MVC. I have shown several ways of dynamically adding/removing elements from the list through the use of Javascript and then jQuery-templates. In that postI have used the traditional ASP.NET MVC literals <% %> and of course the whole site operated in HTML4 and jQuery.

 

Today a lot of things have changed. From HTML4 we are moving to HTML5, we start using CSS3 for our styles, we use Razor for our views in ASP.NET MVC and we can take advantage of the knockoutjslibrary that has managed to bring the world of MVVM patterns closer to the world of Javascript and it did it with some impressive results. Therefore, in this post we are going to re-implement the same project adopting all those new (or not so new) great technologies.

 

We need to implement a simple site where we have a list of clients with a first and last name and we need to give to our users the ability to manage that list (insert/remove/edit elements). The initial list and all changes are communicated to the server using AJAX calls. We need to make the site friendly to computer and mobile browsers and provide the maximum possible quality in terms of user experience in both environments. Finally we need our site to know when it is online, in order to inform the user and prevent any changes.

 

(Device awareness) CSS3 Styling with media-queries and other goodies

The first change is the fact that we want to differentiate the view depending on whether we look the demo from a mobile device or from our pc. Therefore we will use CSS3 media queries to change the .css file used depending on the situation detected. In the _Layout.cshtml file we add the following:

 

<link href="@Url.Content("~/Content/mobileDevice.css")" 
      rel="stylesheet" type="text/css" media="screen and (max-width:480px)" />
<link href="@Url.Content("~/Content/computer.css")" 
      rel="stylesheet" type="text/css" media="screen and (min-width:481px)" />

 

Where the important attribute is the “media” attribute which differentiates the stylesheet based on the width of the device.

 

Another element that enables us to define specifically how things will be presented on a mobile device is the viewport meta tag as follows:

 

<meta name="viewport" content="user-scalable=no,width=device-width" />

 

This says to the mobile browser that we do not want to allow the user to be able to scale the webpage with his/her fingers and also that the viewport of the browser (the width of the mobile browser) is the same as the width of the device (as opposed to the more traditional approach where the mobile browser allows us to pan and zoom). Just adding this line makes our page look more like a “mobile app” to the device’s browser.

 

We also want to use a specific kind of fonts (Segoe) that are not the “standard” and therefore need to be embedded to the page. We can do that with CSS3 starting by finding the .ttf file we need from our computer and submitting that to the fontsquillerpage in order to get the font files in various formats recognized by most browsers and the .css definitions of our new font. We get the files, we put them in a special “Fonts” folder in our page and include a reference to the .css file holding their definitions (newFonts.css file in our project). Below is a screenshot of the website’s home page as seen in a browser more than 480px wide and in a browser less that 480px wide with the embedded fonts:


 

Capture2    Capture1


Note the new fonts achieved as previously mentioned and the rounded corners of the links in the mobile version. Those are achieved by the new elements in css as follows combined with the advanced selectors in CSS3 (in specific those ones apply the border rounded corner rules only to the first and last li elements of the unordered list (ul) that holds the navigation:

 

<nav>
    <ul>
        <li>@Html.ActionLink("jump to the demo","Simple","Clients")</li>
        <li>@Html.ActionLink("about","About","Home")</li>
    </ul>
</nav>

 

and the CSS applying the rounded borders:

 

nav ul li:first-child a 
{
    -webkit-border-top-left-radius: 8px; 
    -webkit-border-top-right-radius: 8px; 
    border-top-right-radius: 8px; 
    border-top-left-radius: 8px; 
    -moz-border-top-right-radius: 8px; 
    -moz-border-top-left-radius: 8px;
}
nav ul li:last-child a 
{
    -webkit-border-bottom-left-radius: 8px; 
    -webkit-border-bottom-right-radius: 8px; 
    border-bottom-right-radius: 8px; 
    border-bottom-left-radius: 8px; 
    -moz-border-bottom-right-radius: 8px; 
    -moz-border-bottom-left-radius: 8px;
}

 

We have also applied some shadow to the header of the mobile version with: text-shadow:1px 1px #fff; Also note the new semantic markup for HTML5. The “nav” element indicates that there is a site navigation set of links in this part of the webpage. The same difference in styling is applied also to the “demo” page as shown in the images below":


image     image


Again the two different stylesheets have definitions that achieve the differentiation.

 

(Easier unobtrusive Javascript) Data binding with knockoutjs and jQuery templates

And now we move on to the UI in terms of the client’s list. The methods shown in the previous postare all nice but they rely on a page “POST” to save the values and a page “GET” to get the values from the controller’s actions. We want to turn the page fully AJAX based and provide the maximum quality of user experience. For starters, let us imagine that we have “magically” received the list of clients and simulate this by adding in the page’s JavaScript the following list:

 

var clientsList = [{ id :1, FirstName: 'Ioannis', LastName: 'Panagopoulos' },                   
                   { id: 2, FirstName: 'Kostas', LastName: 'Papadopoulos' },                   
                   { id: 3, FirstName: 'Petros', LastName: 'Georgiadis' },                   
                   { id: 4, FirstName: 'Maria', LastName: 'Apostolou' }];

 

This is hardwired and will be later substituted with an AJAX call. To use knockoutjsand jQuery templateswe need to download and include in the _Layout.cshtml file the following:

 

<script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.tmpl.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/knockout-1.2.1.js")" type="text/javascript"></script>

 

The first step is to define an element in the page where the list will be displayed:

 

<section id="clientsList" data-bind='template: "clientTemplate"'></section>

 

The data-bind attribute is called a custom data attribute in HTML5. Custom data attributes are all attributes prefixed with “data-“. After the “-“ you can put whatever you like. HTML5 defines that custom data attributes are to be used to assist the programmer in any way (meaning that the word after the – may be anything) in developing the page. We know that knockoutjs searches for the data-bind custom data attribute to do its magic. In the previous declaration we tell through the custom data attribute that within the “clientsList” section (section is another HTNL5 element, it could easily be a div in this case) we want to render a jQuery template named “clientTemplate”. This template is as follows:

 

<script type="text/html" id="clientTemplate">    
    {{each(i,client) clients}}
    <div id="Clientidx">
        <input class="clientNameField" data-bind="value: FirstName" />
        <input class="clientNameField" data-bind="value: LastName"  />
        <span class="removeButton" data-bind="click: function(){ removeClient(client) }">x</span>
    </div>
    {{/each}}
</script>

 

This template says that we need to iterate a list named “clients” consisting of objects which we will call “client” (the name is just a way to have a reference to the object in each iteration). For each object, we need an input element to present the value of its FirstName property and an input element for the value of its LastName property. Finally for each object an “x” will appear that has a handler to be executed on its click event. The handler says that we need to call the function removeClient passing as argument the object of “x”’s line.

 

In another place of our code we need to be showing the total number of clients in the list:

 

<h1>clients list (<span data-bind="text: clients().length">&nbsp;</span>)</h1>
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

 

Where we bind to the total number of elements in the clients list. And in another place we have the following:

 

<button class="defaultButton" data-bind="click: addClient">add a client</button>
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

 

So the template finds the template definition, FirstName and LastName find their object within the clients list but who supplies the clients list and the removeClient and addClient methods? Well those are supplied by an object we call ViewModel and is defined as follows:

 

var ViewModel = {
            clients: ko.observableArray(clientsList),
            removeClient: function (clientToRemove) {
                ViewModel.clients.remove(clientToRemove);
            },
            addClient: function () {
                ViewModel.clients.push({id:-1, FirstName: "", LastName: ""});             
            }
        };
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

 

In other words, the ViewModel holds everything our UI has in terms of functionality and data. The ko.observableArray that is used makes the array be able to notify about its changes to every element attached to its properties (including the one we defined showing the total number of clients in the list). This makes it possible for the dynamic change of the number of clients reported whenever we press “add client”. This is the equivalent to INotifyPropertyChanged! The final step is to attach the ViewModel to the UI:

 

$(document).ready(function () {ko.applyBindings(ViewModel);});
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

 

and all the bindings find their way within the ViewModel. To complete our example we need to be able to get this information from an ASP.NET MVC Controller and submit the results to one through AJAX calls. Provided that we implement a controller to get all the clients as follows:

 

public JsonResult GetClients()
{
    List<Client> Clients = new List<Client>();
    _populateClientsList(Clients);
    return Json(Clients,JsonRequestBehavior.AllowGet);
}
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

 

The JavaScript is changed to get the client’s list as follows:

 

$(document).ready(function () {
    $.getJSON("@Url.Action("GetClients","Clients")", null, clientsReceived);
});
function clientsReceived(res) {
    ViewModel.clients = ko.observableArray(res);
    ko.applyBindings(ViewModel);
}
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

 

(there is no need anymore for the clientsList)

 

The same applies for posting the results back to the server when the user has finished editing the list we call:

 

saveClientsList: function () {
    $("#ajaxCallWait").toggle();
        $.post("@Url.Action("SaveClients","Clients")", $.toDictionary({ Clients: ko.toJS(ViewModel.clients) }), 
                function (data) {
                   $("#ajaxCallWait").toggle();
                   alert(data.message);
                })
}
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

 

A few things to note here. First we use the ko.toJS function to get the “raw” list without the ko.ObservableArray embelishments. Second we use a wonderful plugin from here(toDictionary) to enable the correct generation of the elements required for binding with the ASP.NET MVC controller. The controller now is as follows:

 

[HttpPost]
public JsonResult SaveClients(IEnumerable<Client> Clients)
{
    //Your saving logic here
    return Json(new { result = "success",
                      message = String.Format("{0} clients received",Clients.Count()) });
}
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

 

So this is it! We have managed to bind everything with considerable few lines of code compared to what we have achieved.

 

Knowing when we are offline and reacting accordingly

When the user is offline he will not be able to receive any list elements but he will be still be able to add clients and press the save button. We want to prevent this by indicating with a message that the user is offline.

 

We include a cache.manifest file in our project as follows:

 

CACHE MANIFEST
CACHE:
/demo/Clients/Simple
/demo/Scripts/knockout-1.2.1.js
/demo/Scripts/jquery-1.5.1.min.js
/demo/Scripts/jquery-toDictionary.js
/demo/Scripts/jquery.tmpl.js
/demo/Content/computer.css
/demo/Content/mobileDevice.css
/demo/Content/newFonts.css
FALLBACK:
/demo/Scripts/online.js /demo/Scripts/offline.js
NETWORK:
*
#version 1

 

This says that whatever is below the CACHE: should be stored locally, everything else should be fetched from the network (NETWORK: *) and if the browser cannot reach the online.js file (meaning that there is no internet connection), the browser should use the offline.js file that is automatically cached for offline use.

 

The online.js file has only: var online=true; inside while the offline file has only: var online=false; inside. Our webpage includes only online.js as follows (we DO NOT include the offline.js):

 

<script src="@Url.Content("~/Scripts/online.js")" type="text/javascript"></script>

 

and before performing the initial get request for the clients we add:

 

$(document).ready(function () {
        if (!online) {
                alert("Sorry but you are offline!");
                return;
        }
        $.getJSON("@Url.Action("GetClients","Clients")", null, clientsReceived);
});

 

The trick is that when online online.js will set the online variable to true while when offline the online.js file will be substituted with the offline.js file and the online variable will be false. Note that when you use the cache manifest you need to have the complete path for your files. In my case I have deployed the site in a subfolder named demo. Also note that if you have a single mistake or a missing file or a wrong path in the cache.manifest, then the whole file is not parsed. You generally need fiddlerto debug this correctly where you see what is wrong.

 

Well this is it! The complete makeover of an HTML4 page to HTML5. Hope you have enjoyed it!

 

You may download the project

Posted: Παρασκευή, 16 Δεκεμβρίου 2011 6:08 μμ από iwannis | 2 σχόλια
Δημοσίευση στην κατηγορία: ,
ITProDevConnections 2011 HTML5 Presentation Material (in greek)

 

 

Ευχαριστούμε όλους εσάς που ήρθατε και μας τιμήσατε (την Ισαβέλλα και εμένα) στην παρουσίαση "HTML5 Real Live Conversations" στο πλαίσιο του σεμιναρίου ITProDevConnections 2011. Στους παρακάτω συνδέσμους το υλικό της παρουσίασης (μέσα στην εβδομάδα τα sites θα ανανεωθούν με περισσότερο περιεχόμενο που θα ανακοινωθεί από το blog):

 

Παρουσίαση (.pdf)

HTML5Demos site (θα εμπλουτιστεί και άλλο μέσα στην εβδομάδα)

Weekend Deals site (HTML4)

Weelend Deals site (HTML5 - ημιτελές θα ολοκληρωθεί μέσα στην εβδομάδα)

 

Και ραντεβού του χρόνου ξανά στο ITPro ή στο μεταξύ ή σε κάποιο AskADev ή σε κάποιο LiveMeeting!

 

Στη διάθεσή σας για οποιοδήποτε σχόλιο/ερώτηση μέσα από αυτό το post ή το email ipplos_at_gmail_dot_com.

A scripting language for your (web)app with DLR or Roslyn

Well, this subject always excited me! The fact that you can provide at your executable, a programming language (script) that the user can use to interact with your application is something amazing. In this post, we see how this is possible by using the Dynamic Language Runtime (DLR) and IronPython, and then see whether the services provided by the Roslyn project can help as achieve the same result with C#.

The whole idea behind providing a scripting language at runtime may find the following three applications:

 

  • You implement a DSL (Domain Specific Language) meaning that you want to provide to your end use an expressive tool to specify his behavior in a specific application domain. In this case you expose some parts of the information held in your application in the form of methods that the user can use in his scripts to achieve the desired result.
  • You want to be able to change a specific behavior without having to recompile the whole application or in the case where you use the same executable in multi-tenant scenarios.
  • You want your application’s users to have some fun by interacting with your application in ways you have never imagined.

 

We will use a typical ASP.NET MVC application for our tests. The web app consists of one Controller with the following View:

image

That is the user can write a script in the TextArea (in IronPython in this figure) and then click the “Execute” button. The server receives the code and executes it returning the result just below the “Execution” header. While the For-Loop is native to IronPython, the PrintOnWebPage statement has been added by our WebApp providing a way for the script writer to write HTML for the view.

 

Implementation with the DLR (Dynamic Language Runtime)

Download and compile the DLR from Codeplex. Then in your ASP.NET MVC project add the following references:

 

  • IronPython.dll
  • Microsoft.Dynamic.dll
  • Microsoft.Scripting.dll

 

You will find those in the Bin folder of the DLR project you have compiled in the previous step. The whole idea behind script execution is shown in the figure below:

image

An object is initialized called the Script Engine. This engine will receive the user’s script and handle its execution. The engine without anything else only recognizes the native “Python” commands and therefore it has very limited interaction with our WebApp. To change this we need to provide “libraries” in the Scope object used by the engine which contain methods that the user’s script can use. In the initial figure’s example the PrintOnWebPage method is such a method. To provide it to our user the following steps have been taken:

 

A BasicLib class has been implemented:

 

public class BasicLib
{
    public ViewDataDictionary ViewData { get; set; }

    public void PrintOnWebPage(string Content)
    {
        if (ViewData["Result"] == null)
            ViewData["Result"] = Content;
        else
            ViewData["Result"] = ViewData["Result"].ToString() + Content;

    }
}
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

 

Note that the class has a property ViewData. PrinOnWebPage uses this ViewData property to add the HTML content provided at its parameters. An object of this class, will be instantiated, its ViewData property will be given the value of the actual View’s ViewData and then it will be added to the engine’s scope with a special name (eg. BasicLib). From that point on, the PrintOnWebPage method is available to the script via the following notation: BasicLib.PrintOnWebPage.

So the whole picture is as follows. The script engine with its scope are implemented in a class like the following:

 

public class ScriptManager
{
    private ScriptEngine _engine;
    private ScriptScope _scope;

    public ScriptManager(){
        _engine = Python.CreateEngine();
        _scope = _engine.CreateScope();
    }
    public void AddLibrary(object Lib){
        _scope.SetVariable(Lib.GetType().Name,Lib);
    }
    public string RunCode(string script){
        try {_engine.Execute(script, _scope);}
        catch (Exception e) {return e.Message;}
        return "";
    }
}
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

 

The class provides a “RunCode” method where the script in the string parameter will be executed and an “AddLibraryMethod” that adds a library (like the BasicLib) to the scope. The SetVariable method that adds the library to the scope receives as second parameter the name that will be used to recognize the library in our scripts. In this case we just use the library’s type name.

 

Having this ScriptManager our Controller receives the script from the view and performs the following:

 

[HttpPost]
[ValidateInput(false)] 
public ActionResult Index(String Code)
{
    ...
    BasicLib basicLib = new BasicLib();
    basicLib.ViewData = ViewData;
    ScriptManager Mngr = new ScriptManager();
    Mngr.AddLibrary(basicLib);
    Mngr.RunCode(Code);

    return View();
}
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

 

And this is all it takes to provide a scripting language to your user’s. Not bad with so few lines of code don’t you agree?

 

Implementation with the Roslyn CTP

If you have found the previous approach exciting wait until you see this one. Roslyn is the project that puts the C# compiler at your service! It is an API that gives you access to its inner workings. This enables you to do lots of interesting stuff, one of which being the fact that you can give your users the option to use C# as their scripting language.

First you need to download and install the VS 2010 SDK and the Roslyn CTP. Then you need to add the following references to your ASP.NET MVC Application:

 

  • Roslyn.Compilers
  • Roslyn.Compilers.CSharp

 

The idea behind executing scripts written in C# is more or less the same as it is for the DLR. We again have a script engine:

 

Roslyn.Scripting.CSharp.ScriptEngine Engine = new Roslyn.Scripting.CSharp.ScriptEngine(new[] {
                           "System", this.GetType().Assembly.Location});

 

And we provide a session which is a single object whose public methods and properties will be accessible by our script. In our case:

 

BasicLib basicLib = new BasicLib();
basicLib.ViewData = ViewData;
Roslyn.Scripting.Session session = Roslyn.Scripting.Session.Create(basicLib);

 

The complete handling of C# scripting code in the Controller’s post action is given below:

 

Roslyn.Scripting.CSharp.ScriptEngine Engine = new Roslyn.Scripting.CSharp.ScriptEngine(new[] {
                           "System", this.GetType().Assembly.Location});
BasicLib basicLib = new BasicLib();
basicLib.ViewData = ViewData;
Roslyn.Scripting.Session session = Roslyn.Scripting.Session.Create(basicLib);
Engine.Execute(Code, session);
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

 

And this concludes our brief introduction into providing a scripting language to your users. The post’s project can be downloaded

Posted: Δευτέρα, 31 Οκτωβρίου 2011 1:14 μμ από iwannis | 0 σχόλια
Δημοσίευση στην κατηγορία: , , ,
Περισσότερες Δημοσιεύσεις Επόμενη »