Updated the post with the XML File I had used.
I posted this article originally in March 2006 when the ASP.NET 2.0 TreeView had just been released. This article has received tremendous response (35000 views for this particular post) and also many recommendations / suggestions / corrections as comments.
The script then supported checking/unchecking of children/parents when selecting/deselecting a particular node. However, in cases of having multiple children and de-selecting one of them, the parent doesn’t automatically get un-selected. Also there seemed to be a few issues with Firefox, Safari etc.,
So the intent of this post is to publish the best working Java Script (submitted by the community) that fixes the above issues as well as support multiple browsers and provide a better way of handling the event. Special thanks to pushp_aspnet for taking the pain to make this script work across multiple browsers and multiple levels.
To begin with, create a blank new ASP.NET Website and in your web form, drag and drop a TreeView control in to the page. Also, drag and drop an XML DataSource control into your page (this can be found under “Data” tab in the Visual Studio toolbox).
Configure the DataSource to an XML File (I have pasted the XML Code at the end of this post) or any method that returns an XML from your Database etc., Bind the TreeView to the XML DataSource. Also, set the ShowCheckBox=”All” property for the TreeView. The sample code looks as below:-
<asp:TreeView ID="TreeView1" runat="server" DataSourceID="XmlDataSource1" ShowCheckBoxes="All">
</asp:TreeView>
<asp:XmlDataSource ID="XmlDataSource1" runat="server" DataFile="~/Syllabus.xml"></asp:XmlDataSource>
Note, I have set the Datafile to a physical XML file I had which has decent hierarchy of parent/child nodes. (As mentioned earlier, I have pasted this XML at the end of this post)
Just run the solution to check if your Tree renders on the page with the checkboxes as well as the node elements.
The next step is to add the TreeView attribute. In the code-behind, within the Page_Load event, add the following code:-
protected void Page_Load(object sender, EventArgs e)
{
TreeView1.Attributes.Add("onclick", "OnCheckBoxCheckChanged(event)");
}
The next step is to add the Java Script function to handle the above:-
In the ASPX Page, within the <head> </head> tags, add the following code:-
<script type="text/javascript">
function OnCheckBoxCheckChanged(evt) {
var src = window.event != window.undefined ? window.event.srcElement : evt.target;
var isChkBoxClick = (src.tagName.toLowerCase() == "input" && src.type == "checkbox");
if (isChkBoxClick) {
var parentTable = GetParentByTagName("table", src);
var nxtSibling = parentTable.nextSibling;
if (nxtSibling && nxtSibling.nodeType == 1)//check if nxt sibling is not null & is an element node
{
if (nxtSibling.tagName.toLowerCase() == "div") //if node has children
{
//check or uncheck children at all levels
CheckUncheckChildren(parentTable.nextSibling, src.checked);
}
}
//check or uncheck parents at all levels
CheckUncheckParents(src, src.checked);
}
}
function CheckUncheckChildren(childContainer, check) {
var childChkBoxes = childContainer.getElementsByTagName("input");
var childChkBoxCount = childChkBoxes.length;
for (var i = 0; i < childChkBoxCount; i++) {
childChkBoxes[i].checked = check;
}
}
function CheckUncheckParents(srcChild, check) {
var parentDiv = GetParentByTagName("div", srcChild);
var parentNodeTable = parentDiv.previousSibling;
if (parentNodeTable) {
var checkUncheckSwitch;
if (check) //checkbox checked
{
var isAllSiblingsChecked = AreAllSiblingsChecked(srcChild);
if (isAllSiblingsChecked)
checkUncheckSwitch = true;
else
return; //do not need to check parent if any(one or more) child not checked
}
else //checkbox unchecked
{
checkUncheckSwitch = false;
}
var inpElemsInParentTable = parentNodeTable.getElementsByTagName("input");
if (inpElemsInParentTable.length > 0) {
var parentNodeChkBox = inpElemsInParentTable[0];
parentNodeChkBox.checked = checkUncheckSwitch;
//do the same recursively
CheckUncheckParents(parentNodeChkBox, checkUncheckSwitch);
}
}
}
function AreAllSiblingsChecked(chkBox) {
var parentDiv = GetParentByTagName("div", chkBox);
var childCount = parentDiv.childNodes.length;
for (var i = 0; i < childCount; i++) {
if (parentDiv.childNodes[i].nodeType == 1) //check if the child node is an element node
{
if (parentDiv.childNodes[i].tagName.toLowerCase() == "table") {
var prevChkBox = parentDiv.childNodes[i].getElementsByTagName("input")[0];
//if any of sibling nodes are not checked, return false
if (!prevChkBox.checked) {
return false;
}
}
}
}
return true;
}
//utility function to get the container of an element by tagname
function GetParentByTagName(parentTagName, childElementObj) {
var parent = childElementObj.parentNode;
while (parent.tagName.toLowerCase() != parentTagName.toLowerCase()) {
parent = parent.parentNode;
}
return parent;
}
</script>
The above code should work fine when you run and try selecting/de-selecting nodes and the parent behaviors etc.,
When I last checked, it works with IE8 Beta 2, Firefox 3.0.5 & Safari 3.2.1
The link for my original post View Entry
The ASP.NET Forum where this is being discussed with various options http://forums.asp.net/t/976122.aspx?PageIndex=1
The sample XML File content is here below:-
<?xml version="1.0" encoding="utf-8" ?>
<Syllabus>
<Classes>
<Class>XII Standard</Class>
<Subjects>
<Subject>Physics</Subject>
<chapters>
<chapter>Chapter 1</chapter>
<Description>This is Chapter 1 in Physics</Description>
</chapters>
<chapters>
<chapter>Chapter 2</chapter>
<Description>This is Chapter 2 in Physics</Description>
</chapters>
<chapters>
<chapter>Chapter 3</chapter>
<Description>This is Chapter 3 in Physics</Description>
</chapters>
<chapters>
<chapter>Chapter 4</chapter>
<Description>This is Chapter 4 in Physics</Description>
</chapters>
<chapters>
<chapter>Chapter 5</chapter>
<Description>This is Chapter 5 in Physics</Description>
</chapters>
</Subjects>
<Subjects>
<Subject>Biology</Subject>
<chapters>
<chapter>Chapter 1</chapter>
<Description>This is Chapter 1 in Biology</Description>
</chapters>
<chapters>
<chapter>Chapter 2</chapter>
<Description>This is Chapter 2 in Biology</Description>
</chapters>
<chapters>
<chapter>Chapter 3</chapter>
<Description>This is Chapter 3 in Biology</Description>
</chapters>
<chapters>
<chapter>Chapter 4</chapter>
<Description>This is Chapter 4 in Biology</Description>
</chapters>
<chapters>
<chapter>Chapter 5</chapter>
<Description>This is Chapter 5 in Biology</Description>
</chapters>
</Subjects>
<Subjects>
<Subject>Chemistry</Subject>
<chapters>
<chapter>Chapter 1</chapter>
<Description>This is Chapter 1 in Chemistry</Description>
</chapters>
<chapters>
<chapter>Chapter 2</chapter>
<Description>This is Chapter 2 in Chemistry</Description>
</chapters>
<chapters>
<chapter>Chapter 3</chapter>
<Description>This is Chapter 3 in Chemistry</Description>
</chapters>
<chapters>
<chapter>Chapter 4</chapter>
<Description>This is Chapter 4 in Chemistry</Description>
</chapters>
<chapters>
<chapter>Chapter 5</chapter>
<Description>This is Chapter 5 in Chemistry</Description>
</chapters>
</Subjects>
<Subjects>
<Subject>Maths</Subject>
<chapters>
<chapter>Chapter 1</chapter>
<Description>This is Chapter 1 in Maths</Description>
</chapters>
<chapters>
<chapter>Chapter 2</chapter>
<Description>This is Chapter 2 in Maths</Description>
</chapters>
<chapters>
<chapter>Chapter 3</chapter>
<Description>This is Chapter 3 in Maths</Description>
</chapters>
<chapters>
<chapter>Chapter 4</chapter>
<Description>This is Chapter 4 in Maths</Description>
</chapters>
<chapters>
<chapter>Chapter 5</chapter>
<Description>This is Chapter 5 in Maths</Description>
</chapters>
</Subjects>
</Classes>
<Classes>
<Class>X Standard</Class>
<Subjects>
<Subject>Maths</Subject>
<chapters>
<chapter>Chapter 1</chapter>
<Description>This is Chapter 1 in Maths</Description>
</chapters>
<chapters>
<chapter>Chapter 2</chapter>
<Description>This is Chapter 2 in Maths</Description>
</chapters>
<chapters>
<chapter>Chapter 3</chapter>
<Description>This is Chapter 3 in Maths</Description>
</chapters>
<chapters>
<chapter>Chapter 4</chapter>
<Description>This is Chapter 4 in Maths</Description>
</chapters>
<chapters>
<chapter>Chapter 5</chapter>
<Description>This is Chapter 5 in Maths</Description>
</chapters>
</Subjects>
<Subjects>
<Subject>Social</Subject>
<chapters>
<chapter>Chapter 1</chapter>
<Description>This is Chapter 1 in Social</Description>
</chapters>
<chapters>
<chapter>Chapter 2</chapter>
<Description>This is Chapter 2 in Social</Description>
</chapters>
<chapters>
<chapter>Chapter 3</chapter>
<Description>This is Chapter 3 in Social</Description>
</chapters>
<chapters>
<chapter>Chapter 4</chapter>
<Description>This is Chapter 4 in Social</Description>
</chapters>
<chapters>
<chapter>Chapter 5</chapter>
<Description>This is Chapter 5 in Social</Description>
</chapters>
</Subjects>
<Subjects>
<Subject>Science</Subject>
<chapters>
<chapter>Chapter 1</chapter>
<Description>This is Chapter 1 in Science</Description>
</chapters>
<chapters>
<chapter>Chapter 2</chapter>
<Description>This is Chapter 2 in Science</Description>
</chapters>
<chapters>
<chapter>Chapter 3</chapter>
<Description>This is Chapter 3 in Science</Description>
</chapters>
<chapters>
<chapter>Chapter 4</chapter>
<Description>This is Chapter 4 in Science</Description>
</chapters>
<chapters>
<chapter>Chapter 5</chapter>
<Description>This is Chapter 5 in Science</Description>
</chapters>
</Subjects>
<Subjects>
<Subject>English</Subject>
<chapters>
<chapter>Chapter 1</chapter>
<Description>This is Chapter 1 in English</Description>
</chapters>
<chapters>
<chapter>Chapter 2</chapter>
<Description>This is Chapter 2 in English</Description>
</chapters>
<chapters>
<chapter>Chapter 3</chapter>
<Description>This is Chapter 3 in English</Description>
</chapters>
<chapters>
<chapter>Chapter 4</chapter>
<Description>This is Chapter 4 in English</Description>
</chapters>
<chapters>
<chapter>Chapter 5</chapter>
<Description>This is Chapter 5 in English</Description>
</chapters>
</Subjects>
</Classes>
</Syllabus>
Cheers !!!