// // System.Web.UI.WebControls.TreeView.cs // // Authors: // Lluis Sanchez Gual (lluis@novell.com) // // (C) 2004 Novell, Inc (http://www.novell.com) // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // Copyright (C) 2004 Novell, Inc (http://www.novell.com) // #if NET_2_0 using System.Collections; using System.Text; using System.ComponentModel; using System.Web.Handlers; using System.Collections.Specialized; using System.IO; using System.Security.Permissions; namespace System.Web.UI.WebControls { // CAS [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)] // attributes [SupportsEventValidation] [ControlValueProperty ("SelectedValue")] [DefaultEvent ("SelectedNodeChanged")] [Designer ("System.Web.UI.Design.WebControls.TreeViewDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")] public class TreeView: HierarchicalDataBoundControl, IPostBackEventHandler, IPostBackDataHandler, ICallbackEventHandler { bool cssStylesRegistered; Style hoverNodeStyle; TreeNodeStyle leafNodeStyle; TreeNodeStyle nodeStyle; TreeNodeStyle parentNodeStyle; TreeNodeStyle rootNodeStyle; TreeNodeStyle selectedNodeStyle; TreeNodeStyleCollection levelStyles; TreeNodeCollection nodes; TreeNodeBindingCollection dataBindings; TreeNode selectedNode; Hashtable bindings; private static readonly object TreeNodeCheckChangedEvent = new object(); private static readonly object SelectedNodeChangedEvent = new object(); private static readonly object TreeNodeCollapsedEvent = new object(); private static readonly object TreeNodeDataBoundEvent = new object(); private static readonly object TreeNodeExpandedEvent = new object(); private static readonly object TreeNodePopulateEvent = new object(); static Hashtable imageStyles = new Hashtable (); class ImageStyle { public ImageStyle (string expand, string collapse, string noExpand, string icon, string iconLeaf, string iconRoot) { Expand = expand; Collapse = collapse; NoExpand = noExpand; RootIcon = iconRoot; ParentIcon = icon; LeafIcon = iconLeaf; } public string Expand; public string Collapse; public string NoExpand; public string RootIcon; public string ParentIcon; public string LeafIcon; } static TreeView () { imageStyles [TreeViewImageSet.Arrows] = new ImageStyle ("arrow_plus", "arrow_minus", "arrow_noexpand", null, null, null); imageStyles [TreeViewImageSet.BulletedList] = new ImageStyle (null, null, null, "dot_full", "dot_empty", "dot_full"); imageStyles [TreeViewImageSet.BulletedList2] = new ImageStyle (null, null, null, "box_full", "box_empty", "box_full"); imageStyles [TreeViewImageSet.BulletedList3] = new ImageStyle (null, null, null, "star_full", "star_empty", "star_full"); imageStyles [TreeViewImageSet.BulletedList4] = new ImageStyle (null, null, null, "star_full", "star_empty", "dots"); imageStyles [TreeViewImageSet.Contacts] = new ImageStyle ("TreeView_plus", "TreeView_minus", "contact", null, null, null); imageStyles [TreeViewImageSet.Events] = new ImageStyle ("TreeView_plus", "TreeView_minus", "TreeView_noexpand", null, "warning", null); imageStyles [TreeViewImageSet.Inbox] = new ImageStyle ("TreeView_plus", "TreeView_minus", "TreeView_noexpand", "inbox", "inbox", "inbox"); imageStyles [TreeViewImageSet.Msdn] = new ImageStyle ("box_plus", "box_minus", "box_noexpand", null, null, null); imageStyles [TreeViewImageSet.Simple] = new ImageStyle ("TreeView_plus", "TreeView_minus", "box_full", null, null, null); imageStyles [TreeViewImageSet.Simple2] = new ImageStyle ("TreeView_plus", "TreeView_minus", "box_empty", null, null, null); // TODO imageStyles [TreeViewImageSet.News] = new ImageStyle ("TreeView_plus", "TreeView_minus", "TreeView_noexpand", null, null, null); imageStyles [TreeViewImageSet.Faq] = new ImageStyle ("TreeView_plus", "TreeView_minus", "TreeView_noexpand", null, null, null); imageStyles [TreeViewImageSet.WindowsHelp] = new ImageStyle ("TreeView_plus", "TreeView_minus", "TreeView_noexpand", null, null, null); imageStyles [TreeViewImageSet.XPFileExplorer] = new ImageStyle ("TreeView_plus", "TreeView_minus", "TreeView_noexpand", null, null, null); } public event TreeNodeEventHandler TreeNodeCheckChanged { add { Events.AddHandler (TreeNodeCheckChangedEvent, value); } remove { Events.RemoveHandler (TreeNodeCheckChangedEvent, value); } } public event EventHandler SelectedNodeChanged { add { Events.AddHandler (SelectedNodeChangedEvent, value); } remove { Events.RemoveHandler (SelectedNodeChangedEvent, value); } } public event TreeNodeEventHandler TreeNodeCollapsed { add { Events.AddHandler (TreeNodeCollapsedEvent, value); } remove { Events.RemoveHandler (TreeNodeCollapsedEvent, value); } } public event TreeNodeEventHandler TreeNodeDataBound { add { Events.AddHandler (TreeNodeDataBoundEvent, value); } remove { Events.RemoveHandler (TreeNodeDataBoundEvent, value); } } public event TreeNodeEventHandler TreeNodeExpanded { add { Events.AddHandler (TreeNodeExpandedEvent, value); } remove { Events.RemoveHandler (TreeNodeExpandedEvent, value); } } public event TreeNodeEventHandler TreeNodePopulate { add { Events.AddHandler (TreeNodePopulateEvent, value); } remove { Events.RemoveHandler (TreeNodePopulateEvent, value); } } protected virtual void OnTreeNodeCheckChanged (TreeNodeEventArgs e) { if (Events != null) { TreeNodeEventHandler eh = (TreeNodeEventHandler) Events [TreeNodeCheckChangedEvent]; if (eh != null) eh (this, e); } } protected virtual void OnSelectedNodeChanged (EventArgs e) { if (Events != null) { EventHandler eh = (EventHandler) Events [SelectedNodeChangedEvent]; if (eh != null) eh (this, e); } } protected virtual void OnTreeNodeCollapsed (TreeNodeEventArgs e) { if (Events != null) { TreeNodeEventHandler eh = (TreeNodeEventHandler) Events [TreeNodeCollapsedEvent]; if (eh != null) eh (this, e); } } protected virtual void OnTreeNodeDataBound (TreeNodeEventArgs e) { if (Events != null) { TreeNodeEventHandler eh = (TreeNodeEventHandler) Events [TreeNodeDataBoundEvent]; if (eh != null) eh (this, e); } } protected virtual void OnTreeNodeExpanded (TreeNodeEventArgs e) { if (Events != null) { TreeNodeEventHandler eh = (TreeNodeEventHandler) Events [TreeNodeExpandedEvent]; if (eh != null) eh (this, e); } } protected virtual void OnTreeNodePopulate (TreeNodeEventArgs e) { if (Events != null) { TreeNodeEventHandler eh = (TreeNodeEventHandler) Events [TreeNodePopulateEvent]; if (eh != null) eh (this, e); } } [Localizable (true)] public string CollapseImageToolTip { get { return ViewState.GetString ("CollapseImageToolTip", "Collapse {0}"); } set { ViewState["CollapseImageToolTip"] = value; } } [MonoTODO ("Implement support for this")] [WebCategory ("Behavior")] [WebSysDescription ("Whether the tree will automatically generate bindings.")] [DefaultValue (true)] public bool AutoGenerateDataBindings { get { return ViewState.GetBool ("AutoGenerateDataBindings", true); } set { ViewState["AutoGenerateDataBindings"] = value; } } [DefaultValue ("")] [WebSysDescription ("The url of the image to show when a node can be collapsed.")] [UrlProperty] [WebCategory ("Appearance")] [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)] public string CollapseImageUrl { get { return ViewState.GetString ("CollapseImageUrl", ""); } set { ViewState["CollapseImageUrl"] = value; } } [WebCategory ("Data")] [PersistenceMode (PersistenceMode.InnerProperty)] [WebSysDescription ("Bindings for tree nodes.")] [Editor ("System.Web.UI.Design.WebControls.TreeViewBindingsEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)] [DefaultValue (null)] [MergablePropertyAttribute (false)] public TreeNodeBindingCollection DataBindings { get { if (dataBindings == null) { dataBindings = new TreeNodeBindingCollection (); if (IsTrackingViewState) ((IStateManager)dataBindings).TrackViewState(); } return dataBindings; } } [WebCategory ("Behavior")] [WebSysDescription ("Whether the tree view can use client-side script to expand and collapse nodes.")] [Themeable (false)] [DefaultValue (true)] public bool EnableClientScript { get { return ViewState.GetBool ("EnableClientScript", true); } set { ViewState["EnableClientScript"] = value; } } [DefaultValue (-1)] [WebCategory ("Behavior")] [WebSysDescription ("The initial expand depth.")] [TypeConverter ("System.Web.UI.WebControls.TreeView+TreeViewExpandDepthConverter, " + Consts.AssemblySystem_Web)] public int ExpandDepth { get { return ViewState.GetInt ("ExpandDepth", -1); } set { ViewState["ExpandDepth"] = value; } } [Localizable (true)] public string ExpandImageToolTip { get { return ViewState.GetString ("ExpandImageToolTip", "Expand {0}"); } set { ViewState["ExpandImageToolTip"] = value; } } [DefaultValue ("")] [UrlProperty] [WebSysDescription ("The url of the image to show when a node can be expanded.")] [WebCategory ("Appearance")] [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)] public string ExpandImageUrl { get { return ViewState.GetString ("ExpandImageUrl", ""); } set { ViewState["ExpandImageUrl"] = value; } } [PersistenceMode (PersistenceMode.InnerProperty)] [NotifyParentProperty (true)] [DefaultValue (null)] [WebCategory ("Styles")] [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] public Style HoverNodeStyle { get { if (hoverNodeStyle == null) { hoverNodeStyle = new Style(); if (IsTrackingViewState) hoverNodeStyle.TrackViewState(); } return hoverNodeStyle; } } [DefaultValue (TreeViewImageSet.Custom)] public TreeViewImageSet ImageSet { get { return (TreeViewImageSet)ViewState.GetInt ("ImageSet", (int)TreeViewImageSet.Custom); } set { if (!Enum.IsDefined (typeof (TreeViewImageSet), value)) throw new ArgumentOutOfRangeException (); ViewState["ImageSet"] = value; } } [PersistenceMode (PersistenceMode.InnerProperty)] [NotifyParentProperty (true)] [DefaultValue (null)] [WebCategory ("Styles")] [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] public TreeNodeStyle LeafNodeStyle { get { if (leafNodeStyle == null) { leafNodeStyle = new TreeNodeStyle (); if (IsTrackingViewState) leafNodeStyle.TrackViewState(); } return leafNodeStyle; } } [DefaultValue (null)] [WebCategory ("Styles")] [PersistenceMode (PersistenceMode.InnerProperty)] [Editor ("System.Web.UI.Design.WebControls.TreeNodeStyleCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)] public TreeNodeStyleCollection LevelStyles { get { if (levelStyles == null) { levelStyles = new TreeNodeStyleCollection (); if (IsTrackingViewState) ((IStateManager)levelStyles).TrackViewState(); } return levelStyles; } } [DefaultValue ("")] public string LineImagesFolder { get { return ViewState.GetString ("LineImagesFolder", ""); } set { ViewState["LineImagesFolder"] = value; } } [DefaultValue (-1)] public int MaxDataBindDepth { get { return ViewState.GetInt ("MaxDataBindDepth", -1); } set { ViewState["MaxDataBindDepth"] = value; } } [DefaultValue (20)] public int NodeIndent { get { return ViewState.GetInt ("NodeIndent", 20); } set { ViewState["NodeIndent"] = value; } } [PersistenceMode (PersistenceMode.InnerProperty)] [Editor ("System.Web.UI.Design.WebControls.TreeNodeCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)] [DefaultValueAttribute (null)] [MergablePropertyAttribute (false)] public TreeNodeCollection Nodes { get { if (nodes == null) { nodes = new TreeNodeCollection (this); if (IsTrackingViewState) ((IStateManager)nodes).TrackViewState(); } return nodes; } } [PersistenceMode (PersistenceMode.InnerProperty)] [NotifyParentProperty (true)] [DefaultValue (null)] [WebCategory ("Styles")] [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] public TreeNodeStyle NodeStyle { get { if (nodeStyle == null) { nodeStyle = new TreeNodeStyle (); if (IsTrackingViewState) nodeStyle.TrackViewState(); } return nodeStyle; } } [DefaultValue (false)] public bool NodeWrap { get { return ViewState.GetBool ("NodeWrap", false); } set { ViewState ["NodeWrap"] = value; } } [UrlProperty] [DefaultValue ("")] [WebSysDescription ("The url of the image to show for leaf nodes.")] [WebCategory ("Appearance")] [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)] public string NoExpandImageUrl { get { return ViewState.GetString ("NoExpandImageUrl", ""); } set { ViewState ["NoExpandImageUrl"] = value; } } [PersistenceMode (PersistenceMode.InnerProperty)] [NotifyParentProperty (true)] [DefaultValue (null)] [WebCategory ("Styles")] [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] public TreeNodeStyle ParentNodeStyle { get { if (parentNodeStyle == null) { parentNodeStyle = new TreeNodeStyle (); if (IsTrackingViewState) parentNodeStyle.TrackViewState(); } return parentNodeStyle; } } [DefaultValue ('/')] public char PathSeparator { get { return ViewState.GetChar ("PathSeparator", '/'); } set { ViewState ["PathSeparator"] = value; } } [DefaultValue (true)] public bool PopulateNodesFromClient { get { return ViewState.GetBool ("PopulateNodesFromClient", true); } set { ViewState ["PopulateNodesFromClient"] = value; } } [PersistenceMode (PersistenceMode.InnerProperty)] [NotifyParentProperty (true)] [DefaultValue (null)] [WebCategory ("Styles")] [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] public TreeNodeStyle RootNodeStyle { get { if (rootNodeStyle == null) { rootNodeStyle = new TreeNodeStyle (); if (IsTrackingViewState) rootNodeStyle.TrackViewState(); } return rootNodeStyle; } } [PersistenceMode (PersistenceMode.InnerProperty)] [NotifyParentProperty (true)] [DefaultValue (null)] [WebCategory ("Styles")] [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] public TreeNodeStyle SelectedNodeStyle { get { if (selectedNodeStyle == null) { selectedNodeStyle = new TreeNodeStyle (); if (IsTrackingViewState) selectedNodeStyle.TrackViewState(); } return selectedNodeStyle; } } [DefaultValue (TreeNodeTypes.None)] public TreeNodeTypes ShowCheckBoxes { get { return (TreeNodeTypes)ViewState.GetInt ("ShowCheckBoxes", (int)TreeNodeTypes.None); } set { if (!Enum.IsDefined (typeof (TreeNodeTypes), value)) throw new ArgumentOutOfRangeException (); ViewState ["ShowCheckBoxes"] = value; } } [DefaultValue (true)] public bool ShowExpandCollapse { get { return ViewState.GetBool ("ShowExpandCollapse", true); } set { ViewState ["ShowExpandCollapse"] = value; } } [DefaultValue (false)] public bool ShowLines { get { return ViewState.GetBool ("ShowLines", false); } set { ViewState ["ShowLines"] = value; } } [Localizable (true)] public string SkipLinkText { get { return ViewState.GetString ("SkipLinkText", "Skip Navigation Links."); } set { ViewState ["SkipLinkText"] = value; } } [Browsable (false)] [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] public TreeNode SelectedNode { get { return selectedNode; } } [Browsable (false)] [DefaultValue ("")] [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] public string SelectedValue { get { return selectedNode != null ? selectedNode.Value : ""; } } [DefaultValue ("")] public string Target { get { return ViewState.GetString ("Target", ""); } set { ViewState ["Target"] = value; } } [MonoTODO ("why override?")] public override bool Visible { get { return base.Visible; } set { base.Visible = value; } } [Browsable (false)] [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] public TreeNodeCollection CheckedNodes { get { TreeNodeCollection col = new TreeNodeCollection (); FindCheckedNodes (Nodes, col); return col; } } void FindCheckedNodes (TreeNodeCollection nodeList, TreeNodeCollection result) { foreach (TreeNode node in nodeList) { if (node.Checked) result.Add (node); FindCheckedNodes (node.ChildNodes, result); } } public void ExpandAll () { foreach (TreeNode node in Nodes) node.ExpandAll (); } public void CollapseAll () { foreach (TreeNode node in Nodes) node.CollapseAll (); } public TreeNode FindNode (string valuePath) { if (valuePath == null) throw new ArgumentNullException ("valuePath"); string[] path = valuePath.Split (PathSeparator); int n = 0; TreeNodeCollection col = Nodes; bool foundBranch = true; while (col.Count > 0 && foundBranch) { foundBranch = false; foreach (TreeNode node in col) { if (node.Value == path [n]) { if (++n == path.Length) return node; col = node.ChildNodes; foundBranch = true; break; } } } return null; } ImageStyle GetImageStyle () { if (ImageSet != TreeViewImageSet.Custom) return (ImageStyle) imageStyles [ImageSet]; else return null; } protected override HtmlTextWriterTag TagKey { get { return HtmlTextWriterTag.Div; } } protected internal virtual TreeNode CreateNode () { return new TreeNode (this); } public sealed override void DataBind () { base.DataBind (); } protected void SetNodeDataBound (TreeNode node, bool dataBound) { node.SetDataBound (dataBound); } protected void SetNodeDataPath (TreeNode node, string dataPath) { node.SetDataPath (dataPath); } protected void SetNodeDataItem (TreeNode node, object dataItem) { node.SetDataItem (dataItem); } protected internal override void OnInit (EventArgs e) { base.OnInit (e); } internal void SetSelectedNode (TreeNode node, bool loading) { if (selectedNode == node) return; if (selectedNode != null) selectedNode.SelectedFlag = false; selectedNode = node; selectedNode.SelectedFlag = true; if (!loading) OnSelectedNodeChanged (new TreeNodeEventArgs (selectedNode)); } internal void NotifyCheckChanged (TreeNode node) { OnTreeNodeCheckChanged (new TreeNodeEventArgs (node)); } internal void NotifyExpandedChanged (TreeNode node) { if (node.Expanded.HasValue && node.Expanded.Value) OnTreeNodeExpanded (new TreeNodeEventArgs (node)); else OnTreeNodeCollapsed (new TreeNodeEventArgs (node)); } internal void NotifyPopulateRequired (TreeNode node) { OnTreeNodePopulate (new TreeNodeEventArgs (node)); } protected override void TrackViewState() { EnsureDataBound (); base.TrackViewState(); if (hoverNodeStyle != null) { hoverNodeStyle.TrackViewState(); } if (leafNodeStyle != null) { leafNodeStyle.TrackViewState(); } if (levelStyles != null) { ((IStateManager)levelStyles).TrackViewState(); } if (nodeStyle != null) { nodeStyle.TrackViewState(); } if (parentNodeStyle != null) { parentNodeStyle.TrackViewState(); } if (rootNodeStyle != null) { rootNodeStyle.TrackViewState(); } if (selectedNodeStyle != null) { selectedNodeStyle.TrackViewState(); } if (dataBindings != null) { ((IStateManager)dataBindings).TrackViewState (); } if (nodes != null) { ((IStateManager)nodes).TrackViewState();; } } protected override object SaveViewState() { object[] states = new object [10]; states[0] = base.SaveViewState(); states[1] = (hoverNodeStyle == null ? null : hoverNodeStyle.SaveViewState()); states[2] = (leafNodeStyle == null ? null : leafNodeStyle.SaveViewState()); states[3] = (levelStyles == null ? null : ((IStateManager)levelStyles).SaveViewState()); states[4] = (nodeStyle == null ? null : nodeStyle.SaveViewState()); states[5] = (parentNodeStyle == null ? null : parentNodeStyle.SaveViewState()); states[6] = (rootNodeStyle == null ? null : rootNodeStyle.SaveViewState()); states[7] = (selectedNodeStyle == null ? null : selectedNodeStyle.SaveViewState()); states[8] = (dataBindings == null ? null : ((IStateManager)dataBindings).SaveViewState()); states[9] = (nodes == null ? null : ((IStateManager)nodes).SaveViewState()); for (int i = states.Length - 1; i >= 0; i--) { if (states [i] != null) return states; } return null; } protected override void LoadViewState (object savedState) { if (savedState == null) return; object [] states = (object []) savedState; base.LoadViewState (states[0]); if (states[1] != null) HoverNodeStyle.LoadViewState (states[1]); if (states[2] != null) LeafNodeStyle.LoadViewState(states[2]); if (states[3] != null) ((IStateManager)LevelStyles).LoadViewState(states[3]); if (states[4] != null) NodeStyle.LoadViewState(states[4]); if (states[5] != null) ParentNodeStyle.LoadViewState(states[5]); if (states[6] != null) RootNodeStyle.LoadViewState(states[6]); if (states[7] != null) SelectedNodeStyle.LoadViewState(states[7]); if (states[8] != null) ((IStateManager)DataBindings).LoadViewState(states[8]); if (states[9] != null) ((IStateManager)Nodes).LoadViewState(states[9]); } protected virtual void RaisePostBackEvent (string eventArgument) { string[] args = eventArgument.Split ('|'); TreeNode node = FindNodeByPos (args[1]); if (node == null) return; if (args [0] == "sel") HandleSelectEvent (node); else if (args [0] == "ec") HandleExpandCollapseEvent (node); } void HandleSelectEvent (TreeNode node) { switch (node.SelectAction) { case TreeNodeSelectAction.Select: node.Select (); break; case TreeNodeSelectAction.Expand: node.Expand (); break; case TreeNodeSelectAction.SelectExpand: node.Select (); node.Expand (); break; } } void HandleExpandCollapseEvent (TreeNode node) { node.ToggleExpandState (); } protected virtual void RaisePostDataChangedEvent () { } string callbackResult; protected virtual void RaiseCallbackEvent (string eventArgs) { RequiresDataBinding = true; EnsureDataBound (); TreeNode node = FindNodeByPos (eventArgs); ArrayList levelLines = new ArrayList (); TreeNode nd = node; while (nd != null) { int childCount = nd.Parent != null ? nd.Parent.ChildNodes.Count : Nodes.Count; levelLines.Insert (0, (nd.Index < childCount - 1) ? this : null); nd = nd.Parent; } StringWriter sw = new StringWriter (); HtmlTextWriter writer = new HtmlTextWriter (sw); node.Expanded = true; int num = node.ChildNodes.Count; for (int n=0; n= 0 && child.Depth == MaxDataBindDepth) continue; if (hdata == null || !hdata.HasChildren) continue; IHierarchicalEnumerable e = hdata.GetChildren (); FillBoundChildrenRecursive (e, child.ChildNodes); } } protected virtual bool LoadPostData (string postDataKey, NameValueCollection postCollection) { bool res = false; if (PopulateNodesFromClient) { string states = postCollection [ClientID + "_PopulatedStates"]; if (states != null) { foreach (string id in states.Split ('|')) { if (String.IsNullOrEmpty(id)) continue; TreeNode node = FindNodeByPos (id); if (node != null && node.PopulateOnDemand && !node.Populated) node.Populate(); } } res = true; } if (ShowCheckBoxes != TreeNodeTypes.None) { UnsetCheckStates (Nodes, postCollection); SetCheckStates (postCollection); res = true; } if (EnableClientScript) { string states = postCollection [ClientID + "_ExpandStates"]; if (states != null) { string[] ids = states.Split ('|'); UnsetExpandStates (Nodes, ids); SetExpandStates (ids); } else UnsetExpandStates (Nodes, new string[0]); res = true; } return res; } protected internal override void OnPreRender (EventArgs e) { base.OnPreRender (e); cssStylesRegistered = false; ControlStyle.AlwaysRenderTextDecoration = true; if (Page != null) { if (Enabled) Page.RegisterRequiresPostBack (this); if (EnableClientScript && !Page.ClientScript.IsClientScriptIncludeRegistered (typeof(TreeView), "TreeView.js")) { string url = Page.ClientScript.GetWebResourceUrl (typeof(TreeView), "TreeView.js"); Page.ClientScript.RegisterClientScriptInclude (typeof(TreeView), "TreeView.js", url); } if (Page.Header != null) { cssStylesRegistered = true; ControlStyle.Font.Underline = false; Page.Header.StyleSheet.RegisterStyle(ControlStyle, this); if (levelStyles != null) for (int i = 0; i < levelStyles.Count; i++) Page.Header.StyleSheet.RegisterStyle(levelStyles[i], this); } } string ctree = ClientID + "_data"; string script = string.Format ("var {0} = new Object ();\n", ctree); script += string.Format ("{0}.showImage = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (ShowExpandCollapse)); if (ShowExpandCollapse) { bool defaultImages = ShowLines || ImageSet != TreeViewImageSet.Custom || (ExpandImageUrl == "" && CollapseImageUrl == ""); script += string.Format ("{0}.defaultImages = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (defaultImages)); ImageStyle imageStyle = GetImageStyle (); if (!defaultImages) { script += string.Format ("{0}.expandImage = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (GetNodeImageUrl ("plus", imageStyle))); script += string.Format ("{0}.collapseImage = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (GetNodeImageUrl ("minus", imageStyle))); } if (PopulateNodesFromClient) script += string.Format ("{0}.noExpandImage = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (GetNodeImageUrl ("noexpand", imageStyle))); } if (Page != null) { script += string.Format ("{0}.populateFromClient = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (PopulateNodesFromClient)); script += string.Format ("{0}.expandAlt = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (GetNodeImageToolTip (true, null))); script += string.Format ("{0}.collapseAlt = {1};\n", ctree, ClientScriptManager.GetScriptLiteral (GetNodeImageToolTip (false, null))); Page.ClientScript.RegisterStartupScript (typeof(TreeView), this.UniqueID, script, true); if (!Page.IsPostBack) { SetNodesExpandedToDepthRecursive (Nodes); } if (EnableClientScript) { Page.ClientScript.RegisterHiddenField (ClientID + "_ExpandStates", GetExpandStates ()); // Make sure the basic script infrastructure is rendered Page.ClientScript.GetCallbackEventReference (this, "null", "", "null"); Page.ClientScript.GetPostBackClientHyperlink (this, ""); } if (PopulateNodesFromClient) { Page.ClientScript.RegisterHiddenField (ClientID + "_PopulatedStates", "|"); } } } void SetNodesExpandedToDepthRecursive (TreeNodeCollection nodes) { foreach (TreeNode node in nodes) { if (!node.Expanded.HasValue) { if (ExpandDepth < 0 || node.Depth < ExpandDepth) node.Expanded = true; } SetNodesExpandedToDepthRecursive (node.ChildNodes); } } string GetBindingKey (string dataMember, int depth) { return dataMember + " " + depth; } void InitializeDataBindings () { if (dataBindings != null && dataBindings.Count > 0) { bindings = new Hashtable (); foreach (TreeNodeBinding bin in dataBindings) { string key = GetBindingKey (bin.DataMember, bin.Depth); bindings [key] = bin; } } else bindings = null; } internal TreeNodeBinding FindBindingForNode (string type, int depth) { if (bindings == null) return null; TreeNodeBinding bin = (TreeNodeBinding) bindings [GetBindingKey (type, depth)]; if (bin != null) return bin; bin = (TreeNodeBinding) bindings [GetBindingKey (type, -1)]; if (bin != null) return bin; bin = (TreeNodeBinding) bindings [GetBindingKey ("", depth)]; if (bin != null) return bin; return (TreeNodeBinding) bindings [GetBindingKey ("", -1)]; } internal void DecorateNode(TreeNode node) { if (node == null) return; if (node.ImageUrl != null && node.ImageUrl.Length > 0) return; if (node.IsRootNode && rootNodeStyle != null) { node.ImageUrl = rootNodeStyle.ImageUrl; return; } if (node.IsParentNode && parentNodeStyle != null) { node.ImageUrl = parentNodeStyle.ImageUrl; return; } if (node.IsLeafNode && leafNodeStyle != null) node.ImageUrl = leafNodeStyle.ImageUrl; } protected internal override void RenderContents (HtmlTextWriter writer) { ArrayList levelLines = new ArrayList (); int num = Nodes.Count; for (int n=0; n0, n 0; else hasChildNodes = (node.PopulateOnDemand && !node.Populated) || node.ChildNodes.Count > 0; writer.AddAttribute ("cellpadding", "0"); writer.AddAttribute ("cellspacing", "0"); writer.AddStyleAttribute ("border-width", "0"); writer.RenderBeginTag (HtmlTextWriterTag.Table); writer.RenderBeginTag (HtmlTextWriterTag.Tr); // Vertical lines from previous levels for (int n=0; n 0 && node.Parent != null) || (ShowCheckBoxes == TreeNodeTypes.Root && node.Parent == null && node.ChildNodes.Count > 0); if (showChecks) { AddNodeStyle (writer, node, level); writer.RenderBeginTag (HtmlTextWriterTag.Td); // TD writer.AddAttribute ("name", ClientID + "_cs_" + node.Path); writer.AddAttribute ("type", "checkbox"); if (node.Checked) writer.AddAttribute ("checked", "checked"); writer.RenderBeginTag (HtmlTextWriterTag.Input); // INPUT writer.RenderEndTag (); // INPUT writer.RenderEndTag (); // TD } // Text if (!NodeWrap) writer.AddAttribute ("nowrap", "nowrap"); writer.RenderBeginTag (HtmlTextWriterTag.Td); // TD node.BeginRenderText (writer); AddNodeStyle (writer, node, level); if (clientExpand) writer.AddAttribute ("id", GetNodeClientId (node, "txt")); BeginNodeTag (writer, node, clientExpand); writer.Write (node.Text); writer.RenderEndTag (); // style tag node.EndRenderText (writer); writer.RenderEndTag (); // TD writer.RenderEndTag (); // TR writer.RenderEndTag (); // TABLE // Children if (hasChildNodes) { if (level >= levelLines.Count) { if (hasNext) levelLines.Add (this); else levelLines.Add (null); } else { if (hasNext) levelLines [level] = this; else levelLines [level] = null; } if (clientExpand) { if (!(node.Expanded.HasValue && node.Expanded.Value)) writer.AddStyleAttribute ("display", "none"); else writer.AddStyleAttribute ("display", "block"); writer.AddAttribute ("id", GetNodeClientId (node, null)); writer.RenderBeginTag (HtmlTextWriterTag.Span); if (renderChildNodes) { int num = node.ChildNodes.Count; for (int n=0; n= Nodes.Count) return null; node = Nodes [i]; } else { if (i >= node.ChildNodes.Count) return null; node = node.ChildNodes [i]; } } return node; } void UnsetCheckStates (TreeNodeCollection col, NameValueCollection states) { foreach (TreeNode node in col) { if (node.Checked) { string val = states [ClientID + "_cs_" + node.Path]; if (val != "on") node.Checked = false; } if (node.HasChildData) UnsetCheckStates (node.ChildNodes, states); } } void SetCheckStates (NameValueCollection states) { string keyPrefix = ClientID + "_cs_"; foreach (string key in states) { if (key.StartsWith (keyPrefix)) { string id = key.Substring (keyPrefix.Length); TreeNode node = FindNodeByPos (id); if (node != null) node.Checked = (Context.Request.Form [key] == "on"); } } } void UnsetExpandStates (TreeNodeCollection col, string[] states) { foreach (TreeNode node in col) { if (node.Expanded.HasValue && node.Expanded.Value) { bool expand = (Array.IndexOf (states, node.Path) != -1); if (!expand) node.Expanded = false; } if (node.HasChildData) UnsetExpandStates (node.ChildNodes, states); } } void SetExpandStates (string[] states) { foreach (string id in states) { if (id == null || id == "") continue; TreeNode node = FindNodeByPos (id); if (node != null) node.Expanded = true; } } string GetExpandStates () { StringBuilder sb = new StringBuilder ("|"); foreach (TreeNode node in Nodes) GetExpandStates (sb, node); return sb.ToString (); } void GetExpandStates (StringBuilder sb, TreeNode node) { if (node.Expanded.HasValue && node.Expanded.Value) { sb.Append (node.Path); sb.Append ('|'); } if (node.HasChildData) { foreach (TreeNode child in node.ChildNodes) GetExpandStates (sb, child); } } } } #endif