Xamarin Public Jenkins (auto-signing) 966bba02bb Imported Upstream version 5.2.0.175
Former-commit-id: bb0468d0f257ff100aa895eb5fe583fb5dfbf900
2017-06-07 13:16:24 +00:00

1985 lines
62 KiB
C#

//
// 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)
//
using System.Collections;
using System.Text;
using System.ComponentModel;
using System.Globalization;
using System.Web.Handlers;
using System.Collections.Specialized;
using System.IO;
using System.Security.Permissions;
using System.Collections.Generic;
using System.Web.Util;
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
{
static readonly char[] postDataSplitChars = {'|'};
string activeSiteMapPath;
bool stylesPrepared;
Style hoverNodeStyle;
TreeNodeStyle leafNodeStyle;
TreeNodeStyle nodeStyle;
TreeNodeStyle parentNodeStyle;
TreeNodeStyle rootNodeStyle;
TreeNodeStyle selectedNodeStyle;
TreeNodeStyleCollection levelStyles;
TreeNodeCollection nodes;
TreeNodeBindingCollection dataBindings;
TreeNode selectedNode;
Hashtable bindings;
int registeredStylesCounter = -1;
List<Style> levelLinkStyles;
Style controlLinkStyle;
Style nodeLinkStyle;
Style rootNodeLinkStyle;
Style parentNodeLinkStyle;
Style leafNodeLinkStyle;
Style selectedNodeLinkStyle;
Style hoverNodeLinkStyle;
static readonly object TreeNodeCheckChangedEvent = new object();
static readonly object SelectedNodeChangedEvent = new object();
static readonly object TreeNodeCollapsedEvent = new object();
static readonly object TreeNodeDataBoundEvent = new object();
static readonly object TreeNodeExpandedEvent = new object();
static readonly object TreeNodePopulateEvent = new object();
static Hashtable imageStyles = new Hashtable ();
class TreeViewExpandDepthConverter : TypeConverter
{
public override bool CanConvertFrom (ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof (string) || sourceType == typeof (int))
return true;
return base.CanConvertFrom (context, sourceType);
}
public override bool CanConvertTo (ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof (string) || destinationType == typeof (int))
return true;
return base.CanConvertTo (context, destinationType);
}
public override object ConvertTo (ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType != typeof (int) && destinationType != typeof (string))
return base.ConvertTo (context, culture, value, destinationType);
if (value is string) {
if (destinationType == typeof (int)) {
if (String.Compare ("FullyExpand", (string)value, StringComparison.OrdinalIgnoreCase) == 0)
return -1;
try {
return Int32.Parse ((string)value);
} catch (Exception) {
return -1;
}
} else
return value;
}
int val = (int)value;
if (destinationType == typeof (string)) {
if (val == -1)
return "FullyExpand";
return val.ToString ();
}
return value;
}
public override object ConvertFrom (ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (!(value is string) && !(value is int))
return base.ConvertFrom (context, culture, value);
if (value is string) {
if (String.Compare ("FullyExpand", (string)value, StringComparison.OrdinalIgnoreCase) == 0)
return -1;
try {
return Int32.Parse ((string)value);
} catch (Exception) {
return null;
}
}
return value;
}
}
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 (null, null, null, "warning", "warning", "warning");
imageStyles [TreeViewImageSet.Inbox] = new ImageStyle (null, null, null, "inbox", "inbox", "inbox");
imageStyles [TreeViewImageSet.Msdn] = new ImageStyle ("box_plus", "box_minus", "box_noexpand", null, null, null);
imageStyles [TreeViewImageSet.Simple] = new ImageStyle (null, null, "box_full", null, null, null);
imageStyles [TreeViewImageSet.Simple2] = new ImageStyle (null, null, "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", "folder", "file", "computer");
}
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", String.Empty); }
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", String.Empty); }
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", String.Empty); }
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", String.Empty); }
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;
}
}
Style ControlLinkStyle {
get {
if (controlLinkStyle == null) {
controlLinkStyle = new Style ();
controlLinkStyle.AlwaysRenderTextDecoration = true;
}
return controlLinkStyle;
}
}
Style NodeLinkStyle {
get {
if (nodeLinkStyle == null) {
nodeLinkStyle = new Style ();
}
return nodeLinkStyle;
}
}
Style RootNodeLinkStyle {
get {
if (rootNodeLinkStyle == null)
rootNodeLinkStyle = new Style ();
return rootNodeLinkStyle;
}
}
Style ParentNodeLinkStyle {
get {
if (parentNodeLinkStyle == null)
parentNodeLinkStyle = new Style ();
return parentNodeLinkStyle;
}
}
Style SelectedNodeLinkStyle {
get {
if (selectedNodeLinkStyle == null)
selectedNodeLinkStyle = new Style ();
return selectedNodeLinkStyle;
}
}
Style LeafNodeLinkStyle {
get {
if (leafNodeLinkStyle == null)
leafNodeLinkStyle = new Style ();
return leafNodeLinkStyle;
}
}
Style HoverNodeLinkStyle {
get {
if (hoverNodeLinkStyle == null)
hoverNodeLinkStyle = new Style ();
return hoverNodeLinkStyle;
}
}
[DefaultValue (TreeNodeTypes.None)]
public TreeNodeTypes ShowCheckBoxes {
get { return (TreeNodeTypes)ViewState.GetInt ("ShowCheckBoxes", (int)TreeNodeTypes.None); }
set {
if ((int) value > 7)
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 : String.Empty; }
}
[DefaultValue ("")]
public string Target {
get { return ViewState.GetString ("Target", String.Empty); }
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, false);
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;
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 if (node.Expanded.HasValue && node.IsParentNode)
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 && levelStyles.Count > 0)
((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 state)
{
if (state == null)
return;
object [] states = (object []) state;
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)
{
ValidateEvent (UniqueID, 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 ()
{
}
TreeNode MakeNodeTree (string[] args)
{
string[] segments = args [0].Split ('_');
TreeNode ret = null, node;
foreach (string seg in segments) {
int idx = Int32.Parse (seg);
node = new TreeNode (seg);
if (ret != null) {
ret.ChildNodes.Add (node);
node.Index = idx;
}
ret = node;
}
ret.Value = args [1].Replace ("U+007C", "|");
ret.ImageUrl = args [2].Replace ("U+007C", "|");
ret.NavigateUrl = args [3].Replace ("U+007C", "|");
ret.Target = args [4].Replace ("U+007C", "|");
ret.Tree = this;
NotifyPopulateRequired (ret);
return ret;
}
string callbackResult;
protected virtual void RaiseCallbackEvent (string eventArgument)
{
string[] args = eventArgument.Split ('|');
RequiresDataBinding = true;
EnsureDataBound ();
TreeNode node = MakeNodeTree (args);
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);
EnsureStylesPrepared ();
node.Expanded = true;
int num = node.ChildNodes.Count;
for (int n=0; n<num; n++)
RenderNode (writer, node.ChildNodes [n], node.Depth + 1, levelLines, true, n<num-1);
string res = sw.ToString ();
callbackResult = res.Length > 0 ? res : "*";
}
protected virtual string GetCallbackResult ()
{
return callbackResult;
}
void IPostBackEventHandler.RaisePostBackEvent (string eventArgument)
{
RaisePostBackEvent (eventArgument);
}
bool IPostBackDataHandler.LoadPostData (string postDataKey, NameValueCollection postCollection)
{
return LoadPostData (postDataKey, postCollection);
}
void IPostBackDataHandler.RaisePostDataChangedEvent ()
{
RaisePostDataChangedEvent ();
}
void ICallbackEventHandler.RaiseCallbackEvent (string eventArgs)
{
RaiseCallbackEvent (eventArgs);
}
string ICallbackEventHandler.GetCallbackResult ()
{
return GetCallbackResult ();
}
protected override ControlCollection CreateControlCollection ()
{
return new EmptyControlCollection (this);
}
protected internal override void PerformDataBinding ()
{
base.PerformDataBinding ();
InitializeDataBindings ();
HierarchicalDataSourceView data = GetData (String.Empty);
if (data == null)
return;
Nodes.Clear ();
IHierarchicalEnumerable e = data.Select ();
FillBoundChildrenRecursive (e, Nodes);
}
void FillBoundChildrenRecursive (IHierarchicalEnumerable hEnumerable, TreeNodeCollection nodeCollection)
{
if (hEnumerable == null)
return;
foreach (object obj in hEnumerable) {
IHierarchyData hdata = hEnumerable.GetHierarchyData (obj);
TreeNode child = new TreeNode ();
nodeCollection.Add (child);
child.Bind (hdata);
OnTreeNodeDataBound (new TreeNodeEventArgs (child));
if (MaxDataBindDepth >= 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 (EnableClientScript && PopulateNodesFromClient) {
string states = postCollection [ClientID + "_PopulatedStates"];
if (states != null) {
foreach (string id in states.Split (postDataSplitChars, StringSplitOptions.RemoveEmptyEntries)) {
TreeNode node = FindNodeByPos (id);
if (node != null && node.PopulateOnDemand && !node.Populated) {
Page page = Page;
if (page != null && page.IsCallback)
node.Populated = true; // Bug #492307
else
node.Populate (); // Bug #626829
}
}
}
res = true;
}
UnsetCheckStates (Nodes, postCollection);
SetCheckStates (postCollection);
if (EnableClientScript) {
string states = postCollection [ClientID + "_ExpandStates"];
if (states != null) {
string[] ids = states.Split (postDataSplitChars, StringSplitOptions.RemoveEmptyEntries);
UnsetExpandStates (Nodes, ids);
SetExpandStates (ids);
} else
UnsetExpandStates (Nodes, new string[0]);
res = true;
}
return res;
}
const string _OnPreRender_Script_Preamble =
"var {0} = new Object ();\n" +
"{0}.treeId = {1};\n" +
"{0}.uid = {2};\n" +
"{0}.showImage = {3};\n";
const string _OnPreRender_Script_ShowExpandCollapse =
"{0}.expandImage = {1};\n" +
"{0}.collapseImage = {2};\n";
const string _OnPreRender_Script_ShowExpandCollapse_Populate =
"{0}.noExpandImage = {1};\n";
const string _OnPreRender_Script_PopulateCallback =
"{0}.form = {1};\n" +
"{0}.PopulateNode = function (nodeId, nodeValue, nodeImageUrl, nodeNavigateUrl, nodeTarget) {{\n" +
"\t{2}.__theFormPostData = \"\";\n" +
"\t{2}.__theFormPostCollection = new Array ();\n" +
"\t{2}.WebForm_InitCallback ();\n" +
"\tTreeView_PopulateNode (this.uid, this.treeId, nodeId, nodeValue, nodeImageUrl, nodeNavigateUrl, nodeTarget)\n}};\n";
const string _OnPreRender_Script_CallbackOptions =
"{0}.populateFromClient = {1};\n" +
"{0}.expandAlt = {2};\n" +
"{0}.collapseAlt = {3};\n";
const string _OnPreRender_Script_HoverStyle =
"{0}.hoverClass = {1};\n" +
"{0}.hoverLinkClass = {2};\n";
protected internal override void OnPreRender (EventArgs e)
{
base.OnPreRender (e);
Page page = Page;
if (page != null) {
if (IsEnabled)
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);
}
}
string ctree = ClientID + "_data";
StringBuilder script = new StringBuilder ();
script.AppendFormat (_OnPreRender_Script_Preamble,
ctree,
ClientScriptManager.GetScriptLiteral (ClientID),
ClientScriptManager.GetScriptLiteral (UniqueID),
ClientScriptManager.GetScriptLiteral (ShowExpandCollapse));
if (ShowExpandCollapse) {
ImageStyle imageStyle = GetImageStyle ();
script.AppendFormat (_OnPreRender_Script_ShowExpandCollapse,
ctree,
ClientScriptManager.GetScriptLiteral (GetNodeImageUrl ("plus", imageStyle)),
ClientScriptManager.GetScriptLiteral (GetNodeImageUrl ("minus", imageStyle)));
if (PopulateNodesFromClient)
script.AppendFormat (_OnPreRender_Script_ShowExpandCollapse_Populate,
ctree,
ClientScriptManager.GetScriptLiteral (GetNodeImageUrl ("noexpand", imageStyle)));
}
if (page != null) {
script.AppendFormat (_OnPreRender_Script_PopulateCallback,
ctree,
page.theForm,
page.WebFormScriptReference);
// Page.ClientScript.GetCallbackEventReference (
// "this.uid", "nodeId",
// "TreeView_PopulateCallback",
// "this.treeId + \" \" + nodeId", "TreeView_PopulateCallback", false));
script.AppendFormat (_OnPreRender_Script_CallbackOptions,
ctree,
ClientScriptManager.GetScriptLiteral (PopulateNodesFromClient),
ClientScriptManager.GetScriptLiteral (GetNodeImageToolTip (true, null)),
ClientScriptManager.GetScriptLiteral (GetNodeImageToolTip (false, null)));
if (!page.IsPostBack)
SetNodesExpandedToDepthRecursive (Nodes);
bool enableClientScript = EnableClientScript;
if (enableClientScript) {
page.ClientScript.RegisterHiddenField (ClientID + "_ExpandStates", GetExpandStates ());
// Make sure the basic script infrastructure is rendered
page.ClientScript.RegisterWebFormClientScript ();
}
if (enableClientScript && PopulateNodesFromClient)
page.ClientScript.RegisterHiddenField (ClientID + "_PopulatedStates", "|");
EnsureStylesPrepared ();
if (hoverNodeStyle != null) {
if (page.Header == null)
throw new InvalidOperationException ("Using TreeView.HoverNodeStyle requires Page.Header to be non-null (e.g. <head runat=\"server\" />).");
RegisterStyle (HoverNodeStyle, HoverNodeLinkStyle);
script.AppendFormat (_OnPreRender_Script_HoverStyle,
ctree,
ClientScriptManager.GetScriptLiteral (HoverNodeStyle.RegisteredCssClass),
ClientScriptManager.GetScriptLiteral (HoverNodeLinkStyle.RegisteredCssClass));
}
page.ClientScript.RegisterStartupScript (typeof(TreeView), this.UniqueID, script.ToString (), true);
script = null;
}
}
void EnsureStylesPrepared ()
{
if (stylesPrepared)
return;
stylesPrepared = true;
PrepareStyles ();
}
void PrepareStyles ()
{
// The order in which styles are defined matters when more than one class
// is assigned to an element
ControlLinkStyle.CopyTextStylesFrom (ControlStyle);
RegisterStyle (ControlLinkStyle);
if (nodeStyle != null)
RegisterStyle (NodeStyle, NodeLinkStyle);
if (rootNodeStyle != null)
RegisterStyle (RootNodeStyle, RootNodeLinkStyle);
if (parentNodeStyle != null)
RegisterStyle (ParentNodeStyle, ParentNodeLinkStyle);
if (leafNodeStyle != null)
RegisterStyle (LeafNodeStyle, LeafNodeLinkStyle);
if (levelStyles != null && levelStyles.Count > 0) {
levelLinkStyles = new List<Style> (levelStyles.Count);
foreach (Style style in levelStyles) {
Style linkStyle = new Style ();
levelLinkStyles.Add (linkStyle);
RegisterStyle (style, linkStyle);
}
}
if (selectedNodeStyle != null)
RegisterStyle (SelectedNodeStyle, SelectedNodeLinkStyle);
}
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 IncrementStyleClassName ()
{
registeredStylesCounter++;
return ClientID + "_" + registeredStylesCounter;
}
void RegisterStyle (Style baseStyle, Style linkStyle)
{
linkStyle.CopyTextStylesFrom (baseStyle);
linkStyle.BorderStyle = BorderStyle.None;
linkStyle.AddCssClass (baseStyle.CssClass);
baseStyle.Font.Reset ();
RegisterStyle (linkStyle);
RegisterStyle (baseStyle);
}
void RegisterStyle (Style baseStyle)
{
if (Page.Header == null)
return;
string className = IncrementStyleClassName ().Trim ('_');
baseStyle.SetRegisteredCssClass (className);
Page.Header.StyleSheet.CreateStyleRule (baseStyle, this, "." + className);
}
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);
if (!bindings.ContainsKey(key))
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 (String.Empty, depth)];
if (bin != null)
return bin;
return (TreeNodeBinding) bindings [GetBindingKey (String.Empty, -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)
{
SiteMapDataSource siteMap = GetDataSource () as SiteMapDataSource;
bool checkSitePath = IsBoundUsingDataSourceID && siteMap != null;
if (checkSitePath) {
IHierarchyData data = siteMap.Provider.CurrentNode;
if (data != null)
activeSiteMapPath = data.Path;
}
ArrayList levelLines = new ArrayList ();
int num = Nodes.Count;
for (int n=0; n<num; n++)
RenderNode (writer, Nodes [n], 0, levelLines, n>0, n<num-1);
}
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
base.AddAttributesToRender (writer);
}
public override void RenderBeginTag (HtmlTextWriter writer)
{
string skipLinkText = SkipLinkText;
if (!String.IsNullOrEmpty (skipLinkText)) {
writer.AddAttribute (HtmlTextWriterAttribute.Href, "#" + ClientID + "_SkipLink");
writer.RenderBeginTag (HtmlTextWriterTag.A);
ClientScriptManager csm = new ClientScriptManager (null);
writer.AddAttribute (HtmlTextWriterAttribute.Alt, skipLinkText);
writer.AddAttribute (HtmlTextWriterAttribute.Src, csm.GetWebResourceUrl (typeof (SiteMapPath), "transparent.gif"));
writer.AddAttribute (HtmlTextWriterAttribute.Height, "0");
writer.AddAttribute (HtmlTextWriterAttribute.Width, "0");
writer.AddStyleAttribute (HtmlTextWriterStyle.BorderWidth, "0px");
writer.RenderBeginTag (HtmlTextWriterTag.Img);
writer.RenderEndTag (); // img
writer.RenderEndTag (); // a
}
base.RenderBeginTag (writer);
}
public override void RenderEndTag (HtmlTextWriter writer)
{
base.RenderEndTag (writer);
if (!String.IsNullOrEmpty (SkipLinkText)) {
writer.AddAttribute (HtmlTextWriterAttribute.Id, ClientID + "_SkipLink");
writer.RenderBeginTag (HtmlTextWriterTag.A);
writer.RenderEndTag ();
}
}
void RenderNode (HtmlTextWriter writer, TreeNode node, int level, ArrayList levelLines, bool hasPrevious, bool hasNext)
{
// FIXME: disabled for now - needs closer investigation
//if (node.PopulateOnDemand && node.HadChildrenBeforePopulating)
// throw new InvalidOperationException ("PopulateOnDemand cannot be set to true on a node that already has children.");
DecorateNode(node);
string nodeImage;
bool clientExpand = EnableClientScript && Events [TreeNodeCollapsedEvent] == null && Events [TreeNodeExpandedEvent] == null;
ImageStyle imageStyle = GetImageStyle ();
bool renderChildNodes = node.Expanded.HasValue && node.Expanded.Value;
if (clientExpand && !renderChildNodes)
renderChildNodes = (!node.PopulateOnDemand || node.Populated);
bool hasChildNodes;
if (renderChildNodes)
hasChildNodes = node.ChildNodes.Count > 0;
else
hasChildNodes = (node.PopulateOnDemand && !node.Populated) || node.ChildNodes.Count > 0;
writer.AddAttribute (HtmlTextWriterAttribute.Cellpadding, "0", false);
writer.AddAttribute (HtmlTextWriterAttribute.Cellspacing, "0", false);
writer.AddStyleAttribute (HtmlTextWriterStyle.BorderWidth, "0");
writer.RenderBeginTag (HtmlTextWriterTag.Table);
writer.RenderBeginTag (HtmlTextWriterTag.Tr);
// Vertical lines from previous levels
nodeImage = GetNodeImageUrl ("i", imageStyle);
for (int n=0; n<level; n++) {
writer.RenderBeginTag (HtmlTextWriterTag.Td);
writer.AddStyleAttribute (HtmlTextWriterStyle.Width, NodeIndent + "px");
writer.AddStyleAttribute (HtmlTextWriterStyle.Height, "1px");
writer.RenderBeginTag (HtmlTextWriterTag.Div);
if (ShowLines && levelLines [n] != null) {
writer.AddAttribute (HtmlTextWriterAttribute.Src, nodeImage);
writer.AddAttribute (HtmlTextWriterAttribute.Alt, String.Empty, false);
writer.RenderBeginTag (HtmlTextWriterTag.Img);
writer.RenderEndTag ();
}
writer.RenderEndTag ();
writer.RenderEndTag (); // TD
}
// Node image + line
bool showExpandCollapse = ShowExpandCollapse;
bool showLines = ShowLines;
if (showExpandCollapse || showLines) {
bool buttonImage = false;
string tooltip = String.Empty;
string shape = String.Empty;
if (showLines) {
if (hasPrevious && hasNext)
shape = "t";
else if (hasPrevious && !hasNext)
shape = "l";
else if (!hasPrevious && hasNext)
shape = "r";
else
shape = "dash";
}
if (showExpandCollapse) {
if (hasChildNodes) {
buttonImage = true;
if (node.Expanded.HasValue && node.Expanded.Value)
shape += "minus";
else
shape += "plus";
tooltip = GetNodeImageToolTip (!(node.Expanded.HasValue && node.Expanded.Value), node.Text);
} else if (!showLines)
shape = "noexpand";
}
if (!String.IsNullOrEmpty (shape)) {
nodeImage = GetNodeImageUrl (shape, imageStyle);
writer.RenderBeginTag (HtmlTextWriterTag.Td); // TD
if (buttonImage) {
if (!clientExpand || (!PopulateNodesFromClient && node.PopulateOnDemand && !node.Populated))
writer.AddAttribute (HtmlTextWriterAttribute.Href, GetClientEvent (node, "ec"));
else
writer.AddAttribute (HtmlTextWriterAttribute.Href, GetClientExpandEvent(node));
writer.RenderBeginTag (HtmlTextWriterTag.A); // Anchor
}
// tooltip is 'HtmlAttributeEncoded'
writer.AddAttribute (HtmlTextWriterAttribute.Alt, tooltip);
if (buttonImage && clientExpand)
writer.AddAttribute (HtmlTextWriterAttribute.Id, GetNodeClientId (node, "img"));
writer.AddAttribute (HtmlTextWriterAttribute.Src, nodeImage);
if (buttonImage)
writer.AddStyleAttribute (HtmlTextWriterStyle.BorderWidth, "0");
writer.RenderBeginTag (HtmlTextWriterTag.Img);
writer.RenderEndTag ();
if (buttonImage)
writer.RenderEndTag (); // Anchor
writer.RenderEndTag (); // TD
}
}
// Node icon
string imageUrl = node.ImageUrl.Length > 0 ? ResolveClientUrl (node.ImageUrl) : null;
if (String.IsNullOrEmpty (imageUrl) && imageStyle != null) {
if (imageStyle.RootIcon != null && node.IsRootNode)
imageUrl = GetNodeIconUrl (imageStyle.RootIcon);
else if (imageStyle.ParentIcon != null && node.IsParentNode)
imageUrl = GetNodeIconUrl (imageStyle.ParentIcon);
else if (imageStyle.LeafIcon != null && node.IsLeafNode)
imageUrl = GetNodeIconUrl (imageStyle.LeafIcon);
}
if (level < LevelStyles.Count && LevelStyles [level].ImageUrl != null)
imageUrl = ResolveClientUrl (LevelStyles [level].ImageUrl);
if (!String.IsNullOrEmpty (imageUrl)) {
writer.RenderBeginTag (HtmlTextWriterTag.Td); // TD
writer.AddAttribute (HtmlTextWriterAttribute.Tabindex, "-1");
BeginNodeTag (writer, node, clientExpand);
writer.AddAttribute (HtmlTextWriterAttribute.Src, imageUrl);
writer.AddStyleAttribute (HtmlTextWriterStyle.BorderWidth, "0");
writer.AddAttribute (HtmlTextWriterAttribute.Alt, node.ImageToolTip);
writer.RenderBeginTag (HtmlTextWriterTag.Img);
writer.RenderEndTag (); // IMG
writer.RenderEndTag (); // style tag
writer.RenderEndTag (); // TD
}
if (!NodeWrap)
writer.AddStyleAttribute (HtmlTextWriterStyle.WhiteSpace, "nowrap");
bool nodeIsSelected = node == SelectedNode && selectedNodeStyle != null;
if (!nodeIsSelected && selectedNodeStyle != null) {
if (!String.IsNullOrEmpty (activeSiteMapPath))
nodeIsSelected = String.Compare (activeSiteMapPath, node.NavigateUrl, RuntimeHelpers.StringComparison) == 0;
}
AddNodeStyle (writer, node, level, nodeIsSelected);
if (EnableClientScript) {
writer.AddAttribute ("onmouseout", "TreeView_UnhoverNode(this)", false);
writer.AddAttribute ("onmouseover", "TreeView_HoverNode('" + ClientID + "', this)");
}
writer.RenderBeginTag (HtmlTextWriterTag.Td); // TD
// Checkbox
if (node.ShowCheckBoxInternal) {
writer.AddAttribute (HtmlTextWriterAttribute.Name, ClientID + "_cs_" + node.Path);
writer.AddAttribute (HtmlTextWriterAttribute.Type, "checkbox", false);
string str = node.ToolTip;
if (!String.IsNullOrEmpty (str))
writer.AddAttribute (HtmlTextWriterAttribute.Title, str);
if (node.Checked)
writer.AddAttribute (HtmlTextWriterAttribute.Checked, "checked", false);
writer.RenderBeginTag (HtmlTextWriterTag.Input); // INPUT
writer.RenderEndTag (); // INPUT
}
// Text
node.BeginRenderText (writer);
if (clientExpand)
writer.AddAttribute (HtmlTextWriterAttribute.Id, GetNodeClientId (node, "txt"));
AddNodeLinkStyle (writer, node, level, nodeIsSelected);
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 (HtmlTextWriterStyle.Display, "none");
else
writer.AddStyleAttribute (HtmlTextWriterStyle.Display, "block");
writer.AddAttribute (HtmlTextWriterAttribute.Id, GetNodeClientId (node, null));
writer.RenderBeginTag (HtmlTextWriterTag.Span);
if (renderChildNodes) {
AddChildrenPadding (writer, node);
int num = node.ChildNodes.Count;
for (int n=0; n<num; n++)
RenderNode (writer, node.ChildNodes [n], level + 1, levelLines, true, n<num-1);
if (hasNext)
AddChildrenPadding (writer, node);
}
writer.RenderEndTag (); // SPAN
} else if (renderChildNodes) {
AddChildrenPadding (writer, node);
int num = node.ChildNodes.Count;
for (int n=0; n<num; n++)
RenderNode (writer, node.ChildNodes [n], level + 1, levelLines, true, n<num-1);
if (hasNext)
AddChildrenPadding (writer, node);
}
}
}
void AddChildrenPadding (HtmlTextWriter writer, TreeNode node)
{
int level = node.Depth;
Unit cnp = Unit.Empty;
if (levelStyles != null && level < levelStyles.Count)
cnp = levelStyles [level].ChildNodesPadding;
if (cnp.IsEmpty && nodeStyle != null)
cnp = nodeStyle.ChildNodesPadding;
double value;
if (cnp.IsEmpty || (value = cnp.Value) == 0 || cnp.Type != UnitType.Pixel)
return;
writer.RenderBeginTag (HtmlTextWriterTag.Table);
writer.AddAttribute (HtmlTextWriterAttribute.Height, ((int) value).ToString (), false);
writer.RenderBeginTag (HtmlTextWriterTag.Tr);
writer.RenderBeginTag (HtmlTextWriterTag.Td);
writer.RenderEndTag (); // td
writer.RenderEndTag (); // tr
writer.RenderEndTag (); // table
}
void RenderMenuItemSpacing (HtmlTextWriter writer, Unit itemSpacing)
{
writer.RenderBeginTag (HtmlTextWriterTag.Tr);
writer.RenderBeginTag (HtmlTextWriterTag.Td);
writer.RenderEndTag ();
writer.RenderEndTag ();
}
Unit GetNodeSpacing (TreeNode node)
{
if (node.Selected && selectedNodeStyle != null && selectedNodeStyle.NodeSpacing != Unit.Empty)
return selectedNodeStyle.NodeSpacing;
if (levelStyles != null && node.Depth < levelStyles.Count && levelStyles [node.Depth].NodeSpacing != Unit.Empty)
return levelStyles [node.Depth].NodeSpacing;
if (node.IsLeafNode) {
if (leafNodeStyle != null && leafNodeStyle.NodeSpacing != Unit.Empty)
return leafNodeStyle.NodeSpacing;
} else if (node.IsRootNode) {
if (rootNodeStyle != null && rootNodeStyle.NodeSpacing != Unit.Empty)
return rootNodeStyle.NodeSpacing;
} else if (node.IsParentNode) {
if (parentNodeStyle != null && parentNodeStyle.NodeSpacing != Unit.Empty)
return parentNodeStyle.NodeSpacing;
}
if (nodeStyle != null)
return nodeStyle.NodeSpacing;
else
return Unit.Empty;
}
void AddNodeStyle (HtmlTextWriter writer, TreeNode node, int level, bool nodeIsSelected)
{
TreeNodeStyle style = new TreeNodeStyle ();
if (Page.Header != null) {
// styles are registered
if (nodeStyle != null) {
style.PrependCssClass (nodeStyle.RegisteredCssClass);
style.PrependCssClass (nodeStyle.CssClass);
}
if (node.IsLeafNode) {
if (leafNodeStyle != null) {
style.PrependCssClass (leafNodeStyle.RegisteredCssClass);
style.PrependCssClass (leafNodeStyle.CssClass);
}
} else if (node.IsRootNode) {
if (rootNodeStyle != null) {
style.PrependCssClass (rootNodeStyle.RegisteredCssClass);
style.PrependCssClass (rootNodeStyle.CssClass);
}
} else if (node.IsParentNode) {
if (parentNodeStyle != null) {
style.AddCssClass (parentNodeStyle.RegisteredCssClass);
style.AddCssClass (parentNodeStyle.CssClass);
}
}
if (levelStyles != null && levelStyles.Count > level) {
style.PrependCssClass (levelStyles [level].RegisteredCssClass);
style.PrependCssClass (levelStyles [level].CssClass);
}
if (nodeIsSelected) {
style.AddCssClass (selectedNodeStyle.RegisteredCssClass);
style.AddCssClass (selectedNodeStyle.CssClass);
}
} else {
// styles are not registered
if (nodeStyle != null) {
style.CopyFrom (nodeStyle);
}
if (node.IsLeafNode) {
if (leafNodeStyle != null) {
style.CopyFrom (leafNodeStyle);
}
} else if (node.IsRootNode) {
if (rootNodeStyle != null) {
style.CopyFrom (rootNodeStyle);
}
} else if (node.IsParentNode) {
if (parentNodeStyle != null) {
style.CopyFrom (parentNodeStyle);
}
}
if (levelStyles != null && levelStyles.Count > level)
style.CopyFrom (levelStyles [level]);
if (nodeIsSelected)
style.CopyFrom (selectedNodeStyle);
}
style.AddAttributesToRender (writer);
}
void AddNodeLinkStyle (HtmlTextWriter writer, TreeNode node, int level, bool nodeIsSelected)
{
Style style = new Style ();
bool addBorderStyle = false;
if (Page.Header != null) {
// styles are registered
style.AddCssClass (ControlLinkStyle.RegisteredCssClass);
if (nodeStyle != null) {
style.AddCssClass (nodeLinkStyle.CssClass);
style.AddCssClass (nodeLinkStyle.RegisteredCssClass);
}
if (levelLinkStyles != null && levelLinkStyles.Count > level) {
style.AddCssClass (levelLinkStyles [level].CssClass);
style.AddCssClass (levelLinkStyles [level].RegisteredCssClass);
addBorderStyle = true;
}
if (node.IsLeafNode) {
if (leafNodeStyle != null) {
style.AddCssClass (leafNodeLinkStyle.CssClass);
style.AddCssClass (leafNodeLinkStyle.RegisteredCssClass);
}
} else if (node.IsRootNode) {
if (rootNodeStyle != null) {
style.AddCssClass (rootNodeLinkStyle.CssClass);
style.AddCssClass (rootNodeLinkStyle.RegisteredCssClass);
}
} else if (node.IsParentNode) {
if (parentNodeStyle != null) {
style.AddCssClass (parentNodeLinkStyle.CssClass);
style.AddCssClass (parentNodeLinkStyle.RegisteredCssClass);
}
}
if (nodeIsSelected) {
style.AddCssClass (selectedNodeLinkStyle.CssClass);
style.AddCssClass (selectedNodeLinkStyle.RegisteredCssClass);
}
} else {
// styles are not registered
style.CopyFrom (ControlLinkStyle);
if (nodeStyle != null)
style.CopyFrom (nodeLinkStyle);
if (levelLinkStyles != null && levelLinkStyles.Count > level) {
style.CopyFrom (levelLinkStyles [level]);
addBorderStyle = true;
}
if (node.IsLeafNode) {
if (node.IsLeafNode && leafNodeStyle != null)
style.CopyFrom (leafNodeLinkStyle);
} else if (node.IsRootNode) {
if (node.IsRootNode && rootNodeStyle != null)
style.CopyFrom (rootNodeLinkStyle);
} else if (node.IsParentNode) {
if (node.IsParentNode && parentNodeStyle != null)
style.CopyFrom (parentNodeLinkStyle);
}
if (nodeIsSelected)
style.CopyFrom (selectedNodeLinkStyle);
style.AlwaysRenderTextDecoration = true;
}
if (addBorderStyle) {
// This appears not to come from any style. Instead, it's added
// whenever a level style is present.
writer.AddStyleAttribute (HtmlTextWriterStyle.BorderStyle, "none");
writer.AddStyleAttribute (HtmlTextWriterStyle.FontSize, "1em");
}
style.AddAttributesToRender (writer);
}
void BeginNodeTag (HtmlTextWriter writer, TreeNode node, bool clientExpand)
{
if(node.ToolTip.Length>0)
writer.AddAttribute (HtmlTextWriterAttribute.Title, node.ToolTip);
string navigateUrl = node.NavigateUrl;
if (!String.IsNullOrEmpty (navigateUrl)) {
string target = node.Target.Length > 0 ? node.Target : Target;
string navUrl = ResolveClientUrl (navigateUrl);
writer.AddAttribute (HtmlTextWriterAttribute.Href, navUrl);
if (target.Length > 0)
writer.AddAttribute (HtmlTextWriterAttribute.Target, target);
writer.RenderBeginTag (HtmlTextWriterTag.A);
} else if (node.SelectAction != TreeNodeSelectAction.None) {
if (node.SelectAction == TreeNodeSelectAction.Expand && clientExpand)
writer.AddAttribute (HtmlTextWriterAttribute.Href, GetClientExpandEvent (node));
else
writer.AddAttribute (HtmlTextWriterAttribute.Href, GetClientEvent (node, "sel"));
writer.RenderBeginTag (HtmlTextWriterTag.A);
} else
writer.RenderBeginTag (HtmlTextWriterTag.Span);
}
string GetNodeImageToolTip (bool expand, string txt)
{
if (expand) {
string expandImageToolTip = ExpandImageToolTip;
if (!String.IsNullOrEmpty (expandImageToolTip))
return String.Format (expandImageToolTip, HttpUtility.HtmlAttributeEncode (txt));
else if (txt != null)
return "Expand " + HttpUtility.HtmlAttributeEncode (txt);
else
return "Expand {0}";
} else {
string collapseImageToolTip = CollapseImageToolTip;
if (!String.IsNullOrEmpty (collapseImageToolTip))
return String.Format (collapseImageToolTip, HttpUtility.HtmlAttributeEncode (txt));
else if (txt != null)
return "Collapse " + HttpUtility.HtmlAttributeEncode (txt);
else
return "Collapse {0}";
}
}
string GetNodeClientId (TreeNode node, string sufix)
{
return ClientID + "_" + node.Path + (sufix != null ? "_" + sufix : String.Empty);
}
string GetNodeImageUrl (string shape, ImageStyle imageStyle)
{
if (ShowLines) {
if (!String.IsNullOrEmpty (LineImagesFolder))
return ResolveClientUrl (LineImagesFolder + "/" + shape + ".gif");
} else {
if (imageStyle != null) {
if (shape == "plus") {
if (!String.IsNullOrEmpty (imageStyle.Expand))
return GetNodeIconUrl (imageStyle.Expand);
} else if (shape == "minus") {
if (!String.IsNullOrEmpty (imageStyle.Collapse))
return GetNodeIconUrl (imageStyle.Collapse);
} else if (shape == "noexpand") {
if (!String.IsNullOrEmpty (imageStyle.NoExpand))
return GetNodeIconUrl (imageStyle.NoExpand);
}
} else {
if (shape == "plus") {
if (!String.IsNullOrEmpty (ExpandImageUrl))
return ResolveClientUrl (ExpandImageUrl);
} else if (shape == "minus") {
if (!String.IsNullOrEmpty (CollapseImageUrl))
return ResolveClientUrl (CollapseImageUrl);
} else if (shape == "noexpand") {
if (!String.IsNullOrEmpty (NoExpandImageUrl))
return ResolveClientUrl (NoExpandImageUrl);
}
}
if (!String.IsNullOrEmpty (LineImagesFolder))
return ResolveClientUrl (LineImagesFolder + "/" + shape + ".gif");
}
return Page.ClientScript.GetWebResourceUrl (typeof (TreeView), "TreeView_" + shape + ".gif");
}
string GetNodeIconUrl (string icon)
{
return Page.ClientScript.GetWebResourceUrl (typeof (TreeView), icon + ".gif");
}
string GetClientEvent (TreeNode node, string ev)
{
return Page.ClientScript.GetPostBackClientHyperlink (this, ev + "|" + node.Path, true);
}
string GetClientExpandEvent (TreeNode node)
{
return String.Format ("javascript:TreeView_ToggleExpand ('{0}','{1}','{2}','{3}','{4}','{5}')",
ClientID,
node.Path,
HttpUtility.HtmlAttributeEncode (node.Value).Replace ("'", "\\'").Replace ("|","U+007C"),
HttpUtility.HtmlAttributeEncode (node.ImageUrl).Replace ("'", "\\'").Replace ("|","U+007c"),
HttpUtility.HtmlAttributeEncode (node.NavigateUrl).Replace ("'", "\\'").Replace ("|","U+007C"),
HttpUtility.HtmlAttributeEncode (node.Target).Replace ("'", "\\'").Replace ("|","U+007C"));
}
TreeNode FindNodeByPos (string path)
{
string[] indexes = path.Split ('_');
TreeNode node = null;
foreach (string index in indexes) {
int i = int.Parse (index);
if (node == null) {
if (i >= 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.ShowCheckBoxInternal && node.Checked) {
if (states == null || states [ClientID + "_cs_" + node.Path] == null)
node.Checked = false;
}
if (node.HasChildData)
UnsetCheckStates (node.ChildNodes, states);
}
}
void SetCheckStates (NameValueCollection states)
{
if (states == null)
return;
string keyPrefix = ClientID + "_cs_";
foreach (string key in states) {
if (key.StartsWith (keyPrefix, StringComparison.Ordinal)) {
string id = key.Substring (keyPrefix.Length);
TreeNode node = FindNodeByPos (id);
if (node != null && !node.Checked)
node.Checked = true;
}
}
}
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 (String.IsNullOrEmpty (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);
}
}
}
}