[RESOLVED]Maintaining treeview state across your site in a master page using Web.sitemap

Hi,

I am using a treeview for navigation and set the ExpandDepth="1" to only display the parent nodes by default which is how I would like to start off and it works great.

However, when I expand a parent node and select one of the child nodes, then I would like the treeview to maintain it’s state. How can I do that?

I saw lot’s of threads here about the same issue but as far as I can tell they are all using xps (whatever that is) instead of a Web.sitemap (which is what I’m using) as the datasourse for the treeview.

Can anyone explain to me how to maintain the treeview state across the website using Web.sitemap?

The code is:

<%@ Master Language="C#" AutoEventWireup="true" CodeFile="MasterPage.master.cs" Inherits="MasterPage" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>default</title>
    <link href="NTstyle.css" rel="stylesheet" />
    <asp:ContentPlaceHolder ID="head" runat="server">
    </asp:ContentPlaceHolder>
</head>
<body>
    <form id="form1" runat="server">
        <div id="pagewrapper">
            <div id="masthead">
                <img src="Images/header_home.png" />
            </div>
            <div id="breadcrumb">
                <asp:SiteMapPath ID="SiteMapPath1" runat="server">
                </asp:SiteMapPath>
            </div>
            <div id="container">
                <div id="left_col">
                    <asp:TreeView ID="TreeView1" runat="server" DataSourceID="SiteMapDataSource1" ExpandDepth="1" Height="450px" ImageSet="Arrows" Width="16px">
                        <HoverNodeStyle Font-Underline="True" ForeColor="#5555DD" />
                        <NodeStyle Font-Names="Verdana" Font-Size="8pt" ForeColor="Black" HorizontalPadding="5px" NodeSpacing="0px" VerticalPadding="0px" />
                        <ParentNodeStyle Font-Bold="False" />
                        <SelectedNodeStyle Font-Underline="True" ForeColor="#5555DD" HorizontalPadding="0px" VerticalPadding="0px" />
                    </asp:TreeView>
                    <asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" />
                </div>
                <div id="page_content">
                    <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
                        <p>page_content</p>
                    </asp:ContentPlaceHolder>
                </div>
            </div>
            <div id="footer">
                For suggestions, questions, problems, contact the
		<a href=mailto:someone@somewhere.com?subject=enquiry>webmaster</a><br />
                Copyright 2014
            </div>
        </div>
    </form>
</body>
</html>

Hi,

Nebulosa

I am using a treeview for navigation and set the ExpandDepth="1" to only display the parent nodes by default which is how I would like to start off and it works great.

However, when I expand a parent node and select one of the child nodes, then I would like the treeview to maintain it’s state. How can I do that?

Firstly, It has nothing to do with web.sitemap you are using. It is the most basic problem when it comes to retaining the state of the TreeView accross multiple pages specially when using MasterPages. Now, Why this happens? It is very simple when we open
a new page the state of the treeview is lost and TreeView opens up with the original ExpandDepth set. To maintain the state of the TreeView we need to use Session object. We have to save the state of the TreeView into the Session object and use it across multiple
pages.

On, How to save the TreeViewState in Session and use it. Below are the two articles you can refer to:

Maintain ASP.NET TreeView State (CSASPNETMaintainTreeViewState) -
http://code.msdn.microsoft.com/CSASPNETMaintainTreeViewSta-c7673683

Save TreeView Nodes Expansion –
http://www.c-sharpcorner.com/uploadfile/VIMAL.LAKHERA/save-treeview-nodes-expansion/

Best Regards!

 

Hi Sam,

thanks for looking into this. However, the 2 links you provided didn’t really help.

The first one

Sam – MSFT

Maintain ASP.NET TreeView State (CSASPNETMaintainTreeViewState) -
http://code.msdn.microsoft.com/CSASPNETMaintainTreeViewSta-c7673683

uses a "save treeview state" button. I have never seen a website ask the user to click on a "save treeview state" button before. Seems a bizarre solution.

The second one

Sam – MSFT

Save TreeView Nodes Expansion –
http://www.c-sharpcorner.com/uploadfile/VIMAL.LAKHERA/save-treeview-nodes-expansion/

is too complicated for me. There are no clear instructions what I am supposed to do. I copied the full CS class code into my CSS file but that came up with lots of red underlines indicating errors. Could it be because I’m using Visual Studio Express 2012?

Anyway, I am a novice and need clearer instructions than that. Sorry for being so thick. Can you help?

Together with the help from a friend we found the solution and it works perfectly.

This is the code for my master page:

<%@ Master Language="C#" AutoEventWireup="true" CodeFile="MasterPage.master.cs" Inherits="MasterPage" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>default</title>
    <link href="NTstyle.css" rel="stylesheet" />
    <asp:ContentPlaceHolder ID="head" runat="server">
    </asp:ContentPlaceHolder>
</head>
<body>
    <form id="form1" runat="server">
        <div id="pagewrapper">
            <div id="masthead">
                <asp:Image ID="Header" runat="server" ImageUrl="~/Images/header_home.png" ImageAlign="Left" />
            </div>
            <div id="breadcrumb">
                <asp:SiteMapPath ID="SiteMapPath1" runat="server">
                </asp:SiteMapPath>
            </div>
            <div id="container">
                <div id="left_col">
                    <asp:TreeView ID="TreeView1" runat="server" DataSourceID="SiteMapDataSource1" ExpandDepth="1" NodeIndent="10" OnTreeNodeCollapsed="TreeView1_TreeNodeCollapsed" OnDataBound="TreeView1_DataBound" OnTreeNodeExpanded="TreeView1_TreeNodeExpanded">
                        <HoverNodeStyle Font-Underline="True" ForeColor="#5555DD" />
                        <NodeStyle Font-Names="Verdana" Font-Size="8pt" ForeColor="Black" HorizontalPadding="5px" NodeSpacing="0px" VerticalPadding="0px" />
                        <ParentNodeStyle Font-Bold="False" />
                        <SelectedNodeStyle Font-Underline="True" ForeColor="#5555DD" HorizontalPadding="0px" VerticalPadding="0px" />
                    </asp:TreeView>
                    <asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" />
                </div>
                <div id="page_content">
                    <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
                        <p>page_content</p>
                    </asp:ContentPlaceHolder>
                </div>
            </div>
            <div id="footer">
                For suggestions, questions, problems, contact the webmaster<br />
                Copyright 2014
            </div>
        </div>
    </form>
</body>
</html>

And this is the CS code behind:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class MasterPage : System.Web.UI.MasterPage
{
    protected void Page_Load(object sender, EventArgs e)
    {
        {
            //
            // Disable ExpandDepth if the TreeView's expand/collapse
            // state is stored in session.
            //
            if (Session["TreeViewState"] != null)
                TreeView1.ExpandDepth = -1;
        }
    }
    protected void TreeView1_DataBound(object sender, EventArgs e)
    {
        if (Session["TreeViewState"] == null)
        {
            //
            // Record the TreeView's current expand/collapse state.
            //
            List<string> list = new List<string>(16);
            SaveTreeViewState(TreeView1.Nodes, list);
            Session["TreeViewState"] = list;
        }
        else
        {
            //
            // Apply the recorded expand/collapse state to the TreeView.
            //
            List<string> list = (List<string>)Session["TreeViewState"];
            RestoreTreeViewState(TreeView1.Nodes, list);
        }
    }

    protected void TreeView1_TreeNodeCollapsed(object sender, TreeNodeEventArgs e)
    {
        if (IsPostBack)
        {
            List<string> list = new List<string>(16);
            SaveTreeViewState(TreeView1.Nodes, list);
            Session["TreeViewState"] = list;
        }
    }

    protected void TreeView1_TreeNodeExpanded(object sender, TreeNodeEventArgs e)
    {
        if (IsPostBack)
        {
            List<string> list = new List<string>(16);
            SaveTreeViewState(TreeView1.Nodes, list);
            Session["TreeViewState"] = list;
        }
    }

    private void SaveTreeViewState(TreeNodeCollection nodes, List<string> list)
    {
        //
        // Recursivley record all expanded nodes in the List.
        //
        foreach (TreeNode node in nodes)
        {
            if (node.ChildNodes != null && node.ChildNodes.Count != 0)
            {
                if (node.Expanded.HasValue && node.Expanded == true && !String.IsNullOrEmpty(node.Text))
                    list.Add(node.Text);
                SaveTreeViewState(node.ChildNodes, list);
            }
        }
    }

    private void RestoreTreeViewState(TreeNodeCollection nodes, List<string> list)
    {
        foreach (TreeNode node in nodes)
        {
            //
            // Restore the state of one node.
            //
            if (list.Contains(node.Text))
            {
                if (node.ChildNodes != null && node.ChildNodes.Count != 0 && node.Expanded.HasValue && node.Expanded == false)
                    node.Expand();
            }
            else
            {
                if (node.ChildNodes != null && node.ChildNodes.Count != 0 && node.Expanded.HasValue && node.Expanded == true)
                    node.Collapse();
            }

            //
            // If the node has child nodes, restore their state, too.
            //
            if (node.ChildNodes != null && node.ChildNodes.Count != 0)
                RestoreTreeViewState(node.ChildNodes, list);
        }
    }
}

 

Leave a Reply