Search This Blog

Thursday, 10 November 2011

Storing the expanded state of TreeNodes added via callback - Telerik Rad TreeView


Consider the following scenario:
  1. There is a treeview on the page
  2. The treeview is bound to a SQL database and the TreeNodes have unique values - it is important that the nodes have unique values so that the task can be achieved
  3. Tree-nodes use ExpandMode.ServerSideCallBack
  4. There is a button on the page
The following should be achieved:
When a postback appears upon a button click the expanded state of the nodes should be persisted afterwards.
Example:
ASPX
<rad:radtreeview
   
id="RadTreeView1"
   
runat="server"
   
OnNodeExpand="RadTreeView1_NodeExpand">
</
rad:radtreeview>
<
asp:Button
   
ID="Button1"
   
runat="server"
   
OnClick="Button1_Click"
   
Text="Button" />
        
C#
private DataTable GetNodeData(string query)
   {
       OleDbConnection dbCon =
 new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Server.MapPath("~/Nodes.mdb"));
       dbCon.Open();

       OleDbDataAdapter adapter =
 new OleDbDataAdapter(query, dbCon);
       DataTable dt =
 new DataTable();
       adapter.Fill(dt);
       dbCon.Close();

       
return dt;
   }

   
private void LoadRootNodes()
   {
       RadTreeView1.Nodes.Clear();
       Session.Remove(
"expandedNodes");
       DataTable dt = GetNodeData(
"SELECT * FROM Nodes WHERE ParentId IS NULL");
       
foreach (DataRow row in dt.Rows)
       {
           RadTreeNode node =
 new RadTreeNode();
           node.Text = (
string)row["Text"];
           node.Value = ((
int)row["Id"]).ToString();
           node.Category =
 "Some Category";
           node.ExpandMode = ExpandMode.ServerSideCallBack;
           RadTreeView1.Nodes.Add(node);
       }
   }

   
private void AddChildNodes(RadTreeNode node)
   {
       
string sql = "SELECT Nodes.Id AS NodeId, Nodes.Text AS NodeText, COUNT(Children.Id) AS HasChildren FROM Nodes LEFT JOIN Nodes Children ON Nodes.Id = Children.ParentId WHERE Nodes.ParentId = {0} GROUP BY Nodes.Id, Nodes.Text";

       sql = String.Format(sql, node.Value);
       DataTable dt = GetNodeData(sql);

       
foreach (DataRow row in dt.Rows)
       {
           RadTreeNode childNode =
 new RadTreeNode();
           childNode.Text = (
string)row["NodeText"];
           childNode.Value = ((
int)row["NodeId"]).ToString();
           childNode.Target =
 "_new";
           
if (((int)row["HasChildren"]) > 0)
           {
               childNode.ExpandMode = ExpandMode.ServerSideCallBack;
           }
           node.Nodes.Add(childNode);
       }
   }

   
protected void Page_Load(object sender, EventArgs e)
   {
       
if (!Page.IsPostBack && !RadTreeView1.IsCallBack)
       {
           LoadRootNodes();
           Session[
"treeViewState"] = RadTreeView1.GetXml();
       }
   }

   
protected void RadTreeView1_NodeExpand(object o, Telerik.WebControls.RadTreeNodeEventArgs e)
   {
       AddChildNodes(e.NodeClicked);

       
string treeViewState = (string) Session["treeViewState"];
       RadTreeView cachedTreeView =
 new RadTreeView();
       cachedTreeView.LoadXmlString(treeViewState);

       
//it is important that the nodes have unique values so that they can be added to the cached treeview
       
RadTreeNode cachedNodeClicked = cachedTreeView.FindNodeByValue(e.NodeClicked.Value);
       AddChildNodes(cachedNodeClicked);
       cachedNodeClicked.ExpandMode = ExpandMode.ClientSide;
       cachedNodeClicked.Expanded = true;

       Session[
"treeViewState"] = cachedTreeView.GetXml();
   }

   
protected void Button1_Click(object sender, EventArgs e)
   {
       
string treeViewState = (string)Session["treeViewState"];
       RadTreeView1.LoadXmlString(treeViewState);
   }
        
VB.NET
Private Function GetNodeData(ByVal query As StringAs DataTable
    Dim dbCon As OleDbConnection = New OleDbConnection(("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Server.MapPath("~/Nodes.mdb")))
    dbCon.Open
    Dim adapter As OleDbDataAdapter = New OleDbDataAdapter(query, dbCon)
    Dim dt As DataTable = New DataTable
    adapter.Fill(dt)
    dbCon.Close
    Return dt
End Function

Private Sub LoadRootNodes()
    RadTreeView1.Nodes.Clear
    Session.Remove("expandedNodes")
    Dim dt As DataTable = GetNodeData("SELECT * FROM Nodes WHERE ParentId IS NULL")
    For Each row As DataRow In dt.Rows
        Dim node As RadTreeNode = New RadTreeNode
        node.Text = CType(row("Text"),String)
        node.Value = CType(row("Id"),Integer).ToString
        node.Category = "Some Category"
        node.ExpandMode = ExpandMode.ServerSideCallBack
        RadTreeView1.Nodes.Add(node)
    Next
End Sub

Private Sub AddChildNodes(ByVal node As RadTreeNode)
    Dim sql As String = "SELECT Nodes.Id AS NodeId, Nodes.Text AS NodeText, COUNT(Children.Id) AS HasChildren FROM Nodes LEFT "& _
    "JOIN Nodes Children ON Nodes.Id = Children.ParentId WHERE Nodes.ParentId = {0} GROUP BY Nodes.Id, No"& _
    "des.Text"
    sql = String.Format(sql, node.Value)
    Dim dt As DataTable = GetNodeData(sql)
    For Each row As DataRow In dt.Rows
        Dim childNode As RadTreeNode = New RadTreeNode
        childNode.Text = CType(row("NodeText"),String)
        childNode.Value = CType(row("NodeId"),Integer).ToString
        childNode.Target = "_new"
        If (CType(row("HasChildren"),Integer) > 0) Then
            childNode.ExpandMode = ExpandMode.ServerSideCallBack
        End If
        node.Nodes.Add(childNode)
    Next
End Sub

Protected Sub Page_Load(ByVal sender As ObjectByVal e As EventArgs)
    If (Not Page.IsPostBack _
                AndAlso Not RadTreeView1.IsCallBack) Then
        LoadRootNodes
        Session("treeViewState") = RadTreeView1.GetXml
    End If
End Sub

Protected Sub RadTreeView1_NodeExpand(ByVal o As ObjectByVal e As Telerik.WebControls.RadTreeNodeEventArgs)
    AddChildNodes(e.NodeClicked)
    Dim treeViewState As String = CType(Session("treeViewState"),String)
    Dim cachedTreeView As RadTreeView = New RadTreeView
    cachedTreeView.LoadXmlString(treeViewState)
    'it is important that the nodes have unique values so that they can be added to the cached treeview
    Dim cachedNodeClicked As RadTreeNode = cachedTreeView.FindNodeByValue(e.NodeClicked.Value)
    AddChildNodes(cachedNodeClicked)
    cachedNodeClicked.ExpandMode = ExpandMode.ClientSide
    cachedNodeClicked.Expanded = true
    Session("treeViewState") = cachedTreeView.GetXml
End Sub

Protected Sub Button1_Click(ByVal sender As ObjectByVal e As EventArgs)
    Dim treeViewState As String = CType(Session("treeViewState"),String)
    RadTreeView1.LoadXmlString(treeViewState)
End Sub

Original Source is : http://www.telerik.com/help/aspnet/treeview/tree_store_expanded_callback.html

DotNet Nook

Welcome to my blog