WinJS.UI.ListView and its LayoutNotInitialized exception

While using WinJS.UI.ListView control and hiding/showing it together with binding/setting its datasource, it’s very possible to get the annoying exception “Layout is not initialized“.

Sample application

I developed a sampe app (after downloading just remove docx extension) where it’s possible to see when the exception is thrown.

The issue occurs in 2 cases:

  1. Given the ListView is hidden (display:none) and it is connected (via binding or JS) to empty list.
    When a new item is inserted into the datasource
    Then the ListView would like to render it but it’s necessary to measure the item size. Because of seeting “display:none” it is not possible, so mesureing fails and the exception is thrown
    Steps: check display none, click regenerate empty list, click add tile
  2. Given the ListView is hidden (display:none) and it is connected (via binding or JS) to non-empty list.
    When the items datasource is reset (via binding or JS) to some other non-empty datasource
    Then the ListView would like to render it but it’s necessary to measure the item size. Because of seeting “display:none” it is not possible, so mesureing fails and the exception is thrown
    Steps: check display none, click regenerate non-empty list

Solution

  1. using groupInfo property of layout which tells ListView: don’t measure on your own, here is the size
  2. when showing/hiding the listview we could enable/disable binding/setting the datasource

It’s possible to see both solution in the action in the downloaded application.

Summary

Solution a) is quite easy to do but it is not as performant as solution b.
Solution b) is better from the performance point of the view because when the listview is hidden and unbound, then it doesn’t receive and process any updates from datasource.

DataTemplate: solution to performance problems with WinJS Templates and binding

Problem: peformance issues with WinJS Templates and binding

WinJS Templates and Binding belongs to core parts of WinJS. Especially they fit very well into MVVM model, declarative binding, separation of concerns (UI logic contains really only UI logic)

Template rendering has the following high-level steps:

  1. optionaly create new container element which will contain a final rendered HTML – this step is optional because a result container can be passed as argument to the method)
  2. clone the template and append it into the container
  3. call WinJS.UI.processAll function on the root
  4. call WinJS.Binding.processAll function on the root and passed binding context objects (aka datacontext object)
  5. return the result

In addition, the whole process is wrapped into promises.

This process works quite well and you can achieve nice results with it. The problem starts when you try to finetune the performance. This is the slowest way of rendering item. There are several other ways which you can find in any WinJS docs/books.

WinJS Template and declarative binding is the slowest approach but the most flexible and I’d like to use it as often as possible but the performance has to be improved.

Let’s measure it!

Download MeasuringTemplatePerformance.zip and run the sample! (after downloading the file, remove extension docx, then unzip it) The sample I attached to this blog post is used to generate the color palette with the divs, using CSS3 grid layout. It does it in different ways and it measure the time spent.

Let’s review each solution.

Manual render

This is the fastest way and we will use it as our unit of measure. It’s the quickest way (at least for me) how to solve our problem. The only issue is that all UI logic (creating DOM elements, setting properties, etc) are done in codebehind, so there is NO separation of concerns.

Cloning render

It differs from manual process in the way how DOM elements are created – they are cloned form a template (do not mix it with WinJS template). In this case, the template is DOM element (acts as prototype) and we create cloned DOM element from the prototype and again, manualy set properties.
This is cca 3x slower than manual and still we violate separation of concerns.

Template, manual binding, manual placing in DOM

This approach uses WinJS template and its render method but it manually sets the properties (it doesnt use binding mechanism at all).
This is cca 7x slower than manual approach and again we violate separation of concerns.

Template, manual binding, auto placing in DOM

Similar approach as the previous case with just one difference: the result is directly added into DOM.
This is cca 11x slower then manual approach and again we violate separation of concerns.

Template, declarative binding, auto placing in DOM

This approach uses fully standard WinJS way of rendering, binding and adding the result to the DOM.
This is cca 30x slower than manual rendering but with full separation of concerns.

How to make the situation better?

The only solution is to reduce JS code to be executed. The source of the issue are two:

  1. calling WinJS.UI.processAll inside WinJS.Binding.Template.render – it could be totaly skipped as we don’t need to process any inner win controls.
  2. calling WinJS.Binding.processAll inside WinJS.Binding.Template.render – It could be rapidly enhanced. It’s overlook very often that WinJS.Binding.processAll has an optional argument called “bindingCache”. It is an object with specific interface and several usages:
    1. store all binding created during the binding process,
    2. cache parse all bindings found in the template
    3. stores all elements IDs with the bindings

Passing “bindingCache” can be reused for future binding process and it will speed up the binding process very much. Let’s see it in the action.

Template, cloning, declarative binding with binding cache, manual placing in DOM

This approach runs the binding process over the template element just to build the binding cache. Then for each data the template element is cloned and bound with support of binding cache. The difference is huge, IMHO.
This approach is slower only cca 4x than manual approach but follows separation of UI logic.

MvvmJS.UI.DataTemplate, declarative binding, auto placing in DOM

It is possible to go further and speed-up binding process with binding cache – binding process uses query selector to find all elements with data-win-bind attribute. I created a control, called MvvmJS.UI.DataTemplate which implements this logic and uses binding cache.

This approach is very simple and it’s slower only 3x than the manual approach but with full declarative binding and it wins for me. Especialy when the templates will be more complicated and it will be necessary to react on any data change.

Solution – MvvmJS.UI.DataTemplate

Usage of MvvmJS.UI.DataTemplate (UI/HTML part)

    <div id="dataTemplate">
        <div></div>
    </div>

Usage of MvvmJS.UI.DataTemplate (UI/code behind part)

                var cellTemplate = document.getElementById("dataTemplate");
                cellTemplate.winControl || WinJS.UI.processAll(cellTemplate);
                cells.forEach(function (cell) {
                    cellTemplate.winControl.render(cell, grid);
                });

DataTemplate class can be found in this project. MvvmJS project will be upgraded later (this month) with all new controls and logic.