Category Archives: English

WPF vs. GDI+ Some additional notes.

In one of my previous posts WPF vs. GDI+ I wrote about performance of WPF and how to solve this problem. After some experiments in Tesseris Pro we’ve found more improvements to solution described in previous post. The main idea is that when you are converting GDI bitmap to WPF bitmap it requires memory allocation and deceases performance. And fortunately there is solution that allows to map WPF bitmap to GDI bitmap so when we are drawing on one bitmap other bitmap is changing too, because they are located in the same memory.

First we will need some API calls. You will be able to read all description in MSDN but names of the functions are more than descriptive, if you know Win API of course 😉

[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreateFileMapping(
                IntPtr hFile, 
                IntPtr lpFileMappingAttributes, 
                uint flProtect, 
                uint dwMaximumSizeHigh,
                uint dwMaximumSizeLow,
                string lpName);

[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr MapViewOfFile(
                IntPtr hFileMappingObject,
                uint dwDesiredAccess,
                uint dwFileOffsetHigh,
                uint dwFileOffsetLow,
                uint dwNumberOfBytesToMap);

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool UnmapViewOfFile(IntPtr hFileMappingObject);

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool CloseHandle(IntPtr handle);

Than before creating bitmap let’s create memory mapped file as source of bitmaps:

var format = PixelFormats.Bgr32;

var pixelCount = (uint)(width * height * format.BitsPerPixel / 8);
var rowWidth = width * (format.BitsPerPixel / 8);

this.fileMapping = CreateFileMapping(
                       new IntPtr(-1), 
                       IntPtr.Zero, 
                       0x04, 
                       0, 
                       pixelCount, 
                       null);

this.mapView = MapViewOfFile(
                       fileMapping, 
                       0xF001F, 
                       0, 
                       0, 
                       pixelCount);

When we are calling CreateFileMapping with new IntPtr(-1) as first parameter windows doesn’t map some file to memory but will use system page file as source of mapping. And of course in this case we should specify size of file with width * height * format.BitsPerPixel / 8.

Now let’s create two bitmaps mapped to this mapped file:

this.bitmap = new System.Drawing.Bitmap(
              width, 
              height,
              rowWidth,
              System.Drawing.Imaging.PixelFormat.Format32bppPArgb,
              this.mapView);

this.image = (System.Windows.Interop.InteropBitmap)
  System.Windows.Interop.Imaging.CreateBitmapSourceFromMemorySection(
                                         fileMapping, 
                                         width, 
                                         height, 
                                         format, 
                                         rowWidth, 
                                         0);

Now you can in OnRender you can use following code:

protected override void OnRender(DrawingContext dc)
{
   // Ensure that bitmap is initialized and has correct size
   // Recreate bitmap ONLY when size is changed
   InitializeBitmap((int)this.width, (int)this.height);

   //TODO: Put here your drawing code

   // Invalidate and draw bitmap on WPF DrawingContext
   this.image.Invalidate();
   dc.DrawImage(
           this.image, 
           new Rect(0, 0, this.bitmap.Width, this.bitmap.Height));
}

Please note than this.image should be of type System.Windows.Interop.InteropBitmap to call Invalidate method. And don’t forget to call UnmapViewOfFile and CloseHandle.

Fornt-end with Knockout.js, require.js and TypeScript

Let’s talk about how to correctly organize front-end with Knockout.js require.js and TypeScript.

The problem

If we will read TypeScript handbook we will find a lot information about how to load modules with AMD and require.js, and everywhere in samples we will find something like this

    import module=require('./module');

But in real application we always have some folder structure to keep the files organized, we are using different package managers and so on, thus in most cases import should look like

    import ko=require('./node_modules/knockout/build/output/knockout-latest')

Unfortunately for some unknown reason this is not working with TypeScript, at least with versions 1.3 and 1.4. Really, why current folder path is working but more complex path is not? We have to deal somehow with this.

An the only way is to use import ko=require(knockout) instead of full path to knockout.

In this post I will describe the way how to build HTML application with MS VisualStudio and I will use node package manger to load all the libraries, but the same idea will work for nuget or any other package managed and IDE.

Application structure

  • node_modules
    • knockout
      • build
        • output
          • knockout-latest.js
    • requirejs
      • require.js
    • moment
      • moment.js
  • typings
    • knockout
      • knockout.d.ts
    • moment
      • moment.d.ts
  • config.js
  • application.ts
  • mainViewmodel.ts
  • bindings.ts
  • index.html

Require.js enabled JavaScript (or TypeScript) application should start with single “ tag in html. In our case it looks like:

    <script data-main='config.js' src='node_modules/requirejs/require.js'></script>

This config.js is the only JavaScript file, all other logic is done in TypeScript. May be there is some way to write it on TypeScript, but I’m not sure that it makes any sense, because you have to do JS specific low level things here. The config.js looks like following:

    require.config({
        baseUrl: "",
        paths: {
            knockout: "./node_modules/knockout/build/output/knockout-latest",
            moment: "./node_modules/moment/moment"
        }
    });

    define(["require", "exports", 'application'], function (require, exports, app) {
        app.Application.instance = new app.Application();
    });

First of all in this file we are configuring require.js to make it understand where to search for libraries. We will load our index.html from file system and of course in real app you should not use folder structure but think about URLs. Please note that you should not specify file extension.

Now require.js will understand how to load knockout. But this will tell nothing our TypeScript compiler and compiler will report errors about undefined module.

To fix this problem with compiler simply add corresponding typings to the project. Now TypeScript will build everything without errors. Please note that in this case TypeScript will not verify correctness of path to modules because it can’t determine the real URL structure of the application. That may be the reason why complex path is not working in import.

Note: don’t forget to switch TypeScript module type to AMD (Asynchronous Module Definition). This will conflict with node.js and next time I will explain how to deal with node.js and AMD.

Application startup

Our application entry point (after config.js) is application.ts file with following content:

    import vm = require('mainViewModel');
    import ko = require('knockout');
    import bindings = require('bindings');

    export class Application{
        public static instance: Application;

        constructor(){
            bindings.register();
            ko.applyBindings(new vm.mainViewModel());
        }
    }

Here we load module(s) (as dependency) with all custom bindings, create main view model and apply it to whole page.

Note that we don’t need to specify path to bindings and mainViewModel in config.js because they are located at the same directory. You can use more complex structure and everything will work with TypeScript just don’t forget to explain require.js how to find all your modules.

Custom bindings

Custom binding are wrapped in single module and can be loaded as any other module. Binding handlers will be registered with bindings.register() call. This can be done with following content of bindings.ts:

    import ko = require("knockout")
    import moment = require("moment")

    export function register(): void {

        ko.expressionRewriting["_twoWayBindings"].datevalue = true;

        var formatValue = function (value, format) {
            format = ko.unwrap(format);
            if (format == null) {
                format = "DD.MM.YYYY";
            }
            return moment(ko.unwrap(value).toString()).format(format);
        }

        ko.bindingHandlers["datevalue"] = {
            init: function (element: HTMLInputElement, valueAccessor, allBindings, viewModel) {
                element.value = formatValue(valueAccessor(), allBindings.get("dateFormat"));

                element.addEventListener("change", function (event) {
                    var dateValue: any
                        = moment(element.value, ko.unwrap(allBindings.get("dateFormat")))
                            .format("YYYY-MM-DD") + "T00:00:00";

                    if (ko.unwrap(valueAccessor()) instanceof Date) {
                        dateValue = new Date(dateValue);
                    }

                    if (ko.isObservable(valueAccessor())) {
                        valueAccessor()(dateValue);
                    }
                    else {
                        allBindings()._ko_property_writers.datevalue(dateValue);
                    }
                });
            },
            update: function (element: HTMLInputElement, valueAccessor, allBindings) {
                element.value = formatValue(valueAccessor(), allBindings.get("dateFormat"));
            }
        }
    }

Here we create very useful datevalue binding, which allows to edit and display dates as string in specific format. This binding is able to work with observables and flat values and store date in JSON compatible format or Date, depending on initial value of bound property. This binding contains some knockout and TypeScript tricks like ko.expressionRewriting["_twoWayBindings"].datevalue = true and allBindings()._ko_property_writers.datevalue(dateValue) but let’s talk in next blog posts about these tricks.

ViewModel

Nothing special just usual view model organized as module

    import ko = require('knockout');

    export class mainViewModel{

        constructor(){
        }

        public name = ko.observable("John Doe");
        public birthday = ko.observable("1983-01-01");
    }

Conclusion

Everybody are waiting for ECMASript 6 support in all browsers with all sweet things like classes, arrows, modules and so on. Life is too short to wait – let’s use TypeScript today! I’ve tested it in big project and yes sometime it looks a little raw but it’s working and make our life easier with type check and better intellisense.

Knockout.js components. What they are and what they are not

What are components?

Some time ago Knockout.js team released new feature – components. This feature allows developer to build some custom components that will have it’s own view and logic. Registration of component looks almost like binding registration

ko.components.register('mywidget', {
    viewModel: function(params) {
        //Define view model here
        this.title = ko.observable("Hello from component!!!");
    },
    template: '<div data-bind="text: title"></div>'
});

The example below looks very similar to definition of user control in technologies like WPF/Silverlight or even WinForms. We have template to define view of element and view-model to define logic.

Most interesting (for me personally) is usage of these components as custom elements – custom HTML tags. after registrations of my widget in previous examaple you can write following in your HTML code:

<mywidget></mywidget>

Brief description (skip it if you already familiar with components)

And this HTML tag will be replaced with template of the component with applied component view model.

Template can be defined in following way:

  • With existing element id. Template element can be any existing element div or template or anything else.
template: { element: 'my-component-template'}

Element content (only children of element) will be cloned to place where you apply your custom element

  • With exiting element instance
template: { element: getElementById('...') }
  • Directly with string of markup
template: '<div data-bind="text: title"></div>'
  • With array of element instances (elements will be add sequentially)

  • With AMD (Asynchronous Module Definition)

template: { require: 'text!some-template.html' }

Require.js or any other AMD module loader can be used. See https://github.com/amdjs/amdjs-api/blob/master/AMD.md for details.

For view-model configuration you can use following:

  • Constructor function
viewModel: function(params) {
    //Define view model here
    this.title = ko.observable("Hello from component!!!");
}
  • Existing instance of view model
viewModel: { instance: viewModelInstance }
  • Factory function
viewModel: {
              createViewModel: function(params, componentInfo) { 
                                  return new ViewModel(params); 
                               }
           }

Here we have additional parameter componentInfo. This parameter allow us to get access to our custom element with componentInfo.element. But unfortunately we can’t get access to this element before template is applied and analyze it as it was initially added to the document. I’ll describe why I’ve said unfortunately a little later

  • Load view model through AMD
viewModel: { require: 'some/module/name' }
  • Specify whole the component as single AMD module
define(['knockout'], function(ko) {
    return {
        viewModel: function(params) {
           this.title = ko.observable("Hello from component!!!");
        },
        template: '<div data-bind="text: title"></div>'
    };
});

And register it with

ko.components.register('my-component', { require: 'some/module' });

What components are not?

Let’s assume we would like to build a component for bootstrap button with popover. And we would like to open this popover when button is clicked and when another button inside popover is clicked we would like to call some handler in view-model. Something like button with confirmation. And we would like to add custom confirmation template with elements bound to view model.

donate-btn

It would be nice to have component with following syntax

<popover text="Donate" 
		 data-bind="command: makeDonation"
		 title="Enter amount of donation">
	<input class='form-control text-right' type='text' 
               data-bind='value: donationAmount' />
</popover>

But unfortunately it’s not possible. There is no way to read HTML content of the component applied as custom HTML tag, because everything view-model factory, view-model constructor and all other functions are called when template is applied to component and template is required parameter.
Thus you can’t build custom controls with templates inside. Only one possible option is to specify template id as parameter of the your custom control.

<template id='donate-template'>
    <input class='form-control text-right' type='text' 
           data-bind='value: donationAmount' />
</template>

<popover text="Donate" 
		 title="Enter amount of donation" 
		 data-bind="command: makeDonation" 
		 template="donate-template"></popover>

Or use usual binding instead of component to specify template control

<div class="btn btn-xs btn-primary">
   <div data-bind="popover: {title:'Enter ammount', command: makeDonation}"
                   class="hidden">
	 <input class='form-control text-right' type='text' 
                data-bind='value: donationAmount' />
   </div>
   Donate
</div>

More or less equivalent code but imagine how useful this “inline templateing” can be for controls like this http://grid.tesseris.com/Home/Documentation#!/General/general

Let’s hope for the future versions…