locked
how to remain the treeview after redirect to another page? RRS feed

  • Question

  • User2144323856 posted

    I'm now currently using treeview bind with sitemapdatasource. After i expand the treeview and click the node, it will redirect to another page, and then the treeview will be refresh to default, which means showing the treeview before expanding.. How can i remain the treeview to where i stop after i click to redirect to another page?

    <asp:TreeView ID="TreeView1" runat="server"  DataSourceID="SiteMapDataSource1" 
                                     ExpandDepth="0"  >
                                 </asp:TreeView>

    Wednesday, March 31, 2021 7:23 AM

Answers

  • User-177150550 posted

    Try this.

    In the master page, store the state of the tree before the page is unloaded:

    <script type="text/javascript" language="javascript">
            window.onbeforeunload = function () {
                try {
                    // The expanded state of the treeview is available in the hidden input
                    // ..._ExpandState. Store that string in a cookie so we have it on the server
                    // side when the page is loaded in order to restore the state of the treeview.
                    var expInfo = document.getElementById('<%=TreeView1.ClientID%>' + '_ExpandState');
                    if (expInfo)
                    {
                        createCookie('ToolsTVExpand', expInfo.value, 365);
                    }
                }
                catch (err) {
                    // Ignore the error
                }
            }
            function createCookie(name, value, days) {
                if (days) {
                    var date = new Date();
                    date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
                    var expires = "; expires=" + date.toGMTString();
                }
                else var expires = "";
                document.cookie = name + "=" + value + expires + "; path=/";
            }
    </script>

    Then in code behind:

    protected void Page_Load(object sender, EventArgs e)
    {
      ....
      // If this is the initial loading of the page, restore the navigation tree view state
      if (!IsPostBack)
          reloadTreeviewState();
    }
    public void reloadTreeviewState()
    {
        try
        {
            HttpCookie cookie = Request.Cookies["ToolsTVExpand"];
            if (cookie != null && cookie.Value != null)
            {
                int currIdx = 0;
                foreach (TreeNode mainNode in TreeView1.Nodes)
                {
                    currIdx = setNodeStates(mainNode, cookie.Value, currIdx);
                }
            }
        }
        catch (Exception e)
        {
            // Just keep going
        }
    }
    protected int setNodeStates(TreeNode node, String stateInfo, int currIdx)
    {
        if (currIdx >= stateInfo.Length)
            throw new Exception("State info shorter than list of nodes.");
        Char state = stateInfo[currIdx];`enter code here`
        if (state == 'e')
        {
            node.Expand();
        }
        currIdx++;
        if (node.ChildNodes != null && node.ChildNodes.Count != 0)
        {
            foreach (TreeNode childNode in node.ChildNodes)
            {
                currIdx = setNodeStates(childNode, stateInfo, currIdx);
            }
        }
    
        return currIdx;
    }
    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, April 5, 2021 4:51 AM

All replies

  • User1535942433 posted

    Hi demonxjun,

    According to your description, as far as I I think,you need to save the treeview state before redirect the other page.

    You could use cookie,session or viewState to save the state.

    Just like this:

    protected void btnReset_Click(object sender, EventArgs e)
    {
        List<string> expandedNodes = new List<string>();
        //get all expanded nodes
        TreeView1.Nodes.Cast<TreeNode>().ToList().ForEach(a => GetExpandedStatus(a, expandedNodes));            
        //collapse all to reset the treeview
        TreeView1.CollapseAll();
        //save expanded node value paths
        Session["ExpandedNodes"] = expandedNodes;
    }
    protected void btnReload_Click(object sender, EventArgs e)
    {
        if (Session["ExpandedNodes"] != null)
            ((List<string>)Session["ExpandedNodes"]).ForEach(a => TreeView1.FindNode(a).Expanded = true);
    }
    public void GetExpandedStatus(TreeNode node, List<string> ExpandedNodes)
    {
        //check if node is expanded
        if (node.Expanded.GetValueOrDefault(false))
            ExpandedNodes.Add(node.ValuePath);
        node.ChildNodes.Cast<TreeNode>().ToList().ForEach(a => GetExpandedStatus(a, ExpandedNodes));            
    }

    Best regards,

    Yijing Sun

    Wednesday, March 31, 2021 9:47 AM
  • User2144323856 posted

    How to makes the code works .. Im currently using this method to bind my treeview.. i have implement your solution but it's not working, isit the way i put is wrong?

      protected void Page_Load(object sender, EventArgs e)
            {
              if (!Page.IsPostBack)

                   {   

                   LoadTransactionMenu();

                             if (Session["ExpandedNodes"] != null)
                            ((List<string>)Session["ExpandedNodes"]).ForEach(a => TreeView3.FindNode(a).Expanded = true);
                }
            }

      private void LoadTransactionMenu()
            {
                //TRANSACTION MENU
                string SubModuleID, SubModuleNM, DocModuleID, DocModuleName, MenuTransID, MenuTransName;
                SqlConnection con = new SqlConnection(ConString);
                string CmdString = "SELECT SUBMODULEID, SUBMODULENM, URLNAME FROM SUBMODULE";
                SqlCommand cmd = new SqlCommand(CmdString, con);
                SqlDataAdapter sda = new SqlDataAdapter(cmd);
                DataTable dt = new DataTable();
                sda.Fill(dt);
                TreeNode node1 = new TreeNode();
                node1.Text = "TRANSACTION MENU";
                TreeView1.Nodes.Add(node1);
               
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    SubModuleID = dt.Rows[i]["SUBMODULEID"].ToString();
                    SubModuleNM = dt.Rows[i]["SUBMODULENM"].ToString();
                    TreeNode SubModuleNode = new TreeNode(SubModuleNM, SubModuleID);
                    SubModuleNode.NavigateUrl = dt.Rows[i]["URLNAME"].ToString();

                    node1.ChildNodes.Add(SubModuleNode);

                    CmdString = "SELECT DDID, DOCNAME, DDADDRESS FROM DOCMODULE WHERE SUBMODULEID=@SUBMODULEID";
                    cmd = new SqlCommand(CmdString, con);
                    cmd.Parameters.AddWithValue("@SUBMODULEID", SubModuleID);
                    sda = new SqlDataAdapter(cmd);
                    DataTable dt2 = new DataTable();
                    sda.Fill(dt2);

                    for (int j = 0; j < dt2.Rows.Count; j++)
                    {
                        DocModuleID = dt2.Rows[j]["DDID"].ToString();
                        DocModuleName = dt2.Rows[j]["DOCNAME"].ToString();
                        TreeNode DocModuleNode = new TreeNode(DocModuleName, DocModuleID);
                        DocModuleNode.NavigateUrl = dt2.Rows[j]["DDADDRESS"].ToString();

                        SubModuleNode.ChildNodes.Add(DocModuleNode);

                        CmdString = "SELECT DID, DNAME, DADDRESS FROM MENUTRANSACTION WHERE DDID=@DDID AND UID= '" + Session["UserID"] + "'";
                        cmd = new SqlCommand(CmdString, con);
                        cmd.Parameters.AddWithValue("@DDID", DocModuleID);
                        sda = new SqlDataAdapter(cmd);
                        DataTable dt3 = new DataTable();
                        sda.Fill(dt3);

                        for (int k = 0; k < dt3.Rows.Count; k++)
                        {
                            MenuTransID = dt3.Rows[k]["DID"].ToString();
                            MenuTransName = dt3.Rows[k]["DNAME"].ToString();
                            TreeNode MenuTransNode = new TreeNode(MenuTransName, MenuTransID);
                            MenuTransNode.NavigateUrl = dt3.Rows[k]["DADDRESS"].ToString();

                            DocModuleNode.ChildNodes.Add(MenuTransNode);
                        }

                        if (DocModuleNode.ChildNodes.Count == 0)
                        {
                            SubModuleNode.ChildNodes.Remove(DocModuleNode);
                        }
                    }
                    if (SubModuleNode.ChildNodes.Count == 0)
                    {
                        node1.ChildNodes.Remove(SubModuleNode);
                    }
                }
            }

            public void GetExpandedStatus(TreeNode node, List<string> ExpandedNodes)
            {
                //check if node is expanded
                if (node.Expanded.GetValueOrDefault(false))
                    ExpandedNodes.Add(node.ValuePath);
                node.ChildNodes.Cast<TreeNode>().ToList().ForEach(a => GetExpandedStatus(a, ExpandedNodes));
            }

            protected void TreeView1_SelectedNodeChanged(object sender, EventArgs e)
            {
                List<string> expandedNodes = new List<string>();
                //get all expanded nodes
                TreeView1.Nodes.Cast<TreeNode>().ToList().ForEach(a => GetExpandedStatus(a, expandedNodes));
                //collapse all to reset the treeview
                TreeView1.CollapseAll();
                //save expanded node value paths
                Session["ExpandedNodes"] = expandedNodes;
            }

    Thursday, April 1, 2021 12:52 AM
  • User1535942433 posted

    Hi demonxjun,

    According to your code,I suggest you could debug and break point at these codes. The  running steps of the codes are below:

    1.When you load the treeview, it will bind your datasource. And then,it will check  if the session is null. Because you don't set the session for the first page load,so it don't run foreach  the treeview  nodes.

    2.When you change the node's selected, it will  create a list to store node's valuepath. It will call the GetExpandedStatus function. If the node's expanded attributes is false, the node's valuepath will be stored into the list and it will be stored in the session.

    3.When you click button to redirect to the other page and return from the other page, it will load the page and foreach the session list.

    I suggest you could check the session list's nodes

    Best regards,

    Yijing Sun

    Thursday, April 1, 2021 8:51 AM
  • User2144323856 posted

    Can you give sample of setting the session for the first page load?

    Friday, April 2, 2021 1:00 AM
  • User2144323856 posted

    I have successfully remain the treeview state using the below method.. but i have 2 treeview, 1 treeview is binding with the sitemapdatasource and 1 more treeview is binding from the database in behind code.. the code is at above post.. only the treeview binding with sitemapdatasource had successfully remain its state.. the treeview that bind from database failed to remain its state... can anyone help?

     protected void PagePreRender(object sender, EventArgs e)
            {

                try
                {
                    FillLeftNavigation();
                    ExpandTreeView(TreeView1.Nodes);
                }
                catch (Exception ex)
                {
                    // Exception handling logic
                }
            }
            public void FillLeftNavigation()
            {
                TreeView1.ShowExpandCollapse = true;
                // set the default state of all nodes.
                TreeView1.CollapseAll();
            }
             private void ExpandTreeView(TreeNodeCollection nodes)

            {

                foreach (TreeNode node in nodes)
                {

                    //Modifying the url string according to tree view not value format
                    string reqNodeValue = HttpContext.Current.Request["ReqVal"];   // Here we are sending treeview selected node value through Query string 
                    if (node.Value.ToString() == reqNodeValue)                 //Compare the value with tree view nodes 
                    {
                        node.Selected = true;                                   //If value is equal expand it 
                        ExpandParent(node.Parent);
                    }

                    if (node.ChildNodes.Count > 0)
                    {
                        ExpandTreeView(node.ChildNodes);
                    }
                }
            }

            private void ExpandParent(TreeNode node)
            {
                if (node != null)
                {
                    node.Expand();
                    ExpandParent(node.Parent);
                }
            } 

    Friday, April 2, 2021 4:22 AM
  • User409696431 posted

    You need to save the expanded state of both treeviews, separately, and expand them separately.  Are you doing that?  I can't see that in your code.

    Saturday, April 3, 2021 3:46 AM
  • User2144323856 posted

    Yes i did, i didn't show it all . But it was a mistake on the above post, the code above doesn't work ...For the treeview that binding with sitemapdatasource, we just need to add ViewStateMode="Enabled" in the treeview in .aspx page and it will be able to remain the state after redirect to another page. But this method doesn't work for the treeview that binding from the database in behind code... i have tried so many other  method :(

    Saturday, April 3, 2021 2:34 PM
  • User409696431 posted

    Use VS's debugger, set some breakpoints and see what the code flow is and what values are being saved and retrieved from session.  That's the most direct way to find out what the code you tried actually does, and identify what isn't happening properly.  (Since you have your full pages, and the database, you are best in a position to do this.)

    Saturday, April 3, 2021 4:45 PM
  • User-177150550 posted

    Try this.

    In the master page, store the state of the tree before the page is unloaded:

    <script type="text/javascript" language="javascript">
            window.onbeforeunload = function () {
                try {
                    // The expanded state of the treeview is available in the hidden input
                    // ..._ExpandState. Store that string in a cookie so we have it on the server
                    // side when the page is loaded in order to restore the state of the treeview.
                    var expInfo = document.getElementById('<%=TreeView1.ClientID%>' + '_ExpandState');
                    if (expInfo)
                    {
                        createCookie('ToolsTVExpand', expInfo.value, 365);
                    }
                }
                catch (err) {
                    // Ignore the error
                }
            }
            function createCookie(name, value, days) {
                if (days) {
                    var date = new Date();
                    date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
                    var expires = "; expires=" + date.toGMTString();
                }
                else var expires = "";
                document.cookie = name + "=" + value + expires + "; path=/";
            }
    </script>

    Then in code behind:

    protected void Page_Load(object sender, EventArgs e)
    {
      ....
      // If this is the initial loading of the page, restore the navigation tree view state
      if (!IsPostBack)
          reloadTreeviewState();
    }
    public void reloadTreeviewState()
    {
        try
        {
            HttpCookie cookie = Request.Cookies["ToolsTVExpand"];
            if (cookie != null && cookie.Value != null)
            {
                int currIdx = 0;
                foreach (TreeNode mainNode in TreeView1.Nodes)
                {
                    currIdx = setNodeStates(mainNode, cookie.Value, currIdx);
                }
            }
        }
        catch (Exception e)
        {
            // Just keep going
        }
    }
    protected int setNodeStates(TreeNode node, String stateInfo, int currIdx)
    {
        if (currIdx >= stateInfo.Length)
            throw new Exception("State info shorter than list of nodes.");
        Char state = stateInfo[currIdx];`enter code here`
        if (state == 'e')
        {
            node.Expand();
        }
        currIdx++;
        if (node.ChildNodes != null && node.ChildNodes.Count != 0)
        {
            foreach (TreeNode childNode in node.ChildNodes)
            {
                currIdx = setNodeStates(childNode, stateInfo, currIdx);
            }
        }
    
        return currIdx;
    }
    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, April 5, 2021 4:51 AM
  • User2144323856 posted

    Thanks Choo Li Jun,

    Finally this code is working for me .. but after i close the program and run again, the treeview showing the state before i close the program.. i need the state to be default which is all collapse..how to solve it?

     protected void Page_Load(object sender, EventArgs e)
            {
                if (!Page.IsPostBack)
                {
                    LoadTransactionMenu();
              TreeView1.CollapseAll();
                    reloadTreeviewState();

    }

    }

    Monday, April 5, 2021 6:48 AM
  • User2144323856 posted

    alright i solved it.. just clear the cookies at the first page load

    Monday, April 5, 2021 9:13 AM