MenuItem.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / fx / src / xsp / System / Web / UI / WebControls / MenuItem.cs / 2 / MenuItem.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Web.UI.WebControls { 
    using System; 
    using System.Collections;
    using System.Collections.Generic; 
    using System.ComponentModel;
    using System.Drawing;
    using System.Drawing.Design;
    using System.Globalization; 
    using System.IO;
    using System.Security.Permissions; 
    using System.Text; 
    using System.Web.UI;
    using System.Web.Util; 


    /// 
    ///     Provides a hierarchical menu item for use in the Menu class 
    /// 
    [ParseChildren(true, "ChildItems")] 
    [AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)] 
    public sealed class MenuItem : IStateManager, ICloneable {
 
        private static readonly Unit HorizontalDefaultSpacing = Unit.Pixel(3);

        private bool _isTrackingViewState;
        private StateBag _viewState; 

        private MenuItemCollection _childItems; 
        private Menu _owner; 
        private MenuItem _parent;
 
        private int _selectDesired;

        private object _dataItem;
        private MenuItemTemplateContainer _container; 

        private int _index; 
        internal string _id = string.Empty; 

        private string _valuePath; 
        private string _internalValuePath;
        private int _depth = -2;

        private bool _isRoot; 

 
        ///  
        ///     Constructs a new MenuItem without a text or value
        ///  
        public MenuItem() {
            _selectDesired = 0;
        }
 

        ///  
        ///     Constructs a new MenuItem with the specified owner Menu 
        /// 
        internal MenuItem(Menu owner, bool isRoot) 
            : this() {
            _owner = owner;
            _isRoot = isRoot;
        } 

 
        ///  
        ///     Constructs a new MenuItem with the specified text
        ///  
        public MenuItem(string text)
            : this(text, null, null, null, null) {
        }
 

        ///  
        ///     Constructs a new MenuItem with the specified text, and value 
        /// 
        public MenuItem(string text, string value) 
            : this(text, value, null, null, null) {
        }

 
        /// 
        ///     Constructs a new MenuItem with the specified text, value, and image URL 
        ///  
        public MenuItem(string text, string value, string imageUrl)
            : this(text, value, imageUrl, null, null) { 
        }


        ///  
        ///     Constructs a new MenuItem with the specified text, value, image URL and navigateUrl
        ///  
        public MenuItem(string text, string value, string imageUrl, string navigateUrl) 
            : this(text, value, imageUrl, navigateUrl, null) {
        } 


        /// 
        ///     Constructs a new MenuItem with the specified text, value, image URL, navigation URL, and target. 
        /// 
        public MenuItem(string text, string value, string imageUrl, string navigateUrl, string target) 
            : this() { 
            if (text != null) {
                Text = text; 
            }

            if (value != null) {
                Value = value; 
            }
 
            if (!String.IsNullOrEmpty(imageUrl)) { 
                ImageUrl = imageUrl;
            } 

            if (!String.IsNullOrEmpty(navigateUrl)) {
                NavigateUrl = navigateUrl;
            } 

            if (!String.IsNullOrEmpty(target)) { 
                Target = target; 
            }
        } 


        /// 
        ///     Gets the collection of children items parented to this MenuItem 
        /// 
        [Browsable(false)] 
        [MergableProperty(false)] 
        [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
        public MenuItemCollection ChildItems { 
            get {
                if (_childItems == null) {
                    _childItems = new MenuItemCollection(this);
                } 
                return _childItems;
            } 
        } 

        internal MenuItemTemplateContainer Container { 
            get {
                return _container;
            }
            set { 
                _container = value;
            } 
        } 

 
        /// 
        ///     Gets whether this item was created through databinding
        /// 
        [Browsable(false)] 
        [DefaultValue(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
        public bool DataBound { 
            get {
                object o = ViewState["DataBound"]; 
                if (o == null) {
                    return false;
                }
                return (bool)o; 
            }
        } 
 

        ///  
        ///     Gets path to the data to which this item is bound.
        /// 
        [Browsable(false)]
        [DefaultValue("")] 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public string DataPath { 
            get { 
                object s = ViewState["DataPath"];
                if (s == null) { 
                    return String.Empty;
                }
                return (string)s;
            } 
        }
 
 
        /// 
        ///     Gets the depth of the menu item. 
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int Depth { 
            get {
                // -2 means not set yet, -1 means root 
                if (_depth == -2) { 
                    if (_isRoot) {
                        return -1; 
                    }

                    if (Parent != null) {
                        _depth = Parent.Depth + 1; 
                    }
                    else { 
                        return 0; 
                    }
                } 
                return _depth;
            }
        }
 

        ///  
        ///     Gets the data item for the menu item. 
        /// 
        [Browsable(false)] 
        [DefaultValue(null)]
        public object DataItem {
            get {
                return _dataItem; 
            }
        } 
 
        [Browsable(true)]
        [DefaultValue(true)] 
        [WebSysDescription(SR.MenuItem_Enabled)]
        public bool Enabled {
            get {
                object o = ViewState["Enabled"]; 
                return (o == null ? true : (bool)o);
            } 
            set { 
                ViewState["Enabled"] = value;
            } 
        }

        internal string FormattedText {
            get { 
                if (_owner.StaticItemFormatString.Length > 0 && Depth < _owner.StaticDisplayLevels) {
                    return String.Format(CultureInfo.CurrentCulture, _owner.StaticItemFormatString, Text); 
                } 
                else if (_owner.DynamicItemFormatString.Length > 0 && Depth >= _owner.StaticDisplayLevels) {
                    return String.Format(CultureInfo.CurrentCulture, _owner.DynamicItemFormatString, Text); 
                }
                else {
                    return Text;
                } 
            }
        } 
 
        internal string Id {
            get { 
                if (_id.Length == 0) {
                    Index = _owner.CreateItemIndex();
                    _id = _owner.ClientID + 'n' + Index;
                } 
                return _id;
            } 
        } 

 
        /// 
        ///     Gets and sets the image URl to be rendered for this item
        /// 
        [DefaultValue("")] 
        [Editor("System.Web.UI.Design.ImageUrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor))]
        [UrlProperty()] 
        [WebSysDescription(SR.MenuItem_ImageUrl)] 
        public string ImageUrl {
            get { 
                object s = ViewState["ImageUrl"];
                if (s == null) {
                    return String.Empty;
                } 
                return (string)s;
            } 
            set { 
                ViewState["ImageUrl"] = value;
            } 
        }


        ///  
        ///     Gets and sets the unique index for the menu item
        ///  
        internal int Index { 
            get {
                return _index; 
            }
            set {
                _index = value;
            } 
        }
 
        internal string InternalValuePath { 
            get {
                if (_internalValuePath != null) { 
                    return _internalValuePath;
                }
                if (_parent != null) {
                    // StringBuilder.Insert is expensive, but we need to build starting from the end. 
                    // First build a list, then build the string starting from the end of the list.
                    List pathParts = new List(); 
                    pathParts.Add(TreeView.Escape(Value)); 
                    MenuItem parent = _parent;
                    while ((parent != null) && !parent._isRoot) { 
                        if (parent._internalValuePath != null) {
                            pathParts.Add(parent._internalValuePath);
                            break;
                        } 
                        else {
                            pathParts.Add(TreeView.Escape(parent.Value)); 
                        } 
                        parent = parent._parent;
                    } 
                    pathParts.Reverse();
                    _internalValuePath = String.Join(TreeView.InternalPathSeparator.ToString(), pathParts.ToArray());
                    return _internalValuePath;
                } 
                else {
                    return String.Empty; 
                } 
            }
        } 

        internal bool IsEnabled {
            get {
                return IsEnabledNoOwner && Owner.IsEnabled; 
            }
        } 
 
        internal bool IsEnabledNoOwner {
            get { 
                MenuItem current = this;
                while (current != null) {
                    if (!current.Enabled) {
                        return false; 
                    }
 
                    current = current.Parent; 
                }
 
                return true;
            }
        }
 

        ///  
        ///     Gets and sets the URL to navigate to when the item is clicked 
        /// 
        [DefaultValue("")] 
        [Editor("System.Web.UI.Design.UrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor))]
        [UrlProperty()]
        [WebSysDescription(SR.MenuItem_NavigateUrl)]
        public string NavigateUrl { 
            get {
                object s = ViewState["NavigateUrl"]; 
                if (s == null) { 
                    return String.Empty;
                } 
                return (string)s;
            }
            set {
                ViewState["NavigateUrl"] = value; 
            }
        } 
 

        ///  
        ///     Gets the owner Menu for this MenuItem, if there is one
        /// 
        internal Menu Owner {
            get { 
                return _owner;
            } 
        } 

 
        /// 
        ///     Gets the parent MenuItem
        /// 
        [Browsable(false)] 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public MenuItem Parent { 
            get { 
                if ((_parent == null) || _parent._isRoot) {
                    return null; 
                }

                return _parent;
            } 

        } 
 

        ///  
        ///     Gets and sets the image URl to be rendered as a pop-out icon for this item if it has children
        /// 
        [DefaultValue("")]
        [Editor("System.Web.UI.Design.ImageUrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor))] 
        [UrlProperty()]
        [WebSysDescription(SR.MenuItem_PopOutImageUrl)] 
        public string PopOutImageUrl { 
            get {
                object s = ViewState["PopOutImageUrl"]; 
                if (s == null) {
                    return String.Empty;
                }
                return (string)s; 
            }
            set { 
                ViewState["PopOutImageUrl"] = value; 
            }
        } 

        [Browsable(true)]
        [DefaultValue(true)]
        [WebSysDescription(SR.MenuItem_Selectable)] 
        public bool Selectable {
            get { 
                object o = ViewState["Selectable"]; 
                return (o == null ? true : (bool)o);
            } 
            set {
                ViewState["Selectable"] = value;
            }
        } 

 
        ///  
        ///     Gets and sets the selected state
        ///  
        [Browsable(true)]
        [DefaultValue(false)]
        [WebSysDescription(SR.MenuItem_Selected)]
        public bool Selected { 
            get {
                object o = ViewState["Selected"]; 
                if (o == null) { 
                    return false;
                } 
                return (bool)o;
            }
            set {
                SetSelected(value); 
                NotifyOwnerSelected();
            } 
        } 

 
        /// 
        ///     Gets and sets the image URl to be rendered as a separator for this item
        /// 
        [DefaultValue("")] 
        [Editor("System.Web.UI.Design.ImageUrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor))]
        [UrlProperty()] 
        [WebSysDescription(SR.MenuItem_SeparatorImageUrl)] 
        public string SeparatorImageUrl {
            get { 
                object s = ViewState["SeparatorImageUrl"];
                if (s == null) {
                    return String.Empty;
                } 
                return (string)s;
            } 
            set { 
                ViewState["SeparatorImageUrl"] = value;
            } 
        }


        ///  
        ///     Gets and sets the target window that the MenuItem will browse to if selected
        ///  
        [DefaultValue("")] 
        [WebSysDescription(SR.MenuItem_Target)]
        public string Target { 
            get {
                object s = ViewState["Target"];
                if (s == null) {
                    return String.Empty; 
                }
                return (string)s; 
            } 
            set {
                ViewState["Target"] = value; 
            }
        }

 
        /// 
        ///     Gets and sets the display text 
        ///  
        [DefaultValue("")]
        [Localizable(true)] 
        [WebSysDescription(SR.MenuItem_Text)]
        public string Text {
            get {
                object s = ViewState["Text"]; 
                if (s == null) {
                    s = ViewState["Value"]; 
                    if (s == null) { 
                        return String.Empty;
                    } 
                }
                return (string)s;
            }
            set { 
                ViewState["Text"] = value;
            } 
        } 

 
        /// 
        ///     Gets and sets the MenuItem tooltip
        /// 
        [DefaultValue("")] 
        [Localizable(true)]
        [WebSysDescription(SR.MenuItem_ToolTip)] 
        public string ToolTip { 
            get {
                object s = ViewState["ToolTip"]; 
                if (s == null) {
                    return String.Empty;
                }
                return (string)s; 
            }
            set { 
                ViewState["ToolTip"] = value; 
            }
        } 


        /// 
        ///     Gets and sets the value 
        /// 
        [DefaultValue("")] 
        [Localizable(true)] 
        [WebSysDescription(SR.MenuItem_Value)]
        public string Value { 
            get {
                object s = ViewState["Value"];
                if (s == null) {
                    s = ViewState["Text"]; 
                    if (s == null) {
                        return String.Empty; 
                    } 
                }
                return (string)s; 
            }
            set {
                ViewState["Value"] = value;
                ResetValuePathRecursive(); 
            }
        } 
 

        ///  
        ///     Gets the full path of the MenuItem
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
        public string ValuePath {
            get { 
                if (_valuePath != null) { 
                    return _valuePath;
                } 

                if (_parent != null) {
                    string parentPath = _parent.ValuePath;
                    _valuePath = ((parentPath.Length == 0) && (_parent.Depth == -1)) ? 
                        Value : parentPath + _owner.PathSeparator + Value;
                    return _valuePath; 
                } 
                else {
                    return String.Empty; 
                }
            }
        }
 

        ///  
        ///     The state for this MenuItem 
        /// 
        private StateBag ViewState { 
            get {
                if (_viewState == null) {
                    _viewState = new StateBag();
                    if (_isTrackingViewState) { 
                        ((IStateManager)_viewState).TrackViewState();
                    } 
                } 
                return _viewState;
            } 
        }

        internal string GetExpandImageUrl() {
            if (ChildItems.Count > 0) { 
                if (PopOutImageUrl.Length != 0) {
                    return _owner.ResolveClientUrl(PopOutImageUrl); 
                } 
                else {
                    if (Depth < _owner.StaticDisplayLevels) { 
                        if (_owner.StaticPopOutImageUrl.Length != 0) {
                            return _owner.ResolveClientUrl(_owner.StaticPopOutImageUrl);
                        }
                        else if (_owner.StaticEnableDefaultPopOutImage) { 
                            return _owner.GetImageUrl(Menu.PopOutImageIndex);
                        } 
                    } 
                    else {
                        if (_owner.DynamicPopOutImageUrl.Length != 0) { 
                            return _owner.ResolveClientUrl(_owner.DynamicPopOutImageUrl);
                        }
                        else if (_owner.DynamicEnableDefaultPopOutImage) {
                            return _owner.GetImageUrl(Menu.PopOutImageIndex); 
                        }
                    } 
                } 
            }
            return String.Empty; 
        }

        internal bool NotTemplated() {
            return ((_owner.StaticItemTemplate == null || Depth >= _owner.StaticDisplayLevels) && 
                    (_owner.DynamicItemTemplate == null || Depth < _owner.StaticDisplayLevels));
        } 
 
        private void NotifyOwnerSelected() {
            object o = ViewState["Selected"]; 
            bool value = (o == null ? false : (bool)o);
            // If the owner hasn't been set, remember that we want to select this item
            // when the owner is determined
            if (_owner == null) { 
                _selectDesired = (value ? +1 : -1);
                return; 
            } 
            else if (value) {
                // Set the Menu's selected item to this one 
                _owner.SetSelectedItem(this);
            }
            else if (this == _owner.SelectedItem) {
                _owner.SetSelectedItem(null); 
            }
        } 
 

        ///  
        ///     Renders the contents of the item and its children.
        /// 
        internal void Render(HtmlTextWriter writer, bool enabled, bool staticOnly) {
            Render(writer, enabled, staticOnly, true); 
        }
 
 
        /// 
        ///     Renders the contents of the item and its children. 
        /// 
        internal void Render(HtmlTextWriter writer, bool enabled, bool staticOnly, bool recursive) {
            enabled = enabled && Enabled;
            // If children exist, maybe render them 
            int nextDepth = Depth + 1;
            if (ChildItems.Count > 0 && nextDepth < _owner.MaximumDepth) { 
                //  
                // Find the right style:
                SubMenuStyle subMenuStyle = _owner.GetSubMenuStyle(this); 
                string styleClass = null;
                if (_owner.Page != null && _owner.Page.SupportsStyleSheets) {
                    styleClass = _owner.GetSubMenuCssClassName(this);
                } 

                if (nextDepth >= _owner.StaticDisplayLevels) { 
                    // The submenu is dynamic 
                    if (!staticOnly && enabled && !(_owner.DesignMode && recursive)) {
                        // Not recreating a panel each time: panel is created and configured only once from Menu.Panel. 
                        PopOutPanel panel = _owner.Panel;
                        if (_owner.Page != null && _owner.Page.SupportsStyleSheets) {
                            panel.ScrollerClass = _owner.GetCssClassName(ChildItems[0], false);
                            panel.ScrollerStyle = null; 
                        }
                        else { 
                            panel.ScrollerClass = null; 
                            panel.ScrollerStyle = _owner.GetMenuItemStyle(ChildItems[0]);
                        } 
                        if (_owner.Page != null && _owner.Page.SupportsStyleSheets) {
                            panel.CssClass = styleClass;
                            panel.SetInternalStyle(null);
                        } 
                        else if (!subMenuStyle.IsEmpty) {
                            panel.CssClass = String.Empty; 
                            panel.SetInternalStyle(subMenuStyle); 
                        }
                        else { 
                            panel.CssClass = String.Empty;
                            panel.SetInternalStyle(null);
                            panel.BackColor = Color.Empty;
                        } 
                        panel.ID = Id + "Items";
                        panel.RenderBeginTag(writer); 
                        writer.AddAttribute(HtmlTextWriterAttribute.Border, "0"); 
                        writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "0");
                        writer.AddAttribute(HtmlTextWriterAttribute.Cellspacing, "0"); 
                        writer.RenderBeginTag(HtmlTextWriterTag.Table);
                        for (int i = 0; i < ChildItems.Count; i++) {
                            ChildItems[i].RenderItem(writer, i, enabled, Orientation.Vertical);
                        } 
                        writer.RenderEndTag(); // Table
                        panel.RenderEndTag(writer); 
 
                        if (recursive) {
                            for (int i = 0; i < ChildItems.Count; i++) { 
                                ChildItems[i].Render(writer, enabled, false);
                            }
                        }
                    } 
                }
                else { 
                    // The submenu is static 
                    writer.AddAttribute(HtmlTextWriterAttribute.Border, "0");
                    writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "0"); 
                    writer.AddAttribute(HtmlTextWriterAttribute.Cellspacing, "0");
                    writer.AddAttribute(HtmlTextWriterAttribute.Width, "100%");
                    if (_owner.Page != null && _owner.Page.SupportsStyleSheets) {
                        if (styleClass != null && styleClass.Length > 0) { 
                            writer.AddAttribute(HtmlTextWriterAttribute.Class, styleClass);
                        } 
                    } 
                    else {
                        subMenuStyle.AddAttributesToRender(writer); 
                    }
                    writer.RenderBeginTag(HtmlTextWriterTag.Table);
                    if (_owner.Orientation == Orientation.Horizontal) {
                        // Render one global tr as items won't render any 
                        writer.RenderBeginTag(HtmlTextWriterTag.Tr);
                    } 
                    bool isNextStatic = (nextDepth + 1 < _owner.StaticDisplayLevels); 
                    bool isNextInRange = (nextDepth + 1 < _owner.MaximumDepth);
                    for (int i = 0; i < ChildItems.Count; i++) { 
                        if (recursive
                            && ChildItems[i].ChildItems.Count != 0
                            && ((enabled && ChildItems[i].Enabled) || isNextStatic)
                            && isNextInRange) { 

                            // If the next items are dynamic, we want to render the div inside the item's 
                            // td so that we don't generate a tr that contains only absolute positioned 
                            // divs, which would cause a gap to appear (VSWhidbey 354884)
                            if (isNextStatic) { 
                                ChildItems[i].RenderItem(writer, i, enabled, _owner.Orientation);
                                if (_owner.Orientation == Orientation.Vertical) {
                                    writer.RenderBeginTag(HtmlTextWriterTag.Tr);
                                    writer.RenderBeginTag(HtmlTextWriterTag.Td); 
                                    ChildItems[i].Render(writer, enabled, staticOnly);
                                    writer.RenderEndTag(); //td 
                                    writer.RenderEndTag(); //tr 
                                }
                                else { 
                                    writer.RenderBeginTag(HtmlTextWriterTag.Td);
                                    ChildItems[i].Render(writer, enabled, staticOnly);
                                    writer.RenderEndTag(); //td
                                } 
                            }
                            else { 
                                ChildItems[i].RenderItem(writer, i, enabled, _owner.Orientation, staticOnly); 
                            }
                        } 
                        else {
                            ChildItems[i].RenderItem(writer, i, enabled, _owner.Orientation);
                        }
                    } 
                    if (_owner.Orientation == Orientation.Horizontal) {
                        // Render global /tr 
                        writer.RenderEndTag(); 
                    }
                    writer.RenderEndTag(); //table 
                    if (!isNextStatic && !staticOnly && recursive && isNextInRange) {
                        for (int i = 0; i < ChildItems.Count; i++) {
                            if (ChildItems[i].ChildItems.Count != 0
                                && ((enabled && ChildItems[i].Enabled))) { 

                                // The next items are dynamic, so we want to render the div outside the menu table 
                                // so that we don't generate a tr that contains only absolute positioned 
                                // divs, which would cause a gap to appear (VSWhidbey 354884)
                                ChildItems[i].Render(writer, enabled, false, true); 
                            }
                        }
                    }
                } 
            }
        } 
 

        ///  
        ///     Renders the contents of the item but not its children.
        /// 
        internal void RenderItem(HtmlTextWriter writer, int position, bool enabled, Orientation orientation) {
            RenderItem(writer, position, enabled, orientation, false); 
        }
 
        internal void RenderItem(HtmlTextWriter writer, int position, bool enabled, Orientation orientation, bool staticOnly) { 
            enabled = enabled && Enabled;
            int depth = Depth; 
            MenuItemStyle mergedStyle = _owner.GetMenuItemStyle(this);

            int depthPlusOne = Depth + 1;
 
            bool staticTopSeparator = (depth < _owner.StaticDisplayLevels) && (_owner.StaticTopSeparatorImageUrl.Length != 0);
            bool dynamicTopSeparator = (depth >= _owner.StaticDisplayLevels) && (_owner.DynamicTopSeparatorImageUrl.Length != 0); 
            // The separator is in a separate td in the vertical case, in a separate tr otherwise. 
            if (staticTopSeparator || dynamicTopSeparator) {
                if (orientation == Orientation.Vertical) { 
                    writer.RenderBeginTag(HtmlTextWriterTag.Tr);
                }
                writer.RenderBeginTag(HtmlTextWriterTag.Td);
                if (staticTopSeparator) { 
                    writer.AddAttribute(HtmlTextWriterAttribute.Src, _owner.ResolveClientUrl(_owner.StaticTopSeparatorImageUrl));
                } 
                else { 
                    writer.AddAttribute(HtmlTextWriterAttribute.Src, _owner.ResolveClientUrl(_owner.DynamicTopSeparatorImageUrl));
                } 
                writer.AddAttribute(HtmlTextWriterAttribute.Alt, String.Empty);
                writer.RenderBeginTag(HtmlTextWriterTag.Img);
                writer.RenderEndTag(); // Img
                writer.RenderEndTag(); // Td 
                if (orientation == Orientation.Vertical) {
                    writer.RenderEndTag(); // Tr 
                } 
            }
 
            // Top spacing
            if ((mergedStyle != null) && !mergedStyle.ItemSpacing.IsEmpty && ((depth != 0) || (position != 0))) {
                RenderItemSpacing(writer, mergedStyle.ItemSpacing, orientation);
            } 

            if (!staticOnly && _owner.Enabled) { 
                if (depthPlusOne > _owner.StaticDisplayLevels) { 
                    // Only the last static level and dynamic levels need hover behavior.
                    // And then only if they are selectable or have children. 
                    if ((Selectable && Enabled) || ChildItems.Count != 0) {
                        writer.AddAttribute("onmouseover", "Menu_HoverDynamic(this)");
                        RenderItemEvents(writer);
                    } 
                    else {
                        // dynamic disabled or unselectable items without children still need to maintain the menu open 
                        writer.AddAttribute("onmouseover", "Menu_HoverDisabled(this)"); 
                        writer.AddAttribute("onmouseout", "Menu_Unhover(this)");
                    } 
                }
                else if (depthPlusOne == _owner.StaticDisplayLevels) {
                    // Here's for the last static level
                    if ((Selectable && Enabled) || ChildItems.Count != 0) { 
                        writer.AddAttribute("onmouseover", "Menu_HoverStatic(this)");
                        RenderItemEvents(writer); 
                    } 
                }
                else if (Selectable && Enabled) { 
                    // Other nodes need hover styles but no expand
                    writer.AddAttribute("onmouseover", "Menu_HoverRoot(this)");
                    RenderItemEvents(writer);
                } 
            }
            // Tooltip 
            if (ToolTip.Length != 0) { 
                writer.AddAttribute(HtmlTextWriterAttribute.Title, ToolTip);
            } 
            // Set the id
            writer.AddAttribute(HtmlTextWriterAttribute.Id, Id);
            if (orientation == Orientation.Vertical) {
                //  
                writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            } 
 
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
 
            // Set the style
            if (_owner.Page != null && _owner.Page.SupportsStyleSheets) {
                string styleClass = _owner.GetCssClassName(this, false);
                if (styleClass.Trim().Length > 0) { 
                    writer.AddAttribute(HtmlTextWriterAttribute.Class, styleClass);
                } 
            } 
            else if (mergedStyle != null) {
                mergedStyle.AddAttributesToRender(writer); 
            }

            writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "0");
            writer.AddAttribute(HtmlTextWriterAttribute.Cellspacing, "0"); 
            writer.AddAttribute(HtmlTextWriterAttribute.Border, "0");
            writer.AddAttribute(HtmlTextWriterAttribute.Width, "100%"); 
            writer.RenderBeginTag(HtmlTextWriterTag.Table); 
            writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            if (!_owner.ItemWrap) { 
                writer.AddStyleAttribute(HtmlTextWriterStyle.WhiteSpace, "nowrap");
            }
            if (orientation == Orientation.Vertical) {
                writer.AddStyleAttribute(HtmlTextWriterStyle.Width, "100%"); 
            }
 
            writer.RenderBeginTag(HtmlTextWriterTag.Td); 

            if (_owner.Page != null && _owner.Page.SupportsStyleSheets) { 
                bool applyInlineBorder;
                string styleClass = _owner.GetCssClassName(this, true, out applyInlineBorder);
                if (styleClass.Trim().Length > 0) {
                    writer.AddAttribute(HtmlTextWriterAttribute.Class, styleClass); 
                    if (applyInlineBorder) {
                        // Add inline style to force the border to none to override any CssClass (VSWhidbey 336610) 
                        writer.AddStyleAttribute(HtmlTextWriterStyle.BorderStyle, "none"); 
                        // And an inline font-size of 1em to avoid squaring relative font sizes by applying them twice
                        writer.AddStyleAttribute(HtmlTextWriterStyle.FontSize, "1em"); 
                    }
                }
            }
            else { 
                if (mergedStyle != null) {
                    mergedStyle.HyperLinkStyle.AddAttributesToRender(writer); 
                } 
            }
 
            string accessKey = _owner.AccessKey;
            if (enabled && Selectable) {
                // If there is a navigation url on this item, set up the navigation stuff
                if (NavigateUrl.Length > 0) { 
                    writer.AddAttribute(HtmlTextWriterAttribute.Href, _owner.ResolveClientUrl(NavigateUrl));
 
                    // Use the MenuItem Target if it has one, the Menu's if it doesn't 
                    string target = ViewState["Target"] as string;
                    if (target == null) { 
                        target = _owner.Target;
                    }

                    if (target.Length > 0) { 
                        writer.AddAttribute(HtmlTextWriterAttribute.Target, target);
                    } 
                } 
                // Otherwise, write out a postback that will select the item
                else { 
                    writer.AddAttribute(HtmlTextWriterAttribute.Href,
                        _owner.Page.ClientScript.GetPostBackClientHyperlink(_owner, InternalValuePath, true, true));
                }
                // AccessKey 
                if (!_owner.AccessKeyRendered && (accessKey.Length != 0)) {
                    writer.AddAttribute(HtmlTextWriterAttribute.Accesskey, accessKey, true); 
                    _owner.AccessKeyRendered = true; 
                }
 
            }
            else {
                // Span if disabled or not selectable
                if (!enabled) { 
                    writer.AddAttribute(HtmlTextWriterAttribute.Disabled, "true");
                } 
                else if ((ChildItems.Count != 0) && (depthPlusOne >= _owner.StaticDisplayLevels)) { 
                    // For accessibility reasons, we want the a to have an href even if it's not selectable
                    // because we want it to be focusable if it has dynamic children. 
                    writer.AddAttribute(HtmlTextWriterAttribute.Href, "#");
                    writer.AddStyleAttribute(HtmlTextWriterStyle.Cursor, "text");
                    // AccessKey
                    if (!_owner.AccessKeyRendered && (accessKey.Length != 0)) { 
                        writer.AddAttribute(HtmlTextWriterAttribute.Accesskey, accessKey, true);
                        _owner.AccessKeyRendered = true; 
                    } 
                }
            } 
            if (depth != 0 && depth < _owner.StaticDisplayLevels) {
                Unit indent = _owner.StaticSubMenuIndent;
                if (!indent.IsEmpty && indent.Value != 0) {
                    double indentValue = indent.Value * depth; 
                    if (indentValue <  Unit.MaxValue) {
                        indent = new Unit(indentValue, indent.Type); 
                    } 
                    else {
                        indent = new Unit(Unit.MaxValue, indent.Type); 
                    }
                    writer.AddStyleAttribute("margin-left", indent.ToString(CultureInfo.InvariantCulture));
                }
            } 
            // 
            // We're rendering an A tag in all cases so that the client script can always find the items by tag name 
            writer.RenderBeginTag(HtmlTextWriterTag.A); 

            // Render out the item icon, if it is set and if the item is not templated 
            if (ImageUrl.Length > 0 && NotTemplated()) {
                // 
                writer.AddAttribute(HtmlTextWriterAttribute.Src, _owner.ResolveClientUrl(ImageUrl));
                writer.AddAttribute(HtmlTextWriterAttribute.Alt, ToolTip); 
                writer.AddStyleAttribute(HtmlTextWriterStyle.BorderStyle, "none");
                writer.AddStyleAttribute("vertical-align", "middle"); 
                writer.RenderBeginTag(HtmlTextWriterTag.Img); 
                writer.RenderEndTag();
            } 

            // Item text
            RenderText(writer);
 
            //  or 
            writer.RenderEndTag(); 
 
            bool shouldRenderExpandImage = ((depthPlusOne >= _owner.StaticDisplayLevels) &&
                (depthPlusOne < _owner.MaximumDepth)); 
            string expandImageUrl = (shouldRenderExpandImage ? GetExpandImageUrl() : String.Empty);

            // Render some space if horizontal
            bool needsSpace = false; 
            if ((orientation == Orientation.Horizontal) &&
                (depth < _owner.StaticDisplayLevels) && 
                (!shouldRenderExpandImage || (expandImageUrl.Length == 0)) && 
                ((mergedStyle == null) || mergedStyle.ItemSpacing.IsEmpty)) {
 

                if (((Depth + 1) < _owner.StaticDisplayLevels) && (ChildItems.Count != 0)) {
                    // next level is static too and exists, so we're not the last static
                    needsSpace = true; 
                }
                else { 
                    // Static item with no static children. 
                    // We need to check if there are any static items at any level after this one.
                    // This is done by checking if any ancestor is not last. 
                    // This walk should be marginally executed as multiple static display levels
                    // don't make sense on a horizontal menu.
                    MenuItem parent = this;
                    while (parent != null) { 
                        if (((parent.Parent == null) &&
                             (_owner.Items.Count != 0) && 
                             (parent != _owner.Items[_owner.Items.Count - 1])) || 
                            ((parent.Parent != null) &&
                             (parent.Parent.ChildItems.Count != 0) && 
                             (parent != parent.Parent.ChildItems[parent.Parent.ChildItems.Count - 1]))) {

                            needsSpace = true;
                            break; 
                        }
                        parent = parent.Parent; 
                    } 
                }
            } 

            // 
            writer.RenderEndTag();
 
            if (shouldRenderExpandImage && expandImageUrl.Length > 0) {
                //  
                writer.RenderEndTag();
            } 


            writer.RenderEndTag(); // 
            writer.RenderEndTag(); // 
writer.AddStyleAttribute(HtmlTextWriterStyle.Width, "0"); writer.RenderBeginTag(HtmlTextWriterTag.Td); // writer.AddAttribute(HtmlTextWriterAttribute.Src, expandImageUrl); writer.AddStyleAttribute(HtmlTextWriterStyle.BorderStyle, "none"); writer.AddStyleAttribute(HtmlTextWriterStyle.VerticalAlign, "middle"); if (depth < _owner.StaticDisplayLevels) { writer.AddAttribute(HtmlTextWriterAttribute.Alt, String.Format(CultureInfo.CurrentCulture, _owner.StaticPopOutImageTextFormatString, Text)); } else if (depth >= _owner.StaticDisplayLevels) { writer.AddAttribute(HtmlTextWriterAttribute.Alt, String.Format(CultureInfo.CurrentCulture, _owner.DynamicPopOutImageTextFormatString, Text)); } writer.RenderBeginTag(HtmlTextWriterTag.Img); writer.RenderEndTag(); //
writer.RenderEndTag(); // if (orientation == Orientation.Vertical) { writer.RenderEndTag(); // } // Bottom (or right) item spacing // We do not render the spacing on the last static item or on the last item of a dynamic submenu if ((mergedStyle != null) && !mergedStyle.ItemSpacing.IsEmpty) { RenderItemSpacing(writer, mergedStyle.ItemSpacing, orientation); } else if (needsSpace) { RenderItemSpacing(writer, HorizontalDefaultSpacing, orientation); } // Bottom separator bool separator = (SeparatorImageUrl.Length != 0); bool staticBottomSeparator = (depth < _owner.StaticDisplayLevels) && (_owner.StaticBottomSeparatorImageUrl.Length != 0); bool dynamicBottomSeparator = (depth >= _owner.StaticDisplayLevels) && (_owner.DynamicBottomSeparatorImageUrl.Length != 0); if (separator || staticBottomSeparator || dynamicBottomSeparator) { if (orientation == Orientation.Vertical) { writer.RenderBeginTag(HtmlTextWriterTag.Tr); } writer.RenderBeginTag(HtmlTextWriterTag.Td); if (separator) { writer.AddAttribute(HtmlTextWriterAttribute.Src, _owner.ResolveClientUrl(SeparatorImageUrl)); } else if (staticBottomSeparator) { writer.AddAttribute(HtmlTextWriterAttribute.Src, _owner.ResolveClientUrl(_owner.StaticBottomSeparatorImageUrl)); } else { writer.AddAttribute(HtmlTextWriterAttribute.Src, _owner.ResolveClientUrl(_owner.DynamicBottomSeparatorImageUrl)); } writer.AddAttribute(HtmlTextWriterAttribute.Alt, String.Empty); writer.RenderBeginTag(HtmlTextWriterTag.Img); writer.RenderEndTag(); // Img writer.RenderEndTag(); // Td if (orientation == Orientation.Vertical) { writer.RenderEndTag(); // Tr } } } private void RenderItemEvents(HtmlTextWriter writer) { writer.AddAttribute("onmouseout", "Menu_Unhover(this)"); if (_owner.IsNotIE) { writer.AddAttribute("onkeyup", "Menu_Key(event)"); } else { writer.AddAttribute("onkeyup", "Menu_Key(this)"); } } private void RenderItemSpacing(HtmlTextWriter writer, Unit spacing, Orientation orientation) { if (orientation == Orientation.Vertical) { writer.AddStyleAttribute(HtmlTextWriterStyle.Height, spacing.ToString(CultureInfo.InvariantCulture)); writer.RenderBeginTag(HtmlTextWriterTag.Tr); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.RenderEndTag(); writer.RenderEndTag(); } else { writer.AddStyleAttribute(HtmlTextWriterStyle.Width, spacing.ToString(CultureInfo.InvariantCulture)); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.RenderEndTag(); } } internal void RenderText(HtmlTextWriter writer) { if (Container != null && ((_owner.StaticItemTemplate != null && Depth < _owner.StaticDisplayLevels) || (_owner.DynamicItemTemplate != null && Depth >= _owner.StaticDisplayLevels))) { Container.RenderControl(writer); } else { writer.Write(FormattedText); } } internal void ResetValuePathRecursive() { if (_valuePath != null) { _valuePath = null; foreach (MenuItem child in ChildItems) { child.ResetValuePathRecursive(); } } } /// /// Marks this item as a databound item /// internal void SetDataBound(bool dataBound) { ViewState["DataBound"] = dataBound; } /// /// Sets the data item for use by the user in databinding /// internal void SetDataItem(object dataItem) { _dataItem = dataItem; } /// /// Sets the data path for use by the Menu in databinding /// internal void SetDataPath(string dataPath) { ViewState["DataPath"] = dataPath; } internal void SetDepth(int depth) { _depth = depth; } internal void SetDirty() { ViewState.SetDirty(true); if (ChildItems.Count > 0) { ChildItems.SetDirty(); } } /// /// Sets the owner Menu of this item. /// internal void SetOwner(Menu owner) { _owner = owner; if (_selectDesired == +1) { _selectDesired = 0; Selected = true; } else if (_selectDesired == -1) { _selectDesired = 0; Selected = false; } foreach (MenuItem item in ChildItems) { item.SetOwner(_owner); } } /// /// Sets the parent MenuItem of the item /// internal void SetParent(MenuItem parent) { _parent = parent; SetPath(null); } internal void SetPath(string newPath) { _internalValuePath = newPath; _depth = -2; } internal void SetSelected(bool value) { ViewState["Selected"] = value; // If the owner hasn't been set, remember that we want to select this node // when the owner is determined if (_owner == null) { _selectDesired = (value ? +1 : -1); } } #region IStateManager implementation /// bool IStateManager.IsTrackingViewState { get { return _isTrackingViewState; } } /// void IStateManager.LoadViewState(object state) { object[] itemState = (object[])state; if (itemState != null) { if (itemState[0] != null) { ((IStateManager)ViewState).LoadViewState(itemState[0]); } // We need to call the selected setter so that the owner can be notified // N.B. The treeview does not need to do that // because it's loading the state of its node differently because of the richer client-side behavior. NotifyOwnerSelected(); if (itemState[1] != null) { ((IStateManager)ChildItems).LoadViewState(itemState[1]); } } } /// object IStateManager.SaveViewState() { object[] state = new object[2]; if (_viewState != null) { state[0] = ((IStateManager)_viewState).SaveViewState(); } if (_childItems != null) { state[1] = ((IStateManager)_childItems).SaveViewState(); } if ((state[0] == null) && (state[1] == null)) { return null; } return state; } /// void IStateManager.TrackViewState() { _isTrackingViewState = true; if (_viewState != null) { ((IStateManager)_viewState).TrackViewState(); } if (_childItems != null) { ((IStateManager)_childItems).TrackViewState(); } } #endregion #region ICloneable implementation /// object ICloneable.Clone() { MenuItem newItem = new MenuItem(); newItem.Enabled = Enabled; newItem.ImageUrl = ImageUrl; newItem.NavigateUrl = NavigateUrl; newItem.PopOutImageUrl = PopOutImageUrl; newItem.Selectable = Selectable; newItem.Selected = Selected; newItem.SeparatorImageUrl = SeparatorImageUrl; newItem.Target = Target; newItem.Text = Text; newItem.ToolTip = ToolTip; newItem.Value = Value; return newItem; } #endregion } [AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)] public sealed class MenuItemTemplateContainer : Control, IDataItemContainer { private int _itemIndex; private object _dataItem; public MenuItemTemplateContainer(int itemIndex, MenuItem dataItem) { _itemIndex = itemIndex; _dataItem = dataItem; } public object DataItem { get { return _dataItem; } set { _dataItem = value; } } public int ItemIndex { get { return _itemIndex; } } protected override bool OnBubbleEvent(object source, EventArgs e) { CommandEventArgs ce = e as CommandEventArgs; if (ce != null) { if (ce is MenuEventArgs) { RaiseBubbleEvent(this, ce); } else { MenuEventArgs args = new MenuEventArgs((MenuItem)_dataItem, source, ce); RaiseBubbleEvent(this, args); } return true; } return false; } object IDataItemContainer.DataItem { get { return _dataItem; } } int IDataItemContainer.DataItemIndex { get { return ItemIndex; } } int IDataItemContainer.DisplayIndex { get { return ItemIndex; } } } }

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK