3
Vote

TreeView and AJAX UpdatePanel issues

description

Hello everybody:

We've tried to use the CSS Friendly Treeview Adapter in a project that uses the Microsoft ASP.NET AJAX Extensions.

Later we realized that the Treeview was one of the controls that didn't fit well within the AJAX UpdatePanel, but then we thought that it could be more easily integrated in the AJAX UpdatePanel using the CSS Friendly Treeview Adapter.

But then again we realized that it wasn't so easy to do, because under some scenarios, after an Asynchronous Postback (partial update), the expanded/collapsed state of the Treeview nodes got lost.

We've made a lesser modification to the TreeView Adapter so that the expanded/collapsed state didn't get lost when "partially rendering" an UpdatePanel (i.e.: selecting a node and showing details, dinamycally creating new nodes or even populating the tree).

Here comes the code:
// First change, new private variable for the class
--> private string _oldHiddenInputName;
    protected override void LoadAdapterViewState(Object state)
    {
        TreeView treeView = Control as TreeView;
        string oldViewState = state as String;
        if ((treeView != null) && (oldViewState != null) && (oldViewState.Split('|').Length == 2))
        {
            string hiddenInputName = oldViewState.Split('|')[0];
            string oldExpansionState = oldViewState.Split('|')[1];
            if (!treeView.ShowExpandCollapse)
            {
                _newViewState = oldExpansionState;
                _updateViewState = true;
            }
            else if (!String.IsNullOrEmpty(Page.Request.Form[hiddenInputName]))
            {
                _newViewState = Page.Request.Form[hiddenInputName];
                _updateViewState = true;
            }

            // Second change, storing the original hidden field name that stores the ViewState      
--> _originalHiddenInputName = hiddenInputName;
        }
    }

    protected override Object SaveAdapterViewState()
    {
        string retStr = "";
        TreeView treeView = Control as TreeView;
        if ((treeView != null) && (_viewState != null))
        {
    // Third change, reusing the original hidden field that stores the ViewState instead of creating a new one
            // if we're using ASP.NET AJAX Extensions and doing a "partial render" of an UpdatePanel
--> if ((_oldHiddenInputName != null) && (ScriptManager.GetCurrent(Page).IsInAsyncPostBack))
--> {
--> retStr = _oldHiddenInputName + "|" + ComposeViewState(treeView.Nodes, "");
--> }
--> else
--> {
                if ((_viewState != null) && (Page != null) && (Page.Form != null) && (!Page.Form.Controls.Contains(_viewState)))
                {
                    Panel panel = new Panel();
                    panel.Controls.Add(_viewState);
                    Page.Form.Controls.Add(panel);
                    string script = "document.getElementById('" + _viewState.ClientID + "').value = GetViewState__AspNetTreeView('" + Extender.MakeChildId("UL") + "');";
                    //Page.ClientScript.RegisterOnSubmitStatement(typeof(TreeViewAdapter), _viewState.ClientID, script);
                    ScriptManager.RegisterOnSubmitStatement(Page, typeof(TreeViewAdapter), _viewState.ClientID, script);
                }
                retStr = _viewState.UniqueID + "|" + ComposeViewState(treeView.Nodes, "");
--> }
        }
        return retStr;
    }

 

We hope this will be useful to anyone.



Juan Daniel Cebrián López
Solnatec, Ingeniería de software
http://www.solnatec.com

comments

bdemarzo wrote Aug 7, 2007 at 2:44 PM

Can someone validate that the proposed changes above do not break anything? If so, then I will incorporate this into the source.

J_D_Cebrian wrote Aug 10, 2007 at 10:03 AM

I'm not sure if this patch could be incorporated into the source, because then the source would also need the "AJAX Extensions", which I think are not required for installing the "CSS Friendly Control Adapters", but at least it solved my issue and probably someone's else in the future.

bdemarzo wrote Aug 10, 2007 at 4:59 PM

No the AJAX extensions should not be required -- I didn't realize the code above had explcit calls to it. The only universal way I can think to support both is by using some kind of provider model to handle the different method calls where needed (i..e Page.ClientScript or ScriptManager methods) -- something that's no small effort.

wrote Sep 13, 2007 at 1:09 PM

wrote May 27, 2008 at 5:28 PM

niraj_ce wrote Aug 26, 2009 at 1:39 PM

can you please attached code file here

wrote Feb 14, 2013 at 8:44 PM

grzechikac wrote May 21, 2015 at 8:38 AM

It worked for me, but I found one error in the code:
there is
-> _originalHiddenInputName = HiddenInputName;
and it should be
-> _oldHiddenInputName = HiddenInputName;

Besides, I added a reference to the library System.Web.Extensions - not universal way :).

Thanks for the tip.