DESCRIPTION


The WijTree widget support different types of datasources and is pretty flexible to work with any of them. An XML structure is one of the commonly used data structure popular among developers. Similarly KnockoutJS is also in trend these days since it helps you to create rich, responsive display and editor user interfaces with a clean underlying data model.

So in this blog we will try to incorporate both these scenarios and see how we can create a WijTree structure out of it. This is what we will end up with.


IMPLEMENTATION


Let's take a look on what all things we need to set up in order to get it working. The first thing obviously needed is an XML file to be used as the datasource. We will take care that the XML data is set up such that it can be used to create WijTree nodes. It can be found in the attached sample.

Next we will add a class which will parse the XML file and return the nodes created from it after parsing. This is how it looks like:
    public object GetProductList()
{
XmlDocument doc = new XmlDocument();
doc.Load(Server.MapPath("~/App_Data/treeview_structure.xml"));
doc.RemoveChild(doc.FirstChild);
XmlNodeList rootNodes = doc.ChildNodes;
nodes = AddNodes(rootNodes);
return nodes;
}

List nodes = new List();

public List AddNodes(XmlNodeList xmlNodeList)
{
for (int i = 0; i < xmlNodeList.Count; i++)
{
string parent = "";
if (xmlNodeList[i].ParentNode.GetType() != typeof(XmlDocument))
parent = xmlNodeList[i].ParentNode.Attributes["Text"].Value.ToString();

nodes.Add(new string[] { parent, xmlNodeList[i].Attributes["Text"].Value.ToString() });
if (xmlNodeList[i].HasChildNodes)
{
XmlNodeList newList = xmlNodeList[i].ChildNodes;
AddNodes(newList);
}
}
return nodes;
}

So this was the server side code, but the WijTree structure will be set up at the client side using Knockout. So we will perform an AJAX call to get the returned nodes from the server and then create WijTree structure using it. The code will look something like this:
   var viewModel = {
disabled: ko.observable(false),
allowTriState: ko.observable(true),
autoCheckNodes: ko.observable(true),
autoCollapse: ko.observable(true),
showCheckBoxes: ko.observable(true),
showExpandCollapse: ko.observable(true),
nodes: ko.observableArray([]),
load: function () {
$.ajax({
type: "POST",
url: "GetDetails.asmx/GetProductList",
contentType: "application/json; charset=utf-8",
success: function (result) {
var data = result.d;
var dict1 = {};
var arr = [];

$.each(data, function (i, elem) {
var d = data[i],
parent = d[0],
child = d[1];

if (parent == "") {
dict1[child] = [];
}
else {
if (!dict1[parent]) {
dict1[parent] = [];
}
dict1[parent].push(new node(child));
}
});

//add nodes to array
$.each(dict1, function (key, value) {
arr.push(new node(key, value.length ? value : null));
});
viewModel.nodes(arr);
},
error: function (e, args) {
alert('error');
}
});
}
};

//create new node
var node = function (Text, childNodes) {
return {
text: Text,
nodes: childNodes
}
}

//Bind ViewModel
$(document).ready(function () {
ko.applyBindings(viewModel, $(".container").get(0));
viewModel.load();
});

These options will be set using the HTML markup and we are done. A sample application demonstrating this implementation can be downloaded using the link below.

Download Sample