如果在MasterPage放一个ASPxTreeView来表示整个系统的作业树,从用户体验来说,在每个页面切换时记住这棵树的节点的展开状态比较好,如何记录呢?
在ASPxTreeView的客户端事件ExpandedChanged里面,借助ASPxCallback,把节点的展开/收拢信息传回服务器。
<Script> function doTreeExpandedChanged(s, e) { Callback_TreeState.PerformCallback(e.node.name + "|" + e.node.GetExpanded()); } </Script> <dx:ASPxTreeView ID="Menu_TreeList" runat="server" AllowSelectNode="True" ClientInstanceName="Menu_TreeList"> <ClientSideEvents ExpandedChanged="function(s,e){doTreeExpandedChanged(s,e);}" /> </dx:ASPxTreeView> <dx:ASPxCallback runat="server" ID="Callback_TreeState" OnCallback="Callback_TreeStateCallback"> </dx:ASPxCallback>服务器收到节点的展开/收拢信息后,与Session中的信息合并:
(我这里的Node.Name是int类型的)。
private const string SessionTreeStateName = "ProcessTreeState"; protected override void OnLoad(EventArgs e) { base.OnLoad(e); string vPageName = Page.Request.RawUrl; if (!Page.IsPostBack) { BuildProcessTree(); } if (!this.Callback_TreeState.IsCallback) { ApplyTreeState(); } } private void ApplyTreeState() { string vTreeState = (string)Session[SessionTreeStateName]; if (!string.IsNullOrEmpty(vTreeState)) { string[] vArray = vTreeState.Split(','); foreach (TreeViewNode vNode in Menu_TreeList.Nodes) { ScanTreeNodeState(vNode, vArray); } } else { if (Menu_TreeList.Nodes.Count > 0) { Menu_TreeList.Nodes[0].Expanded = true; string[] vList = new string[int.Parse(Menu_TreeList.Nodes[0].Name) + 1]; vList[vList.Length - 1] = true.ToString(); Session[SessionTreeStateName] = string.Join(",", vList); } } } /// <summary> /// 合并节点展开状态到Session /// </summary> /// <param name="ANativeSate"></param> private void MergeTreeState(string ANativeSate) { string vState = (string)Session[SessionTreeStateName]; if (!string.IsNullOrEmpty(vState)) { if (!String.IsNullOrEmpty(ANativeSate)) { string[] vArray = vState.Split(','); string[] vArray2 = ANativeSate.Split(','); List<string> vList = vArray.ToList(); for (int i = 0; i < vArray2.Length; i++) { for (int j = vList.Count - 1; j < i; j++) vList.Add(""); if (!string.IsNullOrEmpty(vArray2[i])) vList[i] = vArray2[i]; } string vNewState=string.Join(",", vList.ToArray()); Session[SessionTreeStateName] = vNewState; } } else Session[SessionTreeStateName] = ANativeSate; } private void ScanTreeNodeState(TreeViewNode ANode,string[] ATreeState) { int vIndex = int.Parse(ANode.Name); if (vIndex < ATreeState.Length) { if (!String.IsNullOrEmpty(ATreeState[vIndex])) { ANode.Expanded = bool.Parse(ATreeState[vIndex]); } } foreach (TreeViewNode vNode in ANode.Nodes) { ScanTreeNodeState(vNode, ATreeState); } } protected void Callback_TreeStateCallback(object source, DevExpress.Web.ASPxCallback.CallbackEventArgs e) { ///把节点的展开状态合并到Session中 string[] vParams = e.Parameter.Split('|'); string[] vList=new string[int.Parse(vParams[0])+1]; vList[vList.Length - 1] = vParams[1]; MergeTreeState(string.Join(",",vList)); }