TreeView: mantener el nodo expandido entre enlaces

Si habéis hecho uso del TreeView, seguro que se os ha planteado el escenario en que tenéis varias "ramas" con varias "hojas", y en algún momento enlazáis con otra url que contiene ese mismo treeview... pero no encontráis la manera de mantener expandido el nodo original sobre el que habéis presionado.

Mmmm, ¿algo liosa la explicación? Si habéis tenido ese problema seguro que lo entendéis, pero para lo que no lo hayan tenido, aquí tenemos un TreeView ejemplo:

ejemploTreeView.aspx
        <asp:TreeView ID="TreeView1" runat="server" ExpandDepth="0" OnSelectedNodeChanged="TreeView1_SelectedNodeChanged">
            <Nodes>
                <asp:TreeNode Text="Madre" Value="Madre">
                    <asp:TreeNode Text="Hija 1" Value="Hija 1">
                        <asp:TreeNode Text="Nieta 1_1" Value="1_1"></asp:TreeNode>
                        <asp:TreeNode Text="Nieta 1_2" Value="1_2"></asp:TreeNode>
                        <asp:TreeNode Text="Nieta 1_3" Value="1_3"></asp:TreeNode>
                    </asp:TreeNode>
                    <asp:TreeNode Text="Hija 2" Value="Hija 2">
                        <asp:TreeNode Text="Nieta 2_1" Value="2_1"></asp:TreeNode>
                        <asp:TreeNode Text="Nieta 2_2" Value="2_2"></asp:TreeNode>
                    </asp:TreeNode>
                </asp:TreeNode>
            </Nodes>
        </asp:TreeView>


Como veis es un sencillo TreeView con una madre, dos hijas, la primera de las cuales tiene tres hijas y la segunda  dos.

El quid de la cuestión es que queremos dirigirnos a la URL en la que estamos, pero cambiando el querystring. Lo veremos mejor en el manejo del evento SelectedNodeChanged:

ejemploTreeView.aspx.cs
    protected void TreeView1_SelectedNodeChanged(object sender, EventArgs e)
    {
        TreeView tv = (TreeView)sender;
        string TreeId = HttpUtility.UrlEncode(tv.SelectedNode.ValuePath);

        Response.Redirect("?TreeId=" + TreeId);
    }


Estamos recogiendo el ValuePath del nodo sobre el que presionamos y dirigiéndonos a la misma url pero cambiando el valor TreeId del QueryString.

Ahora lo que vamos a hacer es recoger ese valor del Querystring (si lo hay) y seleccionar el nodo sobre el que hemos presionado, de modo que se abra el árbol desde el nodo nieto hasta la madre:

ejemploTreeView.aspx.cs
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
             // Seleccionamos el TreeId
            string TreeId =
HttpUtility.UrlDecode(Request.QueryString["TreeId"]);

            if (!string.IsNullOrEmpty(TreeId))
            {
                // Elegimos el nodo sobre el que hemos hecho click y comprobamos que realmente exista
                TreeNode node = TreeView1.FindNode(TreeId);
                if (null != node)
                {
                       // Lo ponemos en negrita
                    node.Text = "<b>" + node.Text + "</b>";
                      // Viajamos desde esta nieta hasta la madre usando recursividad y hacemos un expand.
                    while ((node.Parent != null) && (node.Parent.Depth != -1))
                    {
                        node = selectParent(node);
                        node.Expand();
                    }
                }
            }
        }
    }

    // Función recursiva
    private TreeNode selectParent(TreeNode node)
    {
        return node.Parent;
    }



Como os podéis imaginar, este ejemplo es académico, dado que es extraño que se quiera viajar a una Url con un QueryString igual al valuePath del nodo al que le hemos hecho click. Sin embargo esto es el equivalente a una "clase madre" de la que vosotros deberéis heredar y adaptarlo a vuestras necesidades