Menu.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / xsp / System / Web / UI / WebControls / Menu.cs / 1305376 / Menu.cs

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

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

    /// 
    ///     Provides a cascading pop-out hierarchical menu control
    ///  
    [ControlValueProperty("SelectedValue")]
    [DefaultEvent("MenuItemClick")] 
    [Designer("System.Web.UI.Design.WebControls.MenuDesigner, " + AssemblyRef.SystemDesign)] 
    [SupportsEventValidation]
    public partial class Menu : HierarchicalDataBoundControl, IPostBackEventHandler, INamingContainer { 

        internal const int ScrollUpImageIndex = 0;
        internal const int ScrollDownImageIndex = 1;
        internal const int PopOutImageIndex = 2; 

        internal const int ImageUrlsCount = 3; 
 
        private const string _getDesignTimeStaticHtml = "GetDesignTimeStaticHtml";
        private const string _getDesignTimeDynamicHtml = "GetDesignTimeDynamicHtml"; 

        // static readonly instead of const to be able to change it in the future without breaking existing client code
        public static readonly string MenuItemClickCommandName = "Click";
 
        private static readonly object _menuItemClickedEvent = new object();
        private static readonly object _menuItemDataBoundEvent = new object(); 
 
        private MenuRenderingMode _renderingMode = MenuRenderingMode.Default;
 
        private string[] _imageUrls;

        private SubMenuStyle _staticMenuStyle;
        private SubMenuStyle _dynamicMenuStyle; 

        private MenuItemStyle _staticItemStyle; 
        private MenuItemStyle _staticSelectedStyle; 
        private Style _staticHoverStyle;
        private HyperLinkStyle _staticHoverHyperLinkStyle; 

        private MenuItemStyle _dynamicItemStyle;
        private MenuItemStyle _dynamicSelectedStyle;
        private Style _dynamicHoverStyle; 
        private HyperLinkStyle _dynamicHoverHyperLinkStyle;
 
        private Style _rootMenuItemStyle; 

        private SubMenuStyleCollection _levelStyles; 
        private MenuItemStyleCollection _levelMenuItemStyles;
        private MenuItemStyleCollection _levelSelectedStyles;

        // Cached styles. In the current implementation, the styles are the same for all items 
        // and submenus at a given depth.
        private List _cachedMenuItemStyles; 
        private List _cachedSubMenuStyles; 
        private List _cachedMenuItemClassNames;
        private List _cachedMenuItemHyperLinkClassNames; 
        private List _cachedSubMenuClassNames;
        private Collection _cachedLevelsContainingCssClass;

        private MenuItem _rootItem; 
        private MenuItem _selectedItem;
 
        private MenuItemBindingCollection _bindings; 

        private string _cachedScrollUpImageUrl; 
        private string _cachedScrollDownImageUrl;
        private string _cachedPopOutImageUrl;

        private ITemplate _dynamicTemplate; 
        private ITemplate _staticTemplate;
 
        private int _maximumDepth; 
        private int _nodeIndex;
 
        private string _currentSiteMapNodeUrl;
        private bool _dataBound;
        private bool _subControlsDataBound;
        private bool _accessKeyRendered; 

        private PopOutPanel _panel; 
        private Style _panelStyle; 

        private bool _isNotIE; 

        private Type _designTimeTextWriterType;

        private MenuRenderer _renderer; 

        ///  
        ///     Creates a new instance of a Menu. 
        /// 
        public Menu() { 
            _nodeIndex = 0;
            _maximumDepth = 0;

            IncludeStyleBlock = true; 
        }
 
        internal bool AccessKeyRendered { 
            get {
                return _accessKeyRendered; 
            }
            set {
                _accessKeyRendered = value;
            } 
        }
 
        private Collection CachedLevelsContainingCssClass { 
            get {
                if (_cachedLevelsContainingCssClass == null) { 
                    _cachedLevelsContainingCssClass = new Collection();
                }
                return _cachedLevelsContainingCssClass;
            } 
        }
 
        private List CachedMenuItemClassNames { 
            get {
                if (_cachedMenuItemClassNames == null) { 
                    _cachedMenuItemClassNames = new List();
                }
                return _cachedMenuItemClassNames;
            } 
        }
 
        private List CachedMenuItemHyperLinkClassNames { 
            get {
                if (_cachedMenuItemHyperLinkClassNames == null) { 
                    _cachedMenuItemHyperLinkClassNames = new List();
                }
                return _cachedMenuItemHyperLinkClassNames;
            } 
        }
 
        private List CachedMenuItemStyles { 
            get {
                if (_cachedMenuItemStyles == null) { 
                    _cachedMenuItemStyles = new List();
                }
                return _cachedMenuItemStyles;
            } 
        }
 
        private List CachedSubMenuClassNames { 
            get {
                if (_cachedSubMenuClassNames == null) { 
                    _cachedSubMenuClassNames = new List();
                }
                return _cachedSubMenuClassNames;
            } 
        }
 
        private List CachedSubMenuStyles { 
            get {
                if (_cachedSubMenuStyles == null) { 
                    _cachedSubMenuStyles = new List();
                }
                return _cachedSubMenuStyles;
            } 
        }
 
 
        /// 
        ///     Gets the hidden field ID for the expand state of this Menu 
        /// 
        internal string ClientDataObjectID {
            get {
                // 
                return ClientID + "_Data";
            } 
        } 

        public override ControlCollection Controls { 
            get {
                EnsureChildControls();
                return base.Controls;
            } 
        }
 
        [ 
        DefaultValue(null),
        Editor("System.Web.UI.Design.WebControls.MenuBindingsEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)), 
        MergableProperty(false),
        PersistenceMode(PersistenceMode.InnerProperty),
        WebCategory("Data"),
        WebSysDescription(SR.Menu_Bindings) 
        ]
        public MenuItemBindingCollection DataBindings { 
            get { 
                if (_bindings == null) {
                    _bindings = new MenuItemBindingCollection(this); 
                    if (IsTrackingViewState) {
                        ((IStateManager)_bindings).TrackViewState();
                    }
                } 
                return _bindings;
            } 
        } 

 
        [WebCategory("Behavior")]
        [DefaultValue(500)]
        [WebSysDescription(SR.Menu_DisappearAfter)]
        [Themeable(false)] 
        public int DisappearAfter {
            get { 
                object o = ViewState["DisappearAfter"]; 
                if (o == null) {
                    return 500; 
                }
                return (int)o;
            }
            set { 
                if (value < -1) {
                    throw new ArgumentOutOfRangeException("value"); 
                } 
                ViewState["DisappearAfter"] = value;
            } 
        }


        [DefaultValue("")] 
        [Editor("System.Web.UI.Design.ImageUrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor))]
        [Themeable(true)] 
        [UrlProperty()] 
        [WebCategory("Appearance")]
        [WebSysDescription(SR.Menu_DynamicBottomSeparatorImageUrl)] 
        public string DynamicBottomSeparatorImageUrl {
            get {
                object s = ViewState["DynamicBottomSeparatorImageUrl"];
                if (s == null) { 
                    return String.Empty;
                } 
                return (string)s; 
            }
            set { 
                ViewState["DynamicBottomSeparatorImageUrl"] = value;
            }
        }
 

        [ 
        DefaultValue(true), 
        WebCategory("Appearance"),
        WebSysDescription(SR.Menu_DynamicDisplayPopOutImage) 
        ]
        public bool DynamicEnableDefaultPopOutImage {
            get {
                object o = ViewState["DynamicEnableDefaultPopOutImage"]; 
                if (o == null) {
                    return true; 
                } 
                return (bool)o;
            } 
            set {
                ViewState["DynamicEnableDefaultPopOutImage"] = value;
            }
        } 

 
        [ 
        DefaultValue(0),
        WebCategory("Appearance"), 
        WebSysDescription(SR.Menu_DynamicHorizontalOffset)
        ]
        public int DynamicHorizontalOffset {
            get { 
                object o = ViewState["DynamicHorizontalOffset"];
                if (o == null) { 
                    return 0; 
                }
                return (int)o; 
            }
            set {
                ViewState["DynamicHorizontalOffset"] = value;
            } 
        }
 
 
        [
        DefaultValue(null), 
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        NotifyParentProperty(true),
        PersistenceMode(PersistenceMode.InnerProperty),
        WebCategory("Styles"), 
        WebSysDescription(SR.Menu_DynamicHoverStyle)
        ] 
        public Style DynamicHoverStyle { 
            get {
                if (_dynamicHoverStyle == null) { 
                    _dynamicHoverStyle = new Style();
                    if (IsTrackingViewState) {
                        ((IStateManager)_dynamicHoverStyle).TrackViewState();
                    } 
                }
                return _dynamicHoverStyle; 
            } 
        }
 
        [DefaultValue("")]
        [WebCategory("Appearance")]
        [WebSysDescription(SR.Menu_DynamicItemFormatString)]
        public string DynamicItemFormatString { 
            get {
                object s = ViewState["DynamicItemFormatString"]; 
                if (s == null) { 
                    return String.Empty;
                } 
                return (string)s;
            }
            set {
                ViewState["DynamicItemFormatString"] = value; 
            }
        } 
 

        [ 
        WebCategory("Styles"),
        DefaultValue(null),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        NotifyParentProperty(true), 
        PersistenceMode(PersistenceMode.InnerProperty),
        WebSysDescription(SR.Menu_DynamicMenuItemStyle) 
        ] 
        public MenuItemStyle DynamicMenuItemStyle {
            get { 
                if (_dynamicItemStyle == null) {
                    _dynamicItemStyle = new MenuItemStyle();
                    if (IsTrackingViewState) {
                        ((IStateManager)_dynamicItemStyle).TrackViewState(); 
                    }
                } 
                return _dynamicItemStyle; 
            }
        } 


        [
        WebCategory("Styles"), 
        DefaultValue(null),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content), 
        NotifyParentProperty(true), 
        PersistenceMode(PersistenceMode.InnerProperty),
        WebSysDescription(SR.Menu_DynamicMenuStyle) 
        ]
        public SubMenuStyle DynamicMenuStyle {
            get {
                if (_dynamicMenuStyle == null) { 
                    _dynamicMenuStyle = new SubMenuStyle();
                    if (IsTrackingViewState) { 
                        ((IStateManager)_dynamicMenuStyle).TrackViewState(); 
                    }
                } 
                return _dynamicMenuStyle;
            }
        }
 

        [DefaultValue("")] 
        [Editor("System.Web.UI.Design.ImageUrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor))] 
        [UrlProperty()]
        [WebCategory("Appearance")] 
        [WebSysDescription(SR.Menu_DynamicPopoutImageUrl)]
        public string DynamicPopOutImageUrl {
            get {
                object s = ViewState["DynamicPopOutImageUrl"]; 
                if (s == null) {
                    return String.Empty; 
                } 
                return (string)s;
            } 
            set {
                ViewState["DynamicPopOutImageUrl"] = value;
            }
        } 

 
        [WebSysDefaultValue(SR.MenuAdapter_Expand)] 
        [WebCategory("Appearance")]
        [WebSysDescription(SR.Menu_DynamicPopoutImageText)] 
        public string DynamicPopOutImageTextFormatString {
            get {
                object s = ViewState["DynamicPopOutImageTextFormatString"];
                if (s == null) { 
                    return SR.GetString(SR.MenuAdapter_Expand);
                } 
                return (string)s; 
            }
            set { 
                ViewState["DynamicPopOutImageTextFormatString"] = value;
            }
        }
 

        [ 
        WebCategory("Styles"), 
        DefaultValue(null),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content), 
        NotifyParentProperty(true),
        PersistenceMode(PersistenceMode.InnerProperty),
        WebSysDescription(SR.Menu_DynamicSelectedStyle)
        ] 
        public MenuItemStyle DynamicSelectedStyle {
            get { 
                if (_dynamicSelectedStyle == null) { 
                    _dynamicSelectedStyle = new MenuItemStyle();
                    if (IsTrackingViewState) { 
                        ((IStateManager)_dynamicSelectedStyle).TrackViewState();
                    }
                }
                return _dynamicSelectedStyle; 
            }
        } 
 
        [
        Browsable(false), 
        DefaultValue(null),
        PersistenceMode(PersistenceMode.InnerProperty),
        TemplateContainer(typeof(MenuItemTemplateContainer)),
        WebSysDescription(SR.Menu_DynamicTemplate) 
        ]
        public ITemplate DynamicItemTemplate { 
            get { 
                return _dynamicTemplate;
            } 
            set {
                _dynamicTemplate = value;
            }
        } 

 
        [DefaultValue("")] 
        [Editor("System.Web.UI.Design.ImageUrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor))]
        [UrlProperty()] 
        [WebCategory("Appearance")]
        [WebSysDescription(SR.Menu_DynamicTopSeparatorImageUrl)]
        public string DynamicTopSeparatorImageUrl {
            get { 
                object s = ViewState["DynamicTopSeparatorImageUrl"];
                if (s == null) { 
                    return string.Empty; 
                }
                return (string)s; 
            }
            set {
                ViewState["DynamicTopSeparatorImageUrl"] = value;
            } 
        }
 
 
        [
        DefaultValue(0), 
        WebCategory("Appearance"),
        WebSysDescription(SR.Menu_DynamicVerticalOffset)
        ]
        public int DynamicVerticalOffset { 
            get {
                object o = ViewState["DynamicVerticalOffset"]; 
                if (o == null) { 
                    return 0;
                } 
                return (int)o;
            }
            set {
                ViewState["DynamicVerticalOffset"] = value; 
            }
        } 
 
        /// 
        ///     A cache of urls for the built-in images. 
        /// 
        private string[] ImageUrls {
            get {
                if (_imageUrls == null) { 
                    _imageUrls = new string[ImageUrlsCount];
                } 
                return _imageUrls; 
            }
        } 

        [DefaultValue(true)]
        [WebCategory("Appearance")]
        // 
        [Description("Determines whether or not to render the inline style block (only used in standards compliance mode)")]
        public bool IncludeStyleBlock { get; set; } 
 
        internal bool IsNotIE {
            get { 
                return _isNotIE;
            }
        }
 

        ///  
        ///     Gets the collection of top-level nodes. 
        /// 
        [ 
        DefaultValue(null),
        Editor("System.Web.UI.Design.WebControls.MenuItemCollectionEditor," + AssemblyRef.SystemDesign, typeof(UITypeEditor)),
        PersistenceMode(PersistenceMode.InnerProperty),
        MergableProperty(false), 
        WebSysDescription(SR.Menu_Items)
        ] 
        public MenuItemCollection Items { 
            get {
                return RootItem.ChildItems; 
            }
        }

 
        /// 
        ///     Gets and sets whether the text of the items should be wrapped 
        ///  
        [DefaultValue(false)]
        [WebCategory("Appearance")] 
        [WebSysDescription(SR.Menu_ItemWrap)]
        public bool ItemWrap {
            get {
                object o = ViewState["ItemWrap"]; 
                if (o == null) {
                    return false; 
                } 
                return (bool)o;
            } 
            set {
                ViewState["ItemWrap"] = value;
            }
        } 

 
        ///  
        ///     Gets the collection of MenuItemStyles corresponding to each level
        ///  
        [
        DefaultValue(null),
        Editor("System.Web.UI.Design.WebControls.MenuItemStyleCollectionEditor," + AssemblyRef.SystemDesign, typeof(UITypeEditor)),
        PersistenceMode(PersistenceMode.InnerProperty), 
        WebCategory("Styles"),
        WebSysDescription(SR.Menu_LevelMenuItemStyles), 
        ] 
        public MenuItemStyleCollection LevelMenuItemStyles {
            get { 
                if (_levelMenuItemStyles == null) {
                    _levelMenuItemStyles = new MenuItemStyleCollection();
                    if (IsTrackingViewState) {
                        ((IStateManager)_levelMenuItemStyles).TrackViewState(); 
                    }
                } 
 
                return _levelMenuItemStyles;
            } 
        }


        ///  
        ///     Gets the collection of MenuItemStyles corresponding to the selected item on each level
        ///  
        [ 
        DefaultValue(null),
        Editor("System.Web.UI.Design.WebControls.MenuItemStyleCollectionEditor," + AssemblyRef.SystemDesign, typeof(UITypeEditor)), 
        PersistenceMode(PersistenceMode.InnerProperty),
        WebCategory("Styles"),
        WebSysDescription(SR.Menu_LevelSelectedStyles),
        ] 
        public MenuItemStyleCollection LevelSelectedStyles {
            get { 
                if (_levelSelectedStyles == null) { 
                    _levelSelectedStyles = new MenuItemStyleCollection();
                    if (IsTrackingViewState) { 
                        ((IStateManager)_levelSelectedStyles).TrackViewState();
                    }
                }
 
                return _levelSelectedStyles;
            } 
        } 

 
        [
        DefaultValue(null),
        Editor("System.Web.UI.Design.WebControls.SubMenuStyleCollectionEditor," + AssemblyRef.SystemDesign, typeof(UITypeEditor)),
        PersistenceMode(PersistenceMode.InnerProperty), 
        WebCategory("Styles"),
        WebSysDescription(SR.Menu_LevelSubMenuStyles), 
        ] 
        public SubMenuStyleCollection LevelSubMenuStyles {
            get { 
                if (_levelStyles == null) {
                    _levelStyles = new SubMenuStyleCollection();
                    if (IsTrackingViewState) {
                        ((IStateManager)_levelStyles).TrackViewState(); 
                    }
                } 
 
                return _levelStyles;
            } 
        }

        internal int MaximumDepth {
            get { 
                if (_maximumDepth > 0) {
                    return _maximumDepth; 
                } 
                _maximumDepth = MaximumDynamicDisplayLevels + StaticDisplayLevels;
                if (_maximumDepth < MaximumDynamicDisplayLevels || _maximumDepth < StaticDisplayLevels) { 
                    _maximumDepth = int.MaxValue;
                }
                return _maximumDepth;
            } 
        }
 
 
        [WebCategory("Behavior")]
        [DefaultValue(3)] 
        [Themeable(true)]
        [WebSysDescription(SR.Menu_MaximumDynamicDisplayLevels)]
        public int MaximumDynamicDisplayLevels {
            get { 
                object o = ViewState["MaximumDynamicDisplayLevels"];
                if (o == null) { 
                    return 3; 
                }
                return (int)o; 
            }
            set {
                if (value < 0) {
                    throw new ArgumentOutOfRangeException("MaximumDynamicDisplayLevels", SR.GetString(SR.Menu_MaximumDynamicDisplayLevelsInvalid)); 
                }
                // Note: we're not testing against the old value here because 
                // the setter is not the only thing that can change the underlying 
                // ViewState entry: LoadViewState modifies it directly.
                ViewState["MaximumDynamicDisplayLevels"] = value; 
                // Reset max depth cache
                _maximumDepth = 0;
                // Rebind if necessary
                if (_dataBound) { 
                    _dataBound = false;
                    PerformDataBinding(); 
                } 
            }
        } 


        [WebCategory("Layout")]
        [DefaultValue(Orientation.Vertical)] 
        [WebSysDescription(SR.Menu_Orientation)]
        public Orientation Orientation { 
            get { 
                object o = ViewState["Orientation"];
                if (o == null) { 
                    return Orientation.Vertical;
                }
                return (Orientation)o;
            } 
            set {
                ViewState["Orientation"] = value; 
            } 
        }
 
        internal PopOutPanel Panel {
            get {
                if (_panel == null) {
                    _panel = new PopOutPanel(this, _panelStyle); 
                    if (!DesignMode) {
                        _panel.Page = Page; 
                    } 
                }
                return _panel; 
            }
        }

        [DefaultValue('/')] 
        [WebSysDescription(SR.Menu_PathSeparator)]
        public char PathSeparator { 
            get { 
                object o = ViewState["PathSeparator"];
                if (o == null) { 
                    return '/';
                }
                return (char)o;
            } 
            set {
                if (value == '\0') { 
                    ViewState["PathSeparator"] = null; 
                }
                else { 
                    ViewState["PathSeparator"] = value;
                }
                foreach (MenuItem item in Items) {
                    item.ResetValuePathRecursive(); 
                }
            } 
        } 

        internal string PopoutImageUrlInternal { 
            get {
                if (_cachedPopOutImageUrl != null) {
                    return _cachedPopOutImageUrl;
                } 
                _cachedPopOutImageUrl = Page.ClientScript.GetWebResourceUrl(typeof(Menu), ("Menu_Popout.gif"));
                return _cachedPopOutImageUrl; 
            } 
        }
 
        private MenuRenderer Renderer {
            get {
                if (_renderer == null) {
                    switch (RenderingMode) { 
                        case MenuRenderingMode.Table:
                            _renderer = new MenuRendererClassic(this); 
                            break; 
                        case MenuRenderingMode.List:
                            _renderer = new MenuRendererStandards(this); 
                            break;
                        case MenuRenderingMode.Default:
                            if (RenderingCompatibility < VersionUtil.Framework40) {
                                _renderer = new MenuRendererClassic(this); 
                            }
                            else { 
                                _renderer = new MenuRendererStandards(this); 
                            }
                            break; 
                        default:
                            Debug.Fail("Unknown MenuRenderingMode.");
                            break;
                    } 
                }
                return _renderer; 
            } 
        }
 
        [
        WebCategory("Layout"),
        DefaultValue(MenuRenderingMode.Default),
        WebSysDescription(SR.Menu_RenderingMode) 
        ]
        public MenuRenderingMode RenderingMode { 
            get { 
                return _renderingMode;
            } 
            set {
                if (value < MenuRenderingMode.Default || value > MenuRenderingMode.List) {
                    throw new ArgumentOutOfRangeException("value");
                } 
                if (_renderer != null) {
                    throw new InvalidOperationException(SR.GetString(SR.Menu_CannotChangeRenderingMode)); 
                } 
                _renderingMode = value;
            } 
        }

        /// 
        ///     The 'virtual' root node of the menu. This menu item is never shown. 
        ///     It is the parent of the "real" root items.
        ///  
        internal MenuItem RootItem { 
            get {
                if (_rootItem == null) { 
                    _rootItem = new MenuItem(this, true);
                }
                return _rootItem;
            } 
        }
 
        // RootMenuItemStyle is roughly equivalent to ControlStyle.HyperLinkStyle if it existed. 
        internal Style RootMenuItemStyle {
            get { 
                EnsureRootMenuStyle();
                return _rootMenuItemStyle;
            }
        } 

        [DefaultValue("")] 
        [Editor("System.Web.UI.Design.ImageUrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor))] 
        [UrlProperty()]
        [WebCategory("Appearance")] 
        [WebSysDescription(SR.Menu_ScrollDownImageUrl)]
        public string ScrollDownImageUrl {
            get {
                object s = ViewState["ScrollDownImageUrl"]; 
                if (s == null) {
                    return String.Empty; 
                } 
                return (string)s;
            } 
            set {
                ViewState["ScrollDownImageUrl"] = value;
            }
        } 

        internal string ScrollDownImageUrlInternal { 
            get { 
                if (_cachedScrollDownImageUrl != null) {
                    return _cachedScrollDownImageUrl; 
                }
                _cachedScrollDownImageUrl = Page.ClientScript.GetWebResourceUrl(typeof(Menu), ("Menu_ScrollDown.gif"));
                return _cachedScrollDownImageUrl;
            } 
        }
 
 
        [WebSysDefaultValue(SR.Menu_ScrollDown)]
        [Localizable(true)] 
        [WebCategory("Appearance")]
        [WebSysDescription(SR.Menu_ScrollDownText)]
        public string ScrollDownText {
            get { 
                object s = ViewState["ScrollDownText"];
                if (s == null) { 
                    return SR.GetString(SR.Menu_ScrollDown); 
                }
                return (string)s; 
            }
            set {
                ViewState["ScrollDownText"] = value;
            } 
        }
 
 
        [DefaultValue("")]
        [Editor("System.Web.UI.Design.ImageUrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor))] 
        [UrlProperty()]
        [WebCategory("Appearance")]
        [WebSysDescription(SR.Menu_ScrollUpImageUrl)]
        public string ScrollUpImageUrl { 
            get {
                object s = ViewState["ScrollUpImageUrl"]; 
                if (s == null) { 
                    return String.Empty;
                } 
                return (string)s;
            }
            set {
                ViewState["ScrollUpImageUrl"] = value; 
            }
        } 
 
        internal string ScrollUpImageUrlInternal {
            get { 
                if (_cachedScrollUpImageUrl != null) {
                    return _cachedScrollUpImageUrl;
                }
                _cachedScrollUpImageUrl = Page.ClientScript.GetWebResourceUrl(typeof(Menu), ("Menu_ScrollUp.gif")); 
                return _cachedScrollUpImageUrl;
            } 
        } 

 
        [WebSysDefaultValue(SR.Menu_ScrollUp)]
        [Localizable(true)]
        [WebCategory("Appearance")]
        [WebSysDescription(SR.Menu_ScrollUpText)] 
        public string ScrollUpText {
            get { 
                object s = ViewState["ScrollUpText"]; 
                if (s == null) {
                    return SR.GetString(SR.Menu_ScrollUp); 
                }
                return (string)s;
            }
            set { 
                ViewState["ScrollUpText"] = value;
            } 
        } 

 
        /// 
        ///     Gets and sets the Menu's selected node.
        /// 
        [ 
        Browsable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), 
        ] 
        public MenuItem SelectedItem {
            get { 
                return _selectedItem;
            }
        }
 

        [Browsable(false)] 
        [DefaultValue("")] 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public string SelectedValue { 
            get {
                if (SelectedItem != null) {
                    return SelectedItem.Value;
                } 

                return String.Empty; 
            } 
        }
 

        [WebSysDefaultValue(SR.Menu_SkipLinkTextDefault)]
        [Localizable(true)]
        [WebCategory("Accessibility")] 
        [WebSysDescription(SR.WebControl_SkipLinkText)]
        public string SkipLinkText { 
            get { 
                object s = ViewState["SkipLinkText"];
                if (s == null) { 
                    return SR.GetString(SR.Menu_SkipLinkTextDefault);
                }
                return (string)s;
            } 
            set {
                ViewState["SkipLinkText"] = value; 
            } 
        }
 

        [DefaultValue("")]
        [Editor("System.Web.UI.Design.ImageUrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor))]
        [UrlProperty()] 
        [WebCategory("Appearance")]
        [WebSysDescription(SR.Menu_StaticBottomSeparatorImageUrl)] 
        public string StaticBottomSeparatorImageUrl { 
            get {
                object s = ViewState["StaticBottomSeparatorImageUrl"]; 
                if (s == null) {
                    return String.Empty;
                }
                return (string)s; 
            }
            set { 
                ViewState["StaticBottomSeparatorImageUrl"] = value; 
            }
        } 


        [WebCategory("Behavior")]
        [DefaultValue(1)] 
        [Themeable(true)]
        [WebSysDescription(SR.Menu_StaticDisplayLevels)] 
        public int StaticDisplayLevels { 
            get {
                object o = ViewState["StaticDisplayLevels"]; 
                if (o == null) {
                    return 1;
                }
                return (int)o; 
            }
            set { 
                if (value < 1) { 
                    throw new ArgumentOutOfRangeException("value");
                } 
                // Note: we're not testing against the old value here because
                // the setter is not the only thing that can change the underlying
                // ViewState entry: LoadViewState modifies it directly.
                ViewState["StaticDisplayLevels"] = value; 
                // Reset max depth cache
                _maximumDepth = 0; 
                // Rebind if necessary 
                if (_dataBound && !DesignMode) {
                    _dataBound = false; 
                    PerformDataBinding();
                }
            }
        } 

 
        [ 
        DefaultValue(true),
        WebCategory("Appearance"), 
        WebSysDescription(SR.Menu_StaticDisplayPopOutImage)
        ]
        public bool StaticEnableDefaultPopOutImage {
            get { 
                object o = ViewState["StaticEnableDefaultPopOutImage"];
                if (o == null) { 
                    return true; 
                }
                return (bool)o; 
            }
            set {
                ViewState["StaticEnableDefaultPopOutImage"] = value;
            } 
        }
 
 
        [
        DefaultValue(null), 
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        NotifyParentProperty(true),
        PersistenceMode(PersistenceMode.InnerProperty),
        WebCategory("Styles"), 
        WebSysDescription(SR.Menu_StaticHoverStyle)
        ] 
        public Style StaticHoverStyle { 
            get {
                if (_staticHoverStyle == null) { 
                    _staticHoverStyle = new Style();
                    if (IsTrackingViewState) {
                        ((IStateManager)_staticHoverStyle).TrackViewState();
                    } 
                }
                return _staticHoverStyle; 
            } 
        }
 
        [DefaultValue("")]
        [WebCategory("Appearance")]
        [WebSysDescription(SR.Menu_StaticItemFormatString)]
        public string StaticItemFormatString { 
            get {
                object s = ViewState["StaticItemFormatString"]; 
                if (s == null) { 
                    return String.Empty;
                } 
                return (string)s;
            }
            set {
                ViewState["StaticItemFormatString"] = value; 
            }
        } 
 

        [ 
        WebCategory("Styles"),
        DefaultValue(null),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        NotifyParentProperty(true), 
        PersistenceMode(PersistenceMode.InnerProperty),
        WebSysDescription(SR.Menu_StaticMenuItemStyle) 
        ] 
        public MenuItemStyle StaticMenuItemStyle {
            get { 
                if (_staticItemStyle == null) {
                    _staticItemStyle = new MenuItemStyle();
                    if (IsTrackingViewState) {
                        ((IStateManager)_staticItemStyle).TrackViewState(); 
                    }
                } 
                return _staticItemStyle; 
            }
        } 


        [
        WebCategory("Styles"), 
        DefaultValue(null),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content), 
        NotifyParentProperty(true), 
        PersistenceMode(PersistenceMode.InnerProperty),
        WebSysDescription(SR.Menu_StaticMenuStyle) 
        ]
        public SubMenuStyle StaticMenuStyle {
            get {
                if (_staticMenuStyle == null) { 
                    _staticMenuStyle = new SubMenuStyle();
                    if (IsTrackingViewState) { 
                        ((IStateManager)_staticMenuStyle).TrackViewState(); 
                    }
                } 
                return _staticMenuStyle;
            }
        }
 

        [DefaultValue("")] 
        [Editor("System.Web.UI.Design.ImageUrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor))] 
        [UrlProperty()]
        [WebCategory("Appearance")] 
        [WebSysDescription(SR.Menu_StaticPopoutImageUrl)]
        public string StaticPopOutImageUrl {
            get {
                object s = ViewState["StaticPopOutImageUrl"]; 
                if (s == null) {
                    return String.Empty; 
                } 
                return (string)s;
            } 
            set {
                ViewState["StaticPopOutImageUrl"] = value;
            }
        } 

 
        [WebSysDefaultValue(SR.MenuAdapter_Expand)] 
        [WebCategory("Appearance")]
        [WebSysDescription(SR.Menu_StaticPopoutImageText)] 
        public string StaticPopOutImageTextFormatString {
            get {
                object s = ViewState["StaticPopOutImageTextFormatString"];
                if (s == null) { 
                    return SR.GetString(SR.MenuAdapter_Expand);
                } 
                return (string)s; 
            }
            set { 
                ViewState["StaticPopOutImageTextFormatString"] = value;
            }
        }
 

        [ 
        WebCategory("Styles"), 
        DefaultValue(null),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content), 
        NotifyParentProperty(true),
        PersistenceMode(PersistenceMode.InnerProperty),
        WebSysDescription(SR.Menu_StaticSelectedStyle)
        ] 
        public MenuItemStyle StaticSelectedStyle {
            get { 
                if (_staticSelectedStyle == null) { 
                    _staticSelectedStyle = new MenuItemStyle();
                    if (IsTrackingViewState) { 
                        ((IStateManager)_staticSelectedStyle).TrackViewState();
                    }
                }
                return _staticSelectedStyle; 
            }
        } 
 

        [WebCategory("Appearance")] 
        [DefaultValue(typeof(Unit), "")]
        [Themeable(true)]
        [WebSysDescription(SR.Menu_StaticSubMenuIndent)]
        public Unit StaticSubMenuIndent { 
            get {
                object o = ViewState["StaticSubMenuIndent"]; 
                if (o == null) { 
                    return Unit.Empty;
                } 
                return (Unit)o;
            }
            set {
                if (value.Value < 0) { 
                    throw new ArgumentOutOfRangeException("value");
                } 
                ViewState["StaticSubMenuIndent"] = value; 
            }
        } 

        [
        Browsable(false),
        DefaultValue(null), 
        PersistenceMode(PersistenceMode.InnerProperty),
        TemplateContainer(typeof(MenuItemTemplateContainer)), 
        WebSysDescription(SR.Menu_StaticTemplate) 
        ]
        public ITemplate StaticItemTemplate { 
            get {
                return _staticTemplate;
            }
            set { 
                _staticTemplate = value;
            } 
        } 

 
        [DefaultValue("")]
        [Editor("System.Web.UI.Design.ImageUrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor))]
        [UrlProperty()]
        [WebCategory("Appearance")] 
        [WebSysDescription(SR.Menu_StaticTopSeparatorImageUrl)]
        public string StaticTopSeparatorImageUrl { 
            get { 
                object s = ViewState["StaticTopSeparatorImageUrl"];
                if (s == null) { 
                    return String.Empty;
                }
                return (string)s;
            } 
            set {
                ViewState["StaticTopSeparatorImageUrl"] = value; 
            } 
        }
 

        /// 
        ///     Gets and sets the target window that the MenuItems 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; 
            }
        } 


        protected override HtmlTextWriterTag TagKey {
            get { 
                return HtmlTextWriterTag.Table;
            } 
        } 

        #region events 

        /// 
        ///     Triggered when an item has been clicked.
        ///  
        [WebCategory("Behavior")]
        [WebSysDescription(SR.Menu_MenuItemClick)] 
        public event MenuEventHandler MenuItemClick { 
            add {
                Events.AddHandler(_menuItemClickedEvent, value); 
            }
            remove {
                Events.RemoveHandler(_menuItemClickedEvent, value);
            } 
        }
 
 
        /// 
        ///     Triggered when a MenuItem has been databound. 
        /// 
        [WebCategory("Behavior")]
        [WebSysDescription(SR.Menu_MenuItemDataBound)]
        public event MenuEventHandler MenuItemDataBound { 
            add {
                Events.AddHandler(_menuItemDataBoundEvent, value); 
            } 
            remove {
                Events.RemoveHandler(_menuItemDataBoundEvent, value); 
            }
        }
        #endregion
 
        protected override void AddAttributesToRender(HtmlTextWriter writer) {
            VerifyRenderingInServerForm(); 
 
            string oldAccessKey = AccessKey;
            try { 
                AccessKey = String.Empty;
                base.AddAttributesToRender(writer);
            }
            finally { 
                AccessKey = oldAccessKey;
            } 
        } 

        // returns true if the style contains a class name 
        private static bool AppendCssClassName(StringBuilder builder, MenuItemStyle style, bool hyperlink) {
            bool containsClassName = false;
            if (style != null) {
                // We have to merge with any CssClass specified on the Style itself 
                if (style.CssClass.Length != 0) {
                    builder.Append(style.CssClass); 
                    builder.Append(' '); 
                    containsClassName = true;
                } 

                string className = (hyperlink ?
                    style.HyperLinkStyle.RegisteredCssClass :
                    style.RegisteredCssClass); 
                if (className.Length > 0) {
                    builder.Append(className); 
                    builder.Append(' '); 
                }
            } 
            return containsClassName;
        }

        private static void AppendMenuCssClassName(StringBuilder builder, SubMenuStyle style) { 
            if (style != null) {
                // We have to merge with any CssClass specified on the Style itself 
                if (style.CssClass.Length != 0) { 
                    builder.Append(style.CssClass);
                    builder.Append(' '); 
                }
                string className = style.RegisteredCssClass;
                if (className.Length > 0) {
                    builder.Append(className); 
                    builder.Append(' ');
                } 
            } 
        }
 
        private static T CacheGetItem(List cacheList, int index) where T : class {
            Debug.Assert(cacheList != null);
            if (index < cacheList.Count) return cacheList[index];
            return null; 
        }
 
        private static void CacheSetItem(List cacheList, int index, T item) where T : class { 
            if (cacheList.Count > index) {
                cacheList[index] = item; 
            }
            else {
                for (int i = cacheList.Count; i < index; i++) {
                    cacheList.Add(null); 
                }
                cacheList.Add(item); 
            } 
        }
 
        protected internal override void CreateChildControls() {
            Controls.Clear();

            if ((StaticItemTemplate != null) || (DynamicItemTemplate != null)) { 
                if (RequiresDataBinding &&
                    (!String.IsNullOrEmpty(DataSourceID) || DataSource != null)) { 
                    EnsureDataBound(); 
                }
                else { 
                    // Creating child controls from the Items tree
                    CreateChildControlsFromItems(/* dataBinding */ false);
                    ClearChildViewState();
                } 
            }
        } 
 

        private void CreateChildControlsFromItems(bool dataBinding) { 
            if (StaticItemTemplate != null || DynamicItemTemplate != null) {
                int childPosition = 0;
                foreach (MenuItem child in Items) {
                    CreateTemplatedControls(StaticItemTemplate, child, childPosition++, 0, dataBinding); 
                }
            } 
        } 

        ///  
        ///     Creates a menu node index that is unique for this menu
        /// 
        internal int CreateItemIndex() {
            return _nodeIndex++; 
        }
 
        private void CreateTemplatedControls(ITemplate template, MenuItem item, int position, int depth, bool dataBinding) { 

            if (template != null) { 
                MenuItemTemplateContainer container = new MenuItemTemplateContainer(position, item);
                item.Container = (MenuItemTemplateContainer)container;
                template.InstantiateIn(container);
                Controls.Add(container); 
                if (dataBinding) {
                    container.DataBind(); 
                } 
            }
            int childPosition = 0; 
            foreach (MenuItem child in item.ChildItems) {
                int nextDepth = depth + 1;
                if (template == DynamicItemTemplate) {
                    CreateTemplatedControls(DynamicItemTemplate, child, childPosition++, nextDepth, dataBinding); 
                }
                else { 
                    if (nextDepth < StaticDisplayLevels) { 
                        CreateTemplatedControls(template, child, childPosition++, nextDepth, dataBinding);
                    } 
                    else if (DynamicItemTemplate != null) {
                        CreateTemplatedControls(DynamicItemTemplate, child, childPosition++, nextDepth, dataBinding);
                    }
                } 
            }
        } 
 
        /// Data bound controls should override PerformDataBinding instead
        /// of DataBind.  If DataBind if overridden, the OnDataBinding and OnDataBound events will 
        /// fire in the wrong order.  However, for backwards compat on ListControl and AdRotator, we
        /// can't seal this method.  It is sealed on all new BaseDataBoundControl-derived controls.
        public override sealed void DataBind() {
            base.DataBind(); 
        }
 
 
        /// 
        ///     Databinds the specified node to the datasource 
        /// 
        private void DataBindItem(MenuItem item) {
            HierarchicalDataSourceView view = GetData(item.DataPath);
            // Do nothing if no datasource was set 
            if (!IsBoundUsingDataSourceID && (DataSource == null)) {
                return; 
            } 

            if (view == null) { 
                throw new InvalidOperationException(SR.GetString(SR.Menu_DataSourceReturnedNullView, ID));
            }
            IHierarchicalEnumerable enumerable = view.Select();
            item.ChildItems.Clear(); 
            if (enumerable != null) {
                // If we're bound to a SiteMapDataSource, automatically select the node 
                if (IsBoundUsingDataSourceID) { 
                    SiteMapDataSource siteMapDataSource = GetDataSource() as SiteMapDataSource;
                    if (siteMapDataSource != null) { 
                        SiteMapNode currentNode = siteMapDataSource.Provider.CurrentNode;
                        if (currentNode != null) {
                            _currentSiteMapNodeUrl = currentNode.Url;
                        } 
                    }
                } 
 
                try {
                    DataBindRecursive(item, enumerable); 
                }
                finally {
                    _currentSiteMapNodeUrl = null;
                } 
            }
        } 
 

        ///  
        ///     Databinds recursively, using the Menu's Bindings collection, until there is no more data.
        /// 
        private void DataBindRecursive(MenuItem node, IHierarchicalEnumerable enumerable) {
            // Since we are binding children, get the level below the current node's depth 
            int depth = node.Depth + 1;
 
            // Don't databind beyond the maximum specified depth 
            if ((MaximumDynamicDisplayLevels != -1) && (depth >= MaximumDepth)) {
                return; 
            }

            foreach (object item in enumerable) {
                IHierarchyData data = enumerable.GetHierarchyData(item); 

                string text = null; 
                string value = null; 
                string navigateUrl = String.Empty;
                string imageUrl = String.Empty; 
                string popOutImageUrl = String.Empty;
                string separatorImageUrl = String.Empty;
                string target = String.Empty;
                bool enabled = true; 
                bool enabledSet = false;
                bool selectable = true; 
                bool selectableSet = false; 
                string toolTip = String.Empty;
 
                string dataMember = String.Empty;

                dataMember = data.Type;
 
                MenuItemBinding level = DataBindings.GetBinding(dataMember, depth);
 
                if (level != null) { 

                    PropertyDescriptorCollection props = TypeDescriptor.GetProperties(item); 

                    // Bind Text, using the static value if necessary
                    string textField = level.TextField;
                    if (textField.Length > 0) { 
                        PropertyDescriptor desc = props.Find(textField, true);
                        if (desc != null) { 
                            object objData = desc.GetValue(item); 
                            if (objData != null) {
                                if (level.FormatString.Length > 0) { 
                                    text = string.Format(CultureInfo.CurrentCulture, level.FormatString, objData);
                                }
                                else {
                                    text = objData.ToString(); 
                                }
                            } 
                        } 
                        else {
                            throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidDataBinding, textField, "TextField")); 
                        }
                    }

                    if (String.IsNullOrEmpty(text) && !String.IsNullOrEmpty(level.Text)) { 
                        text = level.Text;
                    } 
 
                    // Bind Value, using the static value if necessary
                    string valueField = level.ValueField; 
                    if (valueField.Length > 0) {
                        PropertyDescriptor desc = props.Find(valueField, true);
                        if (desc != null) {
                            object objData = desc.GetValue(item); 
                            if (objData != null) {
                                value = objData.ToString(); 
                            } 
                        }
                        else { 
                            throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidDataBinding, valueField, "ValueField"));
                        }
                    }
 
                    if (String.IsNullOrEmpty(value) && !String.IsNullOrEmpty(level.Value)) {
                        value = level.Value; 
                    } 

                    // Bind Target, using the static value if necessary 
                    string targetField = level.TargetField;
                    if (targetField.Length > 0) {
                        PropertyDescriptor desc = props.Find(targetField, true);
                        if (desc != null) { 
                            object objData = desc.GetValue(item);
                            if (objData != null) { 
                                target = objData.ToString(); 
                            }
                        } 
                        else {
                            throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidDataBinding, targetField, "TargetField"));
                        }
                    } 

                    if (String.IsNullOrEmpty(target)) { 
                        target = level.Target; 
                    }
 
                    // Bind ImageUrl, using the static value if necessary
                    string imageUrlField = level.ImageUrlField;
                    if (imageUrlField.Length > 0) {
                        PropertyDescriptor desc = props.Find(imageUrlField, true); 
                        if (desc != null) {
                            object objData = desc.GetValue(item); 
                            if (objData != null) { 
                                imageUrl = objData.ToString();
                            } 
                        }
                        else {
                            throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidDataBinding, imageUrlField, "ImageUrlField"));
                        } 
                    }
 
                    if (String.IsNullOrEmpty(imageUrl)) { 
                        imageUrl = level.ImageUrl;
                    } 

                    // Bind NavigateUrl, using the static value if necessary
                    string navigateUrlField = level.NavigateUrlField;
                    if (navigateUrlField.Length > 0) { 
                        PropertyDescriptor desc = props.Find(navigateUrlField, true);
                        if (desc != null) { 
                            object objData = desc.GetValue(item); 
                            if (objData != null) {
                                navigateUrl = objData.ToString(); 
                            }
                        }
                        else {
                            throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidDataBinding, navigateUrlField, "NavigateUrlField")); 
                        }
                    } 
 
                    if (String.IsNullOrEmpty(navigateUrl)) {
                        navigateUrl = level.NavigateUrl; 
                    }

                    // Bind PopOutImageUrl, using the static value if necessary
                    string popOutImageUrlField = level.PopOutImageUrlField; 
                    if (popOutImageUrlField.Length > 0) {
                        PropertyDescriptor desc = props.Find(popOutImageUrlField, true); 
                        if (desc != null) { 
                            object objData = desc.GetValue(item);
                            if (objData != null) { 
                                popOutImageUrl = objData.ToString();
                            }
                        }
                        else { 
                            throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidDataBinding, popOutImageUrlField, "PopOutImageUrlField"));
                        } 
                    } 

                    if (String.IsNullOrEmpty(popOutImageUrl)) { 
                        popOutImageUrl = level.PopOutImageUrl;
                    }

                    // Bind SeperatorImageUrl, using the static value if necessary 
                    string separatorImageUrlField = level.SeparatorImageUrlField;
                    if (separatorImageUrlField.Length > 0) { 
                        PropertyDescriptor desc = props.Find(separatorImageUrlField, true); 
                        if (desc != null) {
                            object objData = desc.GetValue(item); 
                            if (objData != null) {
                                separatorImageUrl = objData.ToString();
                            }
                        } 
                        else {
                            throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidDataBinding, separatorImageUrlField, "SeparatorImageUrlField")); 
                        } 
                    }
 
                    if (String.IsNullOrEmpty(separatorImageUrl)) {
                        separatorImageUrl = level.SeparatorImageUrl;
                    }
 
                    // Bind ToolTip, using the static value if necessary
                    string toolTipField = level.ToolTipField; 
                    if (toolTipField.Length > 0) { 
                        PropertyDescriptor desc = props.Find(toolTipField, true);
                        if (desc != null) { 
                            object objData = desc.GetValue(item);
                            if (objData != null) {
                                toolTip = objData.ToString();
                            } 
                        }
                        else { 
                            throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidDataBinding, toolTipField, "ToolTipField")); 
                        }
                    } 

                    if (String.IsNullOrEmpty(toolTip)) {
                        toolTip = level.ToolTip;
                    } 

                    // Bind Enabled, using the static value if necessary 
                    string enabledField = level.EnabledField; 
                    if (enabledField.Length > 0) {
                        PropertyDescriptor desc = props.Find(enabledField, true); 
                        if (desc != null) {
                            object objData = desc.GetValue(item);
                            if (objData != null) {
                                if (objData is bool) { 
                                    enabled = (bool)objData;
                                    enabledSet = true; 
                                } 
                                else if (bool.TryParse(objData.ToString(), out enabled)) {
                                    enabledSet = true; 
                                }
                            }
                        }
                        else { 
                            throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidDataBinding, enabledField, "EnabledField"));
                        } 
                    } 

                    if (!enabledSet) { 
                        enabled = level.Enabled;
                    }

                    // Bind Selectable, using the static value if necessary 
                    string selectableField = level.SelectableField;
                    if (selectableField.Length > 0) { 
                        PropertyDescriptor desc = props.Find(selectableField, true); 
                        if (desc != null) {
                            object objData = desc.GetValue(item); 
                            if (objData != null) {
                                if (objData is bool) {
                                    selectable = (bool)objData;
                                    selectableSet = true; 
                                }
                                else if (bool.TryParse(objData.ToString(), out selectable)) { 
                                    selectableSet = true; 
                                }
                            } 
                        }
                        else {
                            throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidDataBinding, selectableField, "SelectableField"));
                        } 
                    }
 
                    if (!selectableSet) { 
                        selectable = level.Selectable;
                    } 
                }
                else if (item is INavigateUIData) {
                    INavigateUIData navigateUIData = (INavigateUIData)item;
                    text = navigateUIData.Name; 
                    value = navigateUIData.Value;
                    navigateUrl = navigateUIData.NavigateUrl; 
                    if (String.IsNullOrEmpty(navigateUrl)) { 
                        selectable = false;
                    } 
                    toolTip = navigateUIData.Description;
                }

                if (text == null) { 
                    text = item.ToString();
                } 
 
                MenuItem newItem = null;
                // Allow String.Empty for the text, but not null 
                if ((text != null) || (value != null)) {
                    newItem = new MenuItem(text, value, imageUrl, navigateUrl, target);
                }
 
                if (newItem != null) {
                    if (toolTip.Length > 0) { 
                        newItem.ToolTip = toolTip; 
                    }
                    if (popOutImageUrl.Length > 0) { 
                        newItem.PopOutImageUrl = popOutImageUrl;
                    }
                    if (separatorImageUrl.Length > 0) {
                        newItem.SeparatorImageUrl = separatorImageUrl; 
                    }
                    newItem.Enabled = enabled; 
                    newItem.Selectable = selectable; 

                    newItem.SetDataPath(data.Path); 
                    newItem.SetDataBound(true);

                    node.ChildItems.Add(newItem);
 
                    if (String.Equals(data.Path, _currentSiteMapNodeUrl, StringComparison.OrdinalIgnoreCase)) {
                        newItem.Selected = true; 
                    } 

                    // Make sure we call user code if they've hooked the populate event 
                    newItem.SetDataItem(data.Item);
                    OnMenuItemDataBound(new MenuEventArgs(newItem));
                    newItem.SetDataItem(null);
 
                    if (data.HasChildren && (depth < MaximumDepth)) {
                        IHierarchicalEnumerable newEnumerable = data.GetChildren(); 
                        if (newEnumerable != null) { 
                            DataBindRecursive(newItem, newEnumerable);
                        } 
                    }
                }
            }
        } 

        protected override void EnsureDataBound() { 
            base.EnsureDataBound(); 
            if (!_subControlsDataBound) {
                foreach (Control ctrl in Controls) { 
                    ctrl.DataBind();
                }
                _subControlsDataBound = true;
            } 
        }
 
        public MenuItem FindItem(string valuePath) { 
            if (valuePath == null) {
                return null; 
            }
            return Items.FindItem(valuePath.Split(PathSeparator), 0);
        }
 
        internal string GetCssClassName(MenuItem item, bool hyperLink) {
            bool discarded; 
            return GetCssClassName(item, hyperLink, out discarded); 
        }
 
        internal string GetCssClassName(MenuItem item, bool hyperlink, out bool containsClassName) {
            if (item == null) {
                throw new ArgumentNullException("item");
            } 

            containsClassName = false; 
            int depth = item.Depth; 
            string baseClassName = CacheGetItem(
                hyperlink ? CachedMenuItemHyperLinkClassNames : CachedMenuItemClassNames, 
                depth);
            if (CachedLevelsContainingCssClass.Contains(depth)) {
                containsClassName = true;
            } 

            if (!item.Selected && (baseClassName != null)) { 
                return baseClassName; 
            }
 
            StringBuilder builder = new StringBuilder();
            if (baseClassName != null) {
                if (!item.Selected) return baseClassName;
                builder.Append(baseClassName); 
                builder.Append(' ');
            } 
            else { 
                // No cached style, so build it
                if (hyperlink) { 
                    builder.Append(RootMenuItemStyle.RegisteredCssClass);
                    builder.Append(' ');
                }
 
                if (depth < StaticDisplayLevels) {
                    containsClassName |= AppendCssClassName(builder, _staticItemStyle, hyperlink); 
                } 
                else {
                    containsClassName |= AppendCssClassName(builder, _dynamicItemStyle, hyperlink); 
                }
                if ((depth < LevelMenuItemStyles.Count) && (LevelMenuItemStyles[depth] != null)) {
                    containsClassName |= AppendCssClassName(builder, LevelMenuItemStyles[depth], hyperlink);
                } 

                baseClassName = builder.ToString().Trim(); 
                CacheSetItem( 
                    hyperlink ? CachedMenuItemHyperLinkClassNames : CachedMenuItemClassNames,
                    depth, 
                    baseClassName);

                if (containsClassName && !CachedLevelsContainingCssClass.Contains(depth)) {
                    CachedLevelsContainingCssClass.Add(depth); 
                }
            } 
 
            if (item.Selected) {
                if (depth < StaticDisplayLevels) { 
                    containsClassName |= AppendCssClassName(builder, _staticSelectedStyle, hyperlink);
                }
                else {
                    containsClassName |= AppendCssClassName(builder, _dynamicSelectedStyle, hyperlink); 
                }
                if ((depth < LevelSelectedStyles.Count) && (LevelSelectedStyles[depth] != null)) { 
                    MenuItemStyle style = LevelSelectedStyles[depth]; 
                    containsClassName |= AppendCssClassName(builder, style, hyperlink);
                } 
                return builder.ToString().Trim();
            }
            return baseClassName;
        } 

        /// Used by GetDesignModeState to find the first dynamic submenu in Items 
        private MenuItem GetOneDynamicItem(MenuItem item) { 
            if (item.Depth >= StaticDisplayLevels) {
                return item; 
            }
            for (int i = 0; i < item.ChildItems.Count; i++) {
                MenuItem result = GetOneDynamicItem(item.ChildItems[i]);
                if (result != null) { 
                    return result;
                } 
            } 
            return null;
        } 


        /// 
        ///  
        /// The designer can get the static and the dynamic mode html by using the
        /// _getDesignTimeStaticHtml and _getDesignTimeDynamicHtml defined string keys 
        /// of the dictionary. 
        /// 
        [SecurityPermission(SecurityAction.Demand, Unrestricted = true)] 
        protected override IDictionary GetDesignModeState() {
            IDictionary dictionary = base.GetDesignModeState();
            Debug.Assert(dictionary != null && DesignMode);
 
            CreateChildControls();
            foreach (Control c in Controls) { 
                c.DataBind(); 
            }
 
            // Create the html for the static part
            using (StringWriter staticHtmlBuilder = new StringWriter(CultureInfo.CurrentCulture)) {
                using (HtmlTextWriter htmlWriter = GetDesignTimeWriter(staticHtmlBuilder)) {
                    Renderer.RenderBeginTag(htmlWriter, true); 
                    Renderer.RenderContents(htmlWriter, true);
                    Renderer.RenderEndTag(htmlWriter, true); 
                    dictionary[_getDesignTimeStaticHtml] = staticHtmlBuilder.ToString(); 
                }
            } 
            // Remember the static depth so we can lower it if necessary to make it faster and avoid overflows
            int oldStaticDisplayLevels = StaticDisplayLevels;
            try {
                // Find a dynamic sub-menu 
                MenuItem dynamicSubMenu = GetOneDynamicItem(RootItem);
                if (dynamicSubMenu == null) { 
                    // We need to forge a whole new dynamic submenu 
                    // First lower the static display levels
                    _dataBound = false; 
                    StaticDisplayLevels = 1;
                    dynamicSubMenu = new MenuItem();
                    dynamicSubMenu.SetDepth(0);
                    dynamicSubMenu.SetOwner(this); 
                    // Create a single dynamic submenu, with one submenu
                    string dummyText = SR.GetString(SR.Menu_DesignTimeDummyItemText); 
                    for (int i = 0; i < 5; i++) { 
                        MenuItem newItem = new MenuItem(dummyText);
                        if (DynamicItemTemplate != null) { 
                            MenuItemTemplateContainer container = new MenuItemTemplateContainer(i, newItem);
                            newItem.Container = container;
                            DynamicItemTemplate.InstantiateIn(container);
                            container.Site = this.Site; 
                            container.DataBind();
                        } 
                        dynamicSubMenu.ChildItems.Add(newItem); 
                    }
                    dynamicSubMenu.ChildItems[1].ChildItems.Add(new MenuItem()); 
                    // Delete cached styles to ensure consistency
                    _cachedLevelsContainingCssClass = null;
                    _cachedMenuItemStyles = null;
                    _cachedSubMenuStyles = null; 
                    _cachedMenuItemClassNames = null;
                    _cachedMenuItemHyperLinkClassNames = null; 
                    _cachedSubMenuClassNames = null; 
                }
                else { 
                    dynamicSubMenu = dynamicSubMenu.Parent;
                }
                // Create the html for the dynamic part
                using (StringWriter dynamicHtmlBuilder = new StringWriter(CultureInfo.CurrentCulture)) { 
                    using (HtmlTextWriter htmlWriter = GetDesignTimeWriter(dynamicHtmlBuilder)) {
                        // Render the control's position on the outer table 
                        Attributes.AddAttributes(htmlWriter); 
                        // Rendering a table around the div so that the designer sees it as a block
                        htmlWriter.RenderBeginTag(HtmlTextWriterTag.Table); 
                        htmlWriter.RenderBeginTag(HtmlTextWriterTag.Tr);
                        htmlWriter.RenderBeginTag(HtmlTextWriterTag.Td);

                        dynamicSubMenu.Render(htmlWriter, true, false, false); 

                        htmlWriter.RenderEndTag(); 
                        htmlWriter.RenderEndTag(); 
                        htmlWriter.RenderEndTag();
                        dictionary[_getDesignTimeDynamicHtml] = dynamicHtmlBuilder.ToString(); 
                    }
                }
            }
            finally { 
                if (StaticDisplayLevels != oldStaticDisplayLevels) {
                    StaticDisplayLevels = oldStaticDisplayLevels; 
                } 
            }
 
            return dictionary;
        }

        private HtmlTextWriter GetDesignTimeWriter(StringWriter stringWriter) { 
            if (_designTimeTextWriterType == null) {
                return new HtmlTextWriter(stringWriter); 
            } 
            else {
                Debug.Assert(_designTimeTextWriterType.IsSubclassOf(typeof(HtmlTextWriter))); 
                ConstructorInfo constructor = _designTimeTextWriterType.GetConstructor(new Type[] { typeof(TextWriter) });
                if (constructor == null) {
                    return new HtmlTextWriter(stringWriter);
                } 
                return (HtmlTextWriter)(constructor.Invoke(new object[] { stringWriter }));
            } 
        } 

 
        /// 
        ///     Gets the URL for the specified image, properly pathing the image filename depending on which image it is
        /// 
        internal string GetImageUrl(int index) { 
            if (ImageUrls[index] == null) {
                switch (index) { 
                    case ScrollUpImageIndex: 
                        ImageUrls[index] = ScrollUpImageUrlInternal;
                        break; 
                    case ScrollDownImageIndex:
                        ImageUrls[index] = ScrollDownImageUrlInternal;
                        break;
                    case PopOutImageIndex: 
                        ImageUrls[index] = PopoutImageUrlInternal;
                        break; 
                } 

                ImageUrls[index] = ResolveClientUrl(ImageUrls[index]); 
            }

            return ImageUrls[index];
        } 

        internal MenuItemStyle GetMenuItemStyle(MenuItem item) { 
            if (item == null) { 
                throw new ArgumentNullException("item");
            } 

            int depth = item.Depth;
            MenuItemStyle typedStyle = CacheGetItem(CachedMenuItemStyles, depth);
 
            if (!item.Selected && typedStyle != null) return typedStyle;
 
            if (typedStyle == null) { 
                typedStyle = new MenuItemStyle();
                typedStyle.CopyFrom(RootMenuItemStyle); 
                if (depth < StaticDisplayLevels) {
                    if (_staticItemStyle != null) {
                        TreeView.GetMergedStyle(typedStyle, _staticItemStyle);
                    } 
                }
                else if (depth >= StaticDisplayLevels && _dynamicItemStyle != null) { 
                    TreeView.GetMergedStyle(typedStyle, _dynamicItemStyle); 
                }
                if ((depth < LevelMenuItemStyles.Count) && (LevelMenuItemStyles[depth] != null)) { 
                    TreeView.GetMergedStyle(typedStyle, LevelMenuItemStyles[depth]);
                }
                CacheSetItem(CachedMenuItemStyles, depth, typedStyle);
            } 

            if (item.Selected) { 
                MenuItemStyle selectedStyle = new MenuItemStyle(); 
                selectedStyle.CopyFrom(typedStyle);
                if (depth < StaticDisplayLevels) { 
                    if (_staticSelectedStyle != null) {
                        TreeView.GetMergedStyle(selectedStyle, _staticSelectedStyle);
                    }
                } 
                else if (depth >= StaticDisplayLevels && _dynamicSelectedStyle != null) {
                    TreeView.GetMergedStyle(selectedStyle, _dynamicSelectedStyle); 
                } 
                if (depth < LevelSelectedStyles.Count && LevelSelectedStyles[depth] != null) {
                    TreeView.GetMergedStyle(selectedStyle, LevelSelectedStyles[depth]); 
                }
                return selectedStyle;
            }
            return typedStyle; 
        }
 
        internal string GetSubMenuCssClassName(MenuItem item) { 
            if (item == null) {
                throw new ArgumentNullException("item"); 
            }

            int nextDepth = item.Depth + 1;
            string baseClassName = CacheGetItem(CachedSubMenuClassNames, nextDepth); 
            if (baseClassName != null) return baseClassName;
 
            StringBuilder builder = new StringBuilder(); 
            if (nextDepth < StaticDisplayLevels) {
                AppendMenuCssClassName(builder, _staticMenuStyle); 
            }
            else {
                SubMenuStyle subMenuStyle = _panelStyle as SubMenuStyle;
                if (subMenuStyle != null) { 
                    AppendMenuCssClassName(builder, subMenuStyle);
                } 
                AppendMenuCssClassName(builder, _dynamicMenuStyle); 
            }
            if ((nextDepth < LevelSubMenuStyles.Count) && (LevelSubMenuStyles[nextDepth] != null)) { 
                SubMenuStyle style = LevelSubMenuStyles[nextDepth] as SubMenuStyle;
                AppendMenuCssClassName(builder, style);
            }
 
            baseClassName = builder.ToString().Trim();
            CacheSetItem(CachedSubMenuClassNames, nextDepth, baseClassName); 
            return baseClassName; 
        }
 
        internal SubMenuStyle GetSubMenuStyle(MenuItem item) {
            if (item == null) {
                throw new ArgumentNullException("item");
            } 

            int nextDepth = item.Depth + 1; 
            SubMenuStyle subMenuStyle = CacheGetItem(CachedSubMenuStyles, nextDepth); 

            if (subMenuStyle != null) return subMenuStyle; 

            int staticDisplayLevels = StaticDisplayLevels;
            if (nextDepth >= staticDisplayLevels && !DesignMode) {
                subMenuStyle = new PopOutPanel.PopOutPanelStyle(Panel); 
            }
            else { 
                subMenuStyle = new SubMenuStyle(); 
            }
            if (nextDepth < staticDisplayLevels) { 
                if (_staticMenuStyle != null) {
                    subMenuStyle.CopyFrom(_staticMenuStyle);
                }
            } 
            else if (nextDepth >= staticDisplayLevels && _dynamicMenuStyle != null) {
                subMenuStyle.CopyFrom(_dynamicMenuStyle); 
            } 
            if (_levelStyles != null &&
                _levelStyles.Count > nextDepth && 
                _levelStyles[nextDepth] != null) {
                TreeView.GetMergedStyle(subMenuStyle, _levelStyles[nextDepth]);
            }
 
            CacheSetItem(CachedSubMenuStyles, nextDepth, subMenuStyle);
            return subMenuStyle; 
        } 

        internal void EnsureRootMenuStyle() { 
            if (_rootMenuItemStyle == null) {
                _rootMenuItemStyle = new Style();
                _rootMenuItemStyle.Font.CopyFrom(Font);
                if (!ForeColor.IsEmpty) { 
                    _rootMenuItemStyle.ForeColor = ForeColor;
                } 
                // Not defaulting to black anymore for not entirely satisfying but reasonable reasons (VSWhidbey 356729) 
                if (!ControlStyle.IsSet(System.Web.UI.WebControls.Style.PROP_FONT_UNDERLINE)) {
                    _rootMenuItemStyle.Font.Underline = false; 
                }
            }
        }
 
        protected internal override void LoadControlState(object savedState) {
            Pair state = savedState as Pair; 
            if (state == null) { 
                base.LoadControlState(savedState);
                return; 
            }
            base.LoadControlState(state.First);

            _selectedItem = null; 
            if (state.Second != null) {
                string path = state.Second as string; 
                if (path != null) { 
                    _selectedItem = Items.FindItem(path.Split(TreeView.InternalPathSeparator), 0);
                } 
            }
        }

        protected override void LoadViewState(object state) { 
            if (state != null) {
                object[] savedState = (object[])state; 
 
                if (savedState[1] != null) {
                    ((IStateManager)StaticMenuItemStyle).LoadViewState(savedState[1]); 
                }

                if (savedState[2] != null) {
                    ((IStateManager)StaticSelectedStyle).LoadViewState(savedState[2]); 
                }
 
                if (savedState[3] != null) { 
                    ((IStateManager)StaticHoverStyle).LoadViewState(savedState[3]);
                } 

                if (savedState[4] != null) {
                    ((IStateManager)StaticMenuStyle).LoadViewState(savedState[4]);
                } 

                if (savedState[5] != null) { 
                    ((IStateManager)DynamicMenuItemStyle).LoadViewState(savedState[5]); 
                }
 
                if (savedState[6] != null) {
                    ((IStateManager)DynamicSelectedStyle).LoadViewState(savedState[6]);
                }
 
                if (savedState[7] != null) {
                    ((IStateManager)DynamicHoverStyle).LoadViewState(savedState[7]); 
                } 

                if (savedState[8] != null) { 
                    ((IStateManager)DynamicMenuStyle).LoadViewState(savedState[8]);
                }

                if (savedState[9] != null) { 
                    ((IStateManager)LevelMenuItemStyles).LoadViewState(savedState[9]);
                } 
 
                if (savedState[10] != null) {
                    ((IStateManager)LevelSelectedStyles).LoadViewState(savedState[10]); 
                }

                if (savedState[11] != null) {
                    ((IStateManager)LevelSubMenuStyles).LoadViewState(savedState[11]); 
                }
 
                if (savedState[12] != null) { 
                    ((IStateManager)Items).LoadViewState(savedState[12]);
                    if (!String.IsNullOrEmpty(DataSourceID) || DataSource != null) { 
                        _dataBound = true;
                    }
                }
 
                // Restore the core viewstate last because some property changes here could
                // necessitate item rebinding (for example, MaximumDynamicDisplayLevels) 
                if (savedState[0] != null) { 
                    base.LoadViewState(savedState[0]);
                } 
            }
        }

        protected override bool OnBubbleEvent(object source, EventArgs e) { 
            MenuEventArgs me = e as MenuEventArgs;
            if (me != null && StringUtil.EqualsIgnoreCase(me.CommandName, MenuItemClickCommandName)) { 
 
                // Do not take any postback into account if the menu is disabled.
                if (!IsEnabled) return true; 

                OnMenuItemClick(me);
                if (AdapterInternal != null) {
                    MenuAdapter menuAdapter = AdapterInternal as MenuAdapter; 
                    if (menuAdapter != null) {
                        MenuItem mi = me.Item; 
                        // Need to tell the adapter about bubbled click events 
                        // for the templated case if the item has children
                        if (mi != null && 
                            mi.ChildItems.Count > 0 &&
                            mi.Depth + 1 >= StaticDisplayLevels) {

                            menuAdapter.SetPath(me.Item.InternalValuePath); 
                        }
                    } 
                } 
                RaiseBubbleEvent(this, e);
                return true; 
            }
            if (e is CommandEventArgs) {
                RaiseBubbleEvent(this, e);
                return true; 
            }
            return false; 
        } 

        protected override void OnDataBinding(EventArgs e) { 
            EnsureChildControls();
            base.OnDataBinding(e);
        }
 
        protected internal override void OnInit(EventArgs e) {
            base.OnInit(e); 
            Page.RegisterRequiresControlState(this); 
        }
 

        protected virtual void OnMenuItemClick(MenuEventArgs e) {
            SetSelectedItem(e.Item);
            MenuEventHandler handler = (MenuEventHandler)Events[_menuItemClickedEvent]; 
            if (handler != null) {
                handler(this, e); 
            } 
        }
 

        /// 
        ///     Raises the MenuItemDataBound event
        ///  
        protected virtual void OnMenuItemDataBound(MenuEventArgs e) {
            MenuEventHandler handler = (MenuEventHandler)Events[_menuItemDataBoundEvent]; 
            if (handler != null) { 
                handler(this, e);
            } 
        }

        /// 
        ///     Overridden to register for postback, and if client script is enabled, renders out 
        ///     the necessary script and hidden field to function.
        ///  
        protected internal override void OnPreRender(EventArgs e) { 
            base.OnPreRender(e);
 
            if (Items.Count > 0) {
                Renderer.PreRender(IsEnabled);
            }
        } 

        ///  
        ///     Overridden to register for postback, and if client script is enabled, renders out 
        ///     the necessary script and hidden field to function.
        ///  
        internal void OnPreRender(EventArgs e, bool registerScript) {
            base.OnPreRender(e);

            if (Items.Count > 0) { 
                Renderer.PreRender(registerScript);
            } 
        } 

        ///  
        ///     Overridden to create all the items based on the datasource provided
        /// 
        protected internal override void PerformDataBinding() {
            base.PerformDataBinding(); 

            DataBindItem(RootItem); 
 
            if (!DesignMode && _dataBound &&
                String.IsNullOrEmpty(DataSourceID) && DataSource == null) { 

                Items.Clear();
                Controls.Clear();
                ClearChildViewState(); 
                TrackViewState();
                ChildControlsCreated = true; 
                return; 
            }
 
            if (!String.IsNullOrEmpty(DataSourceID) ||
                DataSource != null) {

                Controls.Clear(); 
                ClearChildState();
                TrackViewState(); 
 
                CreateChildControlsFromItems(true);
                ChildControlsCreated = true; 
                _dataBound = true;
            }
            else if (!_subControlsDataBound) {
                foreach (Control ctrl in Controls) { 
                    ctrl.DataBind();
                } 
            } 
            _subControlsDataBound = true;
        } 

        protected internal override void Render(HtmlTextWriter writer) {
            VerifyRenderingInServerForm();
 
            if (Items.Count > 0) {
                Renderer.RenderBeginTag(writer, false); 
                Renderer.RenderContents(writer, false); 
                Renderer.RenderEndTag(writer, false);
            } 
        }

        public override void RenderBeginTag(HtmlTextWriter writer) {
            Renderer.RenderBeginTag(writer, false); 
        }
 
        protected internal override void RenderContents(HtmlTextWriter writer) { 
            Renderer.RenderContents(writer, false);
        } 

        public override void RenderEndTag(HtmlTextWriter writer) {
            Renderer.RenderEndTag(writer, false);
        } 

        internal void ResetCachedStyles() { 
            // Reset all these cached values so things can pick up changes in the designer 
            if (_dynamicItemStyle != null) {
                _dynamicItemStyle.ResetCachedStyles(); 
            }
            if (_staticItemStyle != null) {
                _staticItemStyle.ResetCachedStyles();
            } 
            if (_dynamicSelectedStyle != null) {
                _dynamicSelectedStyle.ResetCachedStyles(); 
            } 
            if (_staticSelectedStyle != null) {
                _staticSelectedStyle.ResetCachedStyles(); 
            }
            if (_staticHoverStyle != null) {
                _staticHoverHyperLinkStyle = new HyperLinkStyle(_staticHoverStyle);
            } 
            if (_dynamicHoverStyle != null) {
                _dynamicHoverHyperLinkStyle = new HyperLinkStyle(_dynamicHoverStyle); 
            } 

            foreach (MenuItemStyle style in LevelMenuItemStyles) { 
                style.ResetCachedStyles();
            }

            foreach (MenuItemStyle style in LevelSelectedStyles) { 
                style.ResetCachedStyles();
            } 
 
            if (_imageUrls != null) {
                for (int i = 0; i < _imageUrls.Length; i++) { 
                    _imageUrls[i] = null;
                }
            }
 
            _cachedPopOutImageUrl = null;
            _cachedScrollDownImageUrl = null; 
            _cachedScrollUpImageUrl = null; 
            _cachedLevelsContainingCssClass = null;
            _cachedMenuItemClassNames = null; 
            _cachedMenuItemHyperLinkClassNames = null;
            _cachedMenuItemStyles = null;
            _cachedSubMenuClassNames = null;
            _cachedSubMenuStyles = null; 
        }
 
        protected internal override object SaveControlState() { 
            object baseState = base.SaveControlState();
            if (_selectedItem != null) { 
                return new Pair(baseState, _selectedItem.InternalValuePath);
            }
            else {
                return baseState; 
            }
        } 
 
        protected override object SaveViewState() {
            object[] state = new object[13]; 

            state[0] = base.SaveViewState();

            bool hasViewState = (state[0] != null); 

            if (_staticItemStyle != null) { 
                state[1] = ((IStateManager)_staticItemStyle).SaveViewState(); 
                hasViewState |= (state[1] != null);
            } 

            if (_staticSelectedStyle != null) {
                state[2] = ((IStateManager)_staticSelectedStyle).SaveViewState();
                hasViewState |= (state[2] != null); 
            }
 
            if (_staticHoverStyle != null) { 
                state[3] = ((IStateManager)_staticHoverStyle).SaveViewState();
                hasViewState |= (state[3] != null); 
            }

            if (_staticMenuStyle != null) {
                state[4] = ((IStateManager)_staticMenuStyle).SaveViewState(); 
                hasViewState |= (state[4] != null);
            } 
 
            if (_dynamicItemStyle != null) {
                state[5] = ((IStateManager)_dynamicItemStyle).SaveViewState(); 
                hasViewState |= (state[5] != null);
            }

            if (_dynamicSelectedStyle != null) { 
                state[6] = ((IStateManager)_dynamicSelectedStyle).SaveViewState();
                hasViewState |= (state[6] != null); 
            } 

            if (_dynamicHoverStyle != null) { 
                state[7] = ((IStateManager)_dynamicHoverStyle).SaveViewState();
                hasViewState |= (state[7] != null);
            }
 
            if (_dynamicMenuStyle != null) {
                state[8] = ((IStateManager)_dynamicMenuStyle).SaveViewState(); 
                hasViewState |= (state[8] != null); 
            }
 
            if (_levelMenuItemStyles != null) {
                state[9] = ((IStateManager)_levelMenuItemStyles).SaveViewState();
                hasViewState |= (state[9] != null);
            } 

            if (_levelSelectedStyles != null) { 
                state[10] = ((IStateManager)_levelSelectedStyles).SaveViewState(); 
                hasViewState |= (state[10] != null);
            } 

            if (_levelStyles != null) {
                state[11] = ((IStateManager)_levelStyles).SaveViewState();
                hasViewState |= (state[11] != null); 
            }
 
            state[12] = ((IStateManager)Items).SaveViewState(); 
            hasViewState |= (state[12] != null);
 
            if (hasViewState) {
                return state;
            }
            else { 
                return null;
            } 
        } 

        [SecurityPermission(SecurityAction.Demand, Unrestricted = true)] 
        protected override void SetDesignModeState(IDictionary data) {
            if (data.Contains("DesignTimeTextWriterType")) {
                Type writerType = data["DesignTimeTextWriterType"] as Type;
                if (writerType != null && writerType.IsSubclassOf(typeof(HtmlTextWriter))) { 
                    _designTimeTextWriterType = writerType;
                } 
            } 
            base.SetDesignModeState(data);
        } 


        /// 
        /// Allows a derived Menu to set the DataBound proprety on a node 
        /// 
        protected void SetItemDataBound(MenuItem node, bool dataBound) { 
            node.SetDataBound(dataBound); 
        }
 

        /// 
        /// Allows a derived Menu to set the DataItem on a node
        ///  
        protected void SetItemDataItem(MenuItem node, object dataItem) {
            node.SetDataItem(dataItem); 
        } 

 
        /// 
        /// Allows a derived Menu to set the DataPath on a node
        /// 
        protected void SetItemDataPath(MenuItem node, string dataPath) { 
            node.SetDataPath(dataPath);
        } 
 
        internal void SetSelectedItem(MenuItem node) {
            Debug.Assert(node == null || node.Owner == this); 

            if (_selectedItem != node) {
                if (node != null) {
                    if (node.Depth >= MaximumDepth) { 
                        throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidDepth));
                    } 
                    if (!(node.IsEnabledNoOwner && node.Selectable)) { 
                        throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidSelection));
                    } 
                }

                // Unselect the previously selected item
                if ((_selectedItem != null) && (_selectedItem.Selected)) { 
                    _selectedItem.SetSelected(false);
                } 
                _selectedItem = node; 
                // Notify the new selected item that it's now selected
                if ((_selectedItem != null) && !_selectedItem.Selected) { 
                    _selectedItem.SetSelected(true);
                }
            }
        } 

 
        ///  
        /// 
        ///    Marks the starting point to begin tracking and saving changes to the 
        ///    control as part of the control viewstate.
        /// 
        protected override void TrackViewState() {
            base.TrackViewState(); 

            if (_staticItemStyle != null) { 
                ((IStateManager)_staticItemStyle).TrackViewState(); 
            }
            if (_staticSelectedStyle != null) { 
                ((IStateManager)_staticSelectedStyle).TrackViewState();
            }
            if (_staticHoverStyle != null) {
                ((IStateManager)_staticHoverStyle).TrackViewState(); 
            }
            if (_staticMenuStyle != null) { 
                ((IStateManager)_staticMenuStyle).TrackViewState(); 
            }
            if (_dynamicItemStyle != null) { 
                ((IStateManager)_dynamicItemStyle).TrackViewState();
            }
            if (_dynamicSelectedStyle != null) {
                ((IStateManager)_dynamicSelectedStyle).TrackViewState(); 
            }
            if (_dynamicHoverStyle != null) { 
                ((IStateManager)_dynamicHoverStyle).TrackViewState(); 
            }
            if (_dynamicMenuStyle != null) { 
                ((IStateManager)_dynamicMenuStyle).TrackViewState();
            }
            if (_levelMenuItemStyles != null) {
                ((IStateManager)_levelMenuItemStyles).TrackViewState(); 
            }
            if (_levelSelectedStyles != null) { 
                ((IStateManager)_levelSelectedStyles).TrackViewState(); 
            }
            if (_levelStyles != null) { 
                ((IStateManager)_levelStyles).TrackViewState();
            }
            if (_bindings != null) {
                ((IStateManager)_bindings).TrackViewState(); 
            }
 
            ((IStateManager)Items).TrackViewState(); 
        }
 
        internal void VerifyRenderingInServerForm() {
            if (Page != null) {
                Page.VerifyRenderingInServerForm(this);
            } 
        }
 
        #region IPostBackEventHandler implementation 

        ///  
        void IPostBackEventHandler.RaisePostBackEvent(string eventArgument) {
            RaisePostBackEvent(eventArgument);
        }
 
        protected internal virtual void RaisePostBackEvent(string eventArgument) {
            ValidateEvent(UniqueID, eventArgument); 
 
            // Do not take any postback into account if the menu is disabled.
            if (!IsEnabled) return; 

            EnsureChildControls();
            if (AdapterInternal != null) {
                IPostBackEventHandler pbeh = AdapterInternal as IPostBackEventHandler; 
                if (pbeh != null) {
                    pbeh.RaisePostBackEvent(eventArgument); 
                } 
            }
            else { 
                InternalRaisePostBackEvent(eventArgument);
            }
        }
 
        internal void InternalRaisePostBackEvent(string eventArgument) {
            if (eventArgument.Length == 0) { 
                return; 
            }
 
            // Get the path of the node specified in the eventArgument
            string nodePath = HttpUtility.HtmlDecode(eventArgument);
            // Check the number of separator characters in the argument (should not be more than the max depth)
            int matches = 0; 
            for (int i = 0; i < nodePath.Length; i++) {
                if (nodePath[i] == TreeView.InternalPathSeparator) { 
                    if (++matches >= MaximumDepth) { 
                        throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidDepth));
                    } 
                }
            }
            // Find that node in the tree
            MenuItem node = Items.FindItem(nodePath.Split(TreeView.InternalPathSeparator), 0); 

            if (node != null) { 
                OnMenuItemClick(new MenuEventArgs(node)); 
            }
        } 
        #endregion
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

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

    /// 
    ///     Provides a cascading pop-out hierarchical menu control
    ///  
    [ControlValueProperty("SelectedValue")]
    [DefaultEvent("MenuItemClick")] 
    [Designer("System.Web.UI.Design.WebControls.MenuDesigner, " + AssemblyRef.SystemDesign)] 
    [SupportsEventValidation]
    public partial class Menu : HierarchicalDataBoundControl, IPostBackEventHandler, INamingContainer { 

        internal const int ScrollUpImageIndex = 0;
        internal const int ScrollDownImageIndex = 1;
        internal const int PopOutImageIndex = 2; 

        internal const int ImageUrlsCount = 3; 
 
        private const string _getDesignTimeStaticHtml = "GetDesignTimeStaticHtml";
        private const string _getDesignTimeDynamicHtml = "GetDesignTimeDynamicHtml"; 

        // static readonly instead of const to be able to change it in the future without breaking existing client code
        public static readonly string MenuItemClickCommandName = "Click";
 
        private static readonly object _menuItemClickedEvent = new object();
        private static readonly object _menuItemDataBoundEvent = new object(); 
 
        private MenuRenderingMode _renderingMode = MenuRenderingMode.Default;
 
        private string[] _imageUrls;

        private SubMenuStyle _staticMenuStyle;
        private SubMenuStyle _dynamicMenuStyle; 

        private MenuItemStyle _staticItemStyle; 
        private MenuItemStyle _staticSelectedStyle; 
        private Style _staticHoverStyle;
        private HyperLinkStyle _staticHoverHyperLinkStyle; 

        private MenuItemStyle _dynamicItemStyle;
        private MenuItemStyle _dynamicSelectedStyle;
        private Style _dynamicHoverStyle; 
        private HyperLinkStyle _dynamicHoverHyperLinkStyle;
 
        private Style _rootMenuItemStyle; 

        private SubMenuStyleCollection _levelStyles; 
        private MenuItemStyleCollection _levelMenuItemStyles;
        private MenuItemStyleCollection _levelSelectedStyles;

        // Cached styles. In the current implementation, the styles are the same for all items 
        // and submenus at a given depth.
        private List _cachedMenuItemStyles; 
        private List _cachedSubMenuStyles; 
        private List _cachedMenuItemClassNames;
        private List _cachedMenuItemHyperLinkClassNames; 
        private List _cachedSubMenuClassNames;
        private Collection _cachedLevelsContainingCssClass;

        private MenuItem _rootItem; 
        private MenuItem _selectedItem;
 
        private MenuItemBindingCollection _bindings; 

        private string _cachedScrollUpImageUrl; 
        private string _cachedScrollDownImageUrl;
        private string _cachedPopOutImageUrl;

        private ITemplate _dynamicTemplate; 
        private ITemplate _staticTemplate;
 
        private int _maximumDepth; 
        private int _nodeIndex;
 
        private string _currentSiteMapNodeUrl;
        private bool _dataBound;
        private bool _subControlsDataBound;
        private bool _accessKeyRendered; 

        private PopOutPanel _panel; 
        private Style _panelStyle; 

        private bool _isNotIE; 

        private Type _designTimeTextWriterType;

        private MenuRenderer _renderer; 

        ///  
        ///     Creates a new instance of a Menu. 
        /// 
        public Menu() { 
            _nodeIndex = 0;
            _maximumDepth = 0;

            IncludeStyleBlock = true; 
        }
 
        internal bool AccessKeyRendered { 
            get {
                return _accessKeyRendered; 
            }
            set {
                _accessKeyRendered = value;
            } 
        }
 
        private Collection CachedLevelsContainingCssClass { 
            get {
                if (_cachedLevelsContainingCssClass == null) { 
                    _cachedLevelsContainingCssClass = new Collection();
                }
                return _cachedLevelsContainingCssClass;
            } 
        }
 
        private List CachedMenuItemClassNames { 
            get {
                if (_cachedMenuItemClassNames == null) { 
                    _cachedMenuItemClassNames = new List();
                }
                return _cachedMenuItemClassNames;
            } 
        }
 
        private List CachedMenuItemHyperLinkClassNames { 
            get {
                if (_cachedMenuItemHyperLinkClassNames == null) { 
                    _cachedMenuItemHyperLinkClassNames = new List();
                }
                return _cachedMenuItemHyperLinkClassNames;
            } 
        }
 
        private List CachedMenuItemStyles { 
            get {
                if (_cachedMenuItemStyles == null) { 
                    _cachedMenuItemStyles = new List();
                }
                return _cachedMenuItemStyles;
            } 
        }
 
        private List CachedSubMenuClassNames { 
            get {
                if (_cachedSubMenuClassNames == null) { 
                    _cachedSubMenuClassNames = new List();
                }
                return _cachedSubMenuClassNames;
            } 
        }
 
        private List CachedSubMenuStyles { 
            get {
                if (_cachedSubMenuStyles == null) { 
                    _cachedSubMenuStyles = new List();
                }
                return _cachedSubMenuStyles;
            } 
        }
 
 
        /// 
        ///     Gets the hidden field ID for the expand state of this Menu 
        /// 
        internal string ClientDataObjectID {
            get {
                // 
                return ClientID + "_Data";
            } 
        } 

        public override ControlCollection Controls { 
            get {
                EnsureChildControls();
                return base.Controls;
            } 
        }
 
        [ 
        DefaultValue(null),
        Editor("System.Web.UI.Design.WebControls.MenuBindingsEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)), 
        MergableProperty(false),
        PersistenceMode(PersistenceMode.InnerProperty),
        WebCategory("Data"),
        WebSysDescription(SR.Menu_Bindings) 
        ]
        public MenuItemBindingCollection DataBindings { 
            get { 
                if (_bindings == null) {
                    _bindings = new MenuItemBindingCollection(this); 
                    if (IsTrackingViewState) {
                        ((IStateManager)_bindings).TrackViewState();
                    }
                } 
                return _bindings;
            } 
        } 

 
        [WebCategory("Behavior")]
        [DefaultValue(500)]
        [WebSysDescription(SR.Menu_DisappearAfter)]
        [Themeable(false)] 
        public int DisappearAfter {
            get { 
                object o = ViewState["DisappearAfter"]; 
                if (o == null) {
                    return 500; 
                }
                return (int)o;
            }
            set { 
                if (value < -1) {
                    throw new ArgumentOutOfRangeException("value"); 
                } 
                ViewState["DisappearAfter"] = value;
            } 
        }


        [DefaultValue("")] 
        [Editor("System.Web.UI.Design.ImageUrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor))]
        [Themeable(true)] 
        [UrlProperty()] 
        [WebCategory("Appearance")]
        [WebSysDescription(SR.Menu_DynamicBottomSeparatorImageUrl)] 
        public string DynamicBottomSeparatorImageUrl {
            get {
                object s = ViewState["DynamicBottomSeparatorImageUrl"];
                if (s == null) { 
                    return String.Empty;
                } 
                return (string)s; 
            }
            set { 
                ViewState["DynamicBottomSeparatorImageUrl"] = value;
            }
        }
 

        [ 
        DefaultValue(true), 
        WebCategory("Appearance"),
        WebSysDescription(SR.Menu_DynamicDisplayPopOutImage) 
        ]
        public bool DynamicEnableDefaultPopOutImage {
            get {
                object o = ViewState["DynamicEnableDefaultPopOutImage"]; 
                if (o == null) {
                    return true; 
                } 
                return (bool)o;
            } 
            set {
                ViewState["DynamicEnableDefaultPopOutImage"] = value;
            }
        } 

 
        [ 
        DefaultValue(0),
        WebCategory("Appearance"), 
        WebSysDescription(SR.Menu_DynamicHorizontalOffset)
        ]
        public int DynamicHorizontalOffset {
            get { 
                object o = ViewState["DynamicHorizontalOffset"];
                if (o == null) { 
                    return 0; 
                }
                return (int)o; 
            }
            set {
                ViewState["DynamicHorizontalOffset"] = value;
            } 
        }
 
 
        [
        DefaultValue(null), 
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        NotifyParentProperty(true),
        PersistenceMode(PersistenceMode.InnerProperty),
        WebCategory("Styles"), 
        WebSysDescription(SR.Menu_DynamicHoverStyle)
        ] 
        public Style DynamicHoverStyle { 
            get {
                if (_dynamicHoverStyle == null) { 
                    _dynamicHoverStyle = new Style();
                    if (IsTrackingViewState) {
                        ((IStateManager)_dynamicHoverStyle).TrackViewState();
                    } 
                }
                return _dynamicHoverStyle; 
            } 
        }
 
        [DefaultValue("")]
        [WebCategory("Appearance")]
        [WebSysDescription(SR.Menu_DynamicItemFormatString)]
        public string DynamicItemFormatString { 
            get {
                object s = ViewState["DynamicItemFormatString"]; 
                if (s == null) { 
                    return String.Empty;
                } 
                return (string)s;
            }
            set {
                ViewState["DynamicItemFormatString"] = value; 
            }
        } 
 

        [ 
        WebCategory("Styles"),
        DefaultValue(null),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        NotifyParentProperty(true), 
        PersistenceMode(PersistenceMode.InnerProperty),
        WebSysDescription(SR.Menu_DynamicMenuItemStyle) 
        ] 
        public MenuItemStyle DynamicMenuItemStyle {
            get { 
                if (_dynamicItemStyle == null) {
                    _dynamicItemStyle = new MenuItemStyle();
                    if (IsTrackingViewState) {
                        ((IStateManager)_dynamicItemStyle).TrackViewState(); 
                    }
                } 
                return _dynamicItemStyle; 
            }
        } 


        [
        WebCategory("Styles"), 
        DefaultValue(null),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content), 
        NotifyParentProperty(true), 
        PersistenceMode(PersistenceMode.InnerProperty),
        WebSysDescription(SR.Menu_DynamicMenuStyle) 
        ]
        public SubMenuStyle DynamicMenuStyle {
            get {
                if (_dynamicMenuStyle == null) { 
                    _dynamicMenuStyle = new SubMenuStyle();
                    if (IsTrackingViewState) { 
                        ((IStateManager)_dynamicMenuStyle).TrackViewState(); 
                    }
                } 
                return _dynamicMenuStyle;
            }
        }
 

        [DefaultValue("")] 
        [Editor("System.Web.UI.Design.ImageUrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor))] 
        [UrlProperty()]
        [WebCategory("Appearance")] 
        [WebSysDescription(SR.Menu_DynamicPopoutImageUrl)]
        public string DynamicPopOutImageUrl {
            get {
                object s = ViewState["DynamicPopOutImageUrl"]; 
                if (s == null) {
                    return String.Empty; 
                } 
                return (string)s;
            } 
            set {
                ViewState["DynamicPopOutImageUrl"] = value;
            }
        } 

 
        [WebSysDefaultValue(SR.MenuAdapter_Expand)] 
        [WebCategory("Appearance")]
        [WebSysDescription(SR.Menu_DynamicPopoutImageText)] 
        public string DynamicPopOutImageTextFormatString {
            get {
                object s = ViewState["DynamicPopOutImageTextFormatString"];
                if (s == null) { 
                    return SR.GetString(SR.MenuAdapter_Expand);
                } 
                return (string)s; 
            }
            set { 
                ViewState["DynamicPopOutImageTextFormatString"] = value;
            }
        }
 

        [ 
        WebCategory("Styles"), 
        DefaultValue(null),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content), 
        NotifyParentProperty(true),
        PersistenceMode(PersistenceMode.InnerProperty),
        WebSysDescription(SR.Menu_DynamicSelectedStyle)
        ] 
        public MenuItemStyle DynamicSelectedStyle {
            get { 
                if (_dynamicSelectedStyle == null) { 
                    _dynamicSelectedStyle = new MenuItemStyle();
                    if (IsTrackingViewState) { 
                        ((IStateManager)_dynamicSelectedStyle).TrackViewState();
                    }
                }
                return _dynamicSelectedStyle; 
            }
        } 
 
        [
        Browsable(false), 
        DefaultValue(null),
        PersistenceMode(PersistenceMode.InnerProperty),
        TemplateContainer(typeof(MenuItemTemplateContainer)),
        WebSysDescription(SR.Menu_DynamicTemplate) 
        ]
        public ITemplate DynamicItemTemplate { 
            get { 
                return _dynamicTemplate;
            } 
            set {
                _dynamicTemplate = value;
            }
        } 

 
        [DefaultValue("")] 
        [Editor("System.Web.UI.Design.ImageUrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor))]
        [UrlProperty()] 
        [WebCategory("Appearance")]
        [WebSysDescription(SR.Menu_DynamicTopSeparatorImageUrl)]
        public string DynamicTopSeparatorImageUrl {
            get { 
                object s = ViewState["DynamicTopSeparatorImageUrl"];
                if (s == null) { 
                    return string.Empty; 
                }
                return (string)s; 
            }
            set {
                ViewState["DynamicTopSeparatorImageUrl"] = value;
            } 
        }
 
 
        [
        DefaultValue(0), 
        WebCategory("Appearance"),
        WebSysDescription(SR.Menu_DynamicVerticalOffset)
        ]
        public int DynamicVerticalOffset { 
            get {
                object o = ViewState["DynamicVerticalOffset"]; 
                if (o == null) { 
                    return 0;
                } 
                return (int)o;
            }
            set {
                ViewState["DynamicVerticalOffset"] = value; 
            }
        } 
 
        /// 
        ///     A cache of urls for the built-in images. 
        /// 
        private string[] ImageUrls {
            get {
                if (_imageUrls == null) { 
                    _imageUrls = new string[ImageUrlsCount];
                } 
                return _imageUrls; 
            }
        } 

        [DefaultValue(true)]
        [WebCategory("Appearance")]
        // 
        [Description("Determines whether or not to render the inline style block (only used in standards compliance mode)")]
        public bool IncludeStyleBlock { get; set; } 
 
        internal bool IsNotIE {
            get { 
                return _isNotIE;
            }
        }
 

        ///  
        ///     Gets the collection of top-level nodes. 
        /// 
        [ 
        DefaultValue(null),
        Editor("System.Web.UI.Design.WebControls.MenuItemCollectionEditor," + AssemblyRef.SystemDesign, typeof(UITypeEditor)),
        PersistenceMode(PersistenceMode.InnerProperty),
        MergableProperty(false), 
        WebSysDescription(SR.Menu_Items)
        ] 
        public MenuItemCollection Items { 
            get {
                return RootItem.ChildItems; 
            }
        }

 
        /// 
        ///     Gets and sets whether the text of the items should be wrapped 
        ///  
        [DefaultValue(false)]
        [WebCategory("Appearance")] 
        [WebSysDescription(SR.Menu_ItemWrap)]
        public bool ItemWrap {
            get {
                object o = ViewState["ItemWrap"]; 
                if (o == null) {
                    return false; 
                } 
                return (bool)o;
            } 
            set {
                ViewState["ItemWrap"] = value;
            }
        } 

 
        ///  
        ///     Gets the collection of MenuItemStyles corresponding to each level
        ///  
        [
        DefaultValue(null),
        Editor("System.Web.UI.Design.WebControls.MenuItemStyleCollectionEditor," + AssemblyRef.SystemDesign, typeof(UITypeEditor)),
        PersistenceMode(PersistenceMode.InnerProperty), 
        WebCategory("Styles"),
        WebSysDescription(SR.Menu_LevelMenuItemStyles), 
        ] 
        public MenuItemStyleCollection LevelMenuItemStyles {
            get { 
                if (_levelMenuItemStyles == null) {
                    _levelMenuItemStyles = new MenuItemStyleCollection();
                    if (IsTrackingViewState) {
                        ((IStateManager)_levelMenuItemStyles).TrackViewState(); 
                    }
                } 
 
                return _levelMenuItemStyles;
            } 
        }


        ///  
        ///     Gets the collection of MenuItemStyles corresponding to the selected item on each level
        ///  
        [ 
        DefaultValue(null),
        Editor("System.Web.UI.Design.WebControls.MenuItemStyleCollectionEditor," + AssemblyRef.SystemDesign, typeof(UITypeEditor)), 
        PersistenceMode(PersistenceMode.InnerProperty),
        WebCategory("Styles"),
        WebSysDescription(SR.Menu_LevelSelectedStyles),
        ] 
        public MenuItemStyleCollection LevelSelectedStyles {
            get { 
                if (_levelSelectedStyles == null) { 
                    _levelSelectedStyles = new MenuItemStyleCollection();
                    if (IsTrackingViewState) { 
                        ((IStateManager)_levelSelectedStyles).TrackViewState();
                    }
                }
 
                return _levelSelectedStyles;
            } 
        } 

 
        [
        DefaultValue(null),
        Editor("System.Web.UI.Design.WebControls.SubMenuStyleCollectionEditor," + AssemblyRef.SystemDesign, typeof(UITypeEditor)),
        PersistenceMode(PersistenceMode.InnerProperty), 
        WebCategory("Styles"),
        WebSysDescription(SR.Menu_LevelSubMenuStyles), 
        ] 
        public SubMenuStyleCollection LevelSubMenuStyles {
            get { 
                if (_levelStyles == null) {
                    _levelStyles = new SubMenuStyleCollection();
                    if (IsTrackingViewState) {
                        ((IStateManager)_levelStyles).TrackViewState(); 
                    }
                } 
 
                return _levelStyles;
            } 
        }

        internal int MaximumDepth {
            get { 
                if (_maximumDepth > 0) {
                    return _maximumDepth; 
                } 
                _maximumDepth = MaximumDynamicDisplayLevels + StaticDisplayLevels;
                if (_maximumDepth < MaximumDynamicDisplayLevels || _maximumDepth < StaticDisplayLevels) { 
                    _maximumDepth = int.MaxValue;
                }
                return _maximumDepth;
            } 
        }
 
 
        [WebCategory("Behavior")]
        [DefaultValue(3)] 
        [Themeable(true)]
        [WebSysDescription(SR.Menu_MaximumDynamicDisplayLevels)]
        public int MaximumDynamicDisplayLevels {
            get { 
                object o = ViewState["MaximumDynamicDisplayLevels"];
                if (o == null) { 
                    return 3; 
                }
                return (int)o; 
            }
            set {
                if (value < 0) {
                    throw new ArgumentOutOfRangeException("MaximumDynamicDisplayLevels", SR.GetString(SR.Menu_MaximumDynamicDisplayLevelsInvalid)); 
                }
                // Note: we're not testing against the old value here because 
                // the setter is not the only thing that can change the underlying 
                // ViewState entry: LoadViewState modifies it directly.
                ViewState["MaximumDynamicDisplayLevels"] = value; 
                // Reset max depth cache
                _maximumDepth = 0;
                // Rebind if necessary
                if (_dataBound) { 
                    _dataBound = false;
                    PerformDataBinding(); 
                } 
            }
        } 


        [WebCategory("Layout")]
        [DefaultValue(Orientation.Vertical)] 
        [WebSysDescription(SR.Menu_Orientation)]
        public Orientation Orientation { 
            get { 
                object o = ViewState["Orientation"];
                if (o == null) { 
                    return Orientation.Vertical;
                }
                return (Orientation)o;
            } 
            set {
                ViewState["Orientation"] = value; 
            } 
        }
 
        internal PopOutPanel Panel {
            get {
                if (_panel == null) {
                    _panel = new PopOutPanel(this, _panelStyle); 
                    if (!DesignMode) {
                        _panel.Page = Page; 
                    } 
                }
                return _panel; 
            }
        }

        [DefaultValue('/')] 
        [WebSysDescription(SR.Menu_PathSeparator)]
        public char PathSeparator { 
            get { 
                object o = ViewState["PathSeparator"];
                if (o == null) { 
                    return '/';
                }
                return (char)o;
            } 
            set {
                if (value == '\0') { 
                    ViewState["PathSeparator"] = null; 
                }
                else { 
                    ViewState["PathSeparator"] = value;
                }
                foreach (MenuItem item in Items) {
                    item.ResetValuePathRecursive(); 
                }
            } 
        } 

        internal string PopoutImageUrlInternal { 
            get {
                if (_cachedPopOutImageUrl != null) {
                    return _cachedPopOutImageUrl;
                } 
                _cachedPopOutImageUrl = Page.ClientScript.GetWebResourceUrl(typeof(Menu), ("Menu_Popout.gif"));
                return _cachedPopOutImageUrl; 
            } 
        }
 
        private MenuRenderer Renderer {
            get {
                if (_renderer == null) {
                    switch (RenderingMode) { 
                        case MenuRenderingMode.Table:
                            _renderer = new MenuRendererClassic(this); 
                            break; 
                        case MenuRenderingMode.List:
                            _renderer = new MenuRendererStandards(this); 
                            break;
                        case MenuRenderingMode.Default:
                            if (RenderingCompatibility < VersionUtil.Framework40) {
                                _renderer = new MenuRendererClassic(this); 
                            }
                            else { 
                                _renderer = new MenuRendererStandards(this); 
                            }
                            break; 
                        default:
                            Debug.Fail("Unknown MenuRenderingMode.");
                            break;
                    } 
                }
                return _renderer; 
            } 
        }
 
        [
        WebCategory("Layout"),
        DefaultValue(MenuRenderingMode.Default),
        WebSysDescription(SR.Menu_RenderingMode) 
        ]
        public MenuRenderingMode RenderingMode { 
            get { 
                return _renderingMode;
            } 
            set {
                if (value < MenuRenderingMode.Default || value > MenuRenderingMode.List) {
                    throw new ArgumentOutOfRangeException("value");
                } 
                if (_renderer != null) {
                    throw new InvalidOperationException(SR.GetString(SR.Menu_CannotChangeRenderingMode)); 
                } 
                _renderingMode = value;
            } 
        }

        /// 
        ///     The 'virtual' root node of the menu. This menu item is never shown. 
        ///     It is the parent of the "real" root items.
        ///  
        internal MenuItem RootItem { 
            get {
                if (_rootItem == null) { 
                    _rootItem = new MenuItem(this, true);
                }
                return _rootItem;
            } 
        }
 
        // RootMenuItemStyle is roughly equivalent to ControlStyle.HyperLinkStyle if it existed. 
        internal Style RootMenuItemStyle {
            get { 
                EnsureRootMenuStyle();
                return _rootMenuItemStyle;
            }
        } 

        [DefaultValue("")] 
        [Editor("System.Web.UI.Design.ImageUrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor))] 
        [UrlProperty()]
        [WebCategory("Appearance")] 
        [WebSysDescription(SR.Menu_ScrollDownImageUrl)]
        public string ScrollDownImageUrl {
            get {
                object s = ViewState["ScrollDownImageUrl"]; 
                if (s == null) {
                    return String.Empty; 
                } 
                return (string)s;
            } 
            set {
                ViewState["ScrollDownImageUrl"] = value;
            }
        } 

        internal string ScrollDownImageUrlInternal { 
            get { 
                if (_cachedScrollDownImageUrl != null) {
                    return _cachedScrollDownImageUrl; 
                }
                _cachedScrollDownImageUrl = Page.ClientScript.GetWebResourceUrl(typeof(Menu), ("Menu_ScrollDown.gif"));
                return _cachedScrollDownImageUrl;
            } 
        }
 
 
        [WebSysDefaultValue(SR.Menu_ScrollDown)]
        [Localizable(true)] 
        [WebCategory("Appearance")]
        [WebSysDescription(SR.Menu_ScrollDownText)]
        public string ScrollDownText {
            get { 
                object s = ViewState["ScrollDownText"];
                if (s == null) { 
                    return SR.GetString(SR.Menu_ScrollDown); 
                }
                return (string)s; 
            }
            set {
                ViewState["ScrollDownText"] = value;
            } 
        }
 
 
        [DefaultValue("")]
        [Editor("System.Web.UI.Design.ImageUrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor))] 
        [UrlProperty()]
        [WebCategory("Appearance")]
        [WebSysDescription(SR.Menu_ScrollUpImageUrl)]
        public string ScrollUpImageUrl { 
            get {
                object s = ViewState["ScrollUpImageUrl"]; 
                if (s == null) { 
                    return String.Empty;
                } 
                return (string)s;
            }
            set {
                ViewState["ScrollUpImageUrl"] = value; 
            }
        } 
 
        internal string ScrollUpImageUrlInternal {
            get { 
                if (_cachedScrollUpImageUrl != null) {
                    return _cachedScrollUpImageUrl;
                }
                _cachedScrollUpImageUrl = Page.ClientScript.GetWebResourceUrl(typeof(Menu), ("Menu_ScrollUp.gif")); 
                return _cachedScrollUpImageUrl;
            } 
        } 

 
        [WebSysDefaultValue(SR.Menu_ScrollUp)]
        [Localizable(true)]
        [WebCategory("Appearance")]
        [WebSysDescription(SR.Menu_ScrollUpText)] 
        public string ScrollUpText {
            get { 
                object s = ViewState["ScrollUpText"]; 
                if (s == null) {
                    return SR.GetString(SR.Menu_ScrollUp); 
                }
                return (string)s;
            }
            set { 
                ViewState["ScrollUpText"] = value;
            } 
        } 

 
        /// 
        ///     Gets and sets the Menu's selected node.
        /// 
        [ 
        Browsable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), 
        ] 
        public MenuItem SelectedItem {
            get { 
                return _selectedItem;
            }
        }
 

        [Browsable(false)] 
        [DefaultValue("")] 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public string SelectedValue { 
            get {
                if (SelectedItem != null) {
                    return SelectedItem.Value;
                } 

                return String.Empty; 
            } 
        }
 

        [WebSysDefaultValue(SR.Menu_SkipLinkTextDefault)]
        [Localizable(true)]
        [WebCategory("Accessibility")] 
        [WebSysDescription(SR.WebControl_SkipLinkText)]
        public string SkipLinkText { 
            get { 
                object s = ViewState["SkipLinkText"];
                if (s == null) { 
                    return SR.GetString(SR.Menu_SkipLinkTextDefault);
                }
                return (string)s;
            } 
            set {
                ViewState["SkipLinkText"] = value; 
            } 
        }
 

        [DefaultValue("")]
        [Editor("System.Web.UI.Design.ImageUrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor))]
        [UrlProperty()] 
        [WebCategory("Appearance")]
        [WebSysDescription(SR.Menu_StaticBottomSeparatorImageUrl)] 
        public string StaticBottomSeparatorImageUrl { 
            get {
                object s = ViewState["StaticBottomSeparatorImageUrl"]; 
                if (s == null) {
                    return String.Empty;
                }
                return (string)s; 
            }
            set { 
                ViewState["StaticBottomSeparatorImageUrl"] = value; 
            }
        } 


        [WebCategory("Behavior")]
        [DefaultValue(1)] 
        [Themeable(true)]
        [WebSysDescription(SR.Menu_StaticDisplayLevels)] 
        public int StaticDisplayLevels { 
            get {
                object o = ViewState["StaticDisplayLevels"]; 
                if (o == null) {
                    return 1;
                }
                return (int)o; 
            }
            set { 
                if (value < 1) { 
                    throw new ArgumentOutOfRangeException("value");
                } 
                // Note: we're not testing against the old value here because
                // the setter is not the only thing that can change the underlying
                // ViewState entry: LoadViewState modifies it directly.
                ViewState["StaticDisplayLevels"] = value; 
                // Reset max depth cache
                _maximumDepth = 0; 
                // Rebind if necessary 
                if (_dataBound && !DesignMode) {
                    _dataBound = false; 
                    PerformDataBinding();
                }
            }
        } 

 
        [ 
        DefaultValue(true),
        WebCategory("Appearance"), 
        WebSysDescription(SR.Menu_StaticDisplayPopOutImage)
        ]
        public bool StaticEnableDefaultPopOutImage {
            get { 
                object o = ViewState["StaticEnableDefaultPopOutImage"];
                if (o == null) { 
                    return true; 
                }
                return (bool)o; 
            }
            set {
                ViewState["StaticEnableDefaultPopOutImage"] = value;
            } 
        }
 
 
        [
        DefaultValue(null), 
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        NotifyParentProperty(true),
        PersistenceMode(PersistenceMode.InnerProperty),
        WebCategory("Styles"), 
        WebSysDescription(SR.Menu_StaticHoverStyle)
        ] 
        public Style StaticHoverStyle { 
            get {
                if (_staticHoverStyle == null) { 
                    _staticHoverStyle = new Style();
                    if (IsTrackingViewState) {
                        ((IStateManager)_staticHoverStyle).TrackViewState();
                    } 
                }
                return _staticHoverStyle; 
            } 
        }
 
        [DefaultValue("")]
        [WebCategory("Appearance")]
        [WebSysDescription(SR.Menu_StaticItemFormatString)]
        public string StaticItemFormatString { 
            get {
                object s = ViewState["StaticItemFormatString"]; 
                if (s == null) { 
                    return String.Empty;
                } 
                return (string)s;
            }
            set {
                ViewState["StaticItemFormatString"] = value; 
            }
        } 
 

        [ 
        WebCategory("Styles"),
        DefaultValue(null),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        NotifyParentProperty(true), 
        PersistenceMode(PersistenceMode.InnerProperty),
        WebSysDescription(SR.Menu_StaticMenuItemStyle) 
        ] 
        public MenuItemStyle StaticMenuItemStyle {
            get { 
                if (_staticItemStyle == null) {
                    _staticItemStyle = new MenuItemStyle();
                    if (IsTrackingViewState) {
                        ((IStateManager)_staticItemStyle).TrackViewState(); 
                    }
                } 
                return _staticItemStyle; 
            }
        } 


        [
        WebCategory("Styles"), 
        DefaultValue(null),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content), 
        NotifyParentProperty(true), 
        PersistenceMode(PersistenceMode.InnerProperty),
        WebSysDescription(SR.Menu_StaticMenuStyle) 
        ]
        public SubMenuStyle StaticMenuStyle {
            get {
                if (_staticMenuStyle == null) { 
                    _staticMenuStyle = new SubMenuStyle();
                    if (IsTrackingViewState) { 
                        ((IStateManager)_staticMenuStyle).TrackViewState(); 
                    }
                } 
                return _staticMenuStyle;
            }
        }
 

        [DefaultValue("")] 
        [Editor("System.Web.UI.Design.ImageUrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor))] 
        [UrlProperty()]
        [WebCategory("Appearance")] 
        [WebSysDescription(SR.Menu_StaticPopoutImageUrl)]
        public string StaticPopOutImageUrl {
            get {
                object s = ViewState["StaticPopOutImageUrl"]; 
                if (s == null) {
                    return String.Empty; 
                } 
                return (string)s;
            } 
            set {
                ViewState["StaticPopOutImageUrl"] = value;
            }
        } 

 
        [WebSysDefaultValue(SR.MenuAdapter_Expand)] 
        [WebCategory("Appearance")]
        [WebSysDescription(SR.Menu_StaticPopoutImageText)] 
        public string StaticPopOutImageTextFormatString {
            get {
                object s = ViewState["StaticPopOutImageTextFormatString"];
                if (s == null) { 
                    return SR.GetString(SR.MenuAdapter_Expand);
                } 
                return (string)s; 
            }
            set { 
                ViewState["StaticPopOutImageTextFormatString"] = value;
            }
        }
 

        [ 
        WebCategory("Styles"), 
        DefaultValue(null),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content), 
        NotifyParentProperty(true),
        PersistenceMode(PersistenceMode.InnerProperty),
        WebSysDescription(SR.Menu_StaticSelectedStyle)
        ] 
        public MenuItemStyle StaticSelectedStyle {
            get { 
                if (_staticSelectedStyle == null) { 
                    _staticSelectedStyle = new MenuItemStyle();
                    if (IsTrackingViewState) { 
                        ((IStateManager)_staticSelectedStyle).TrackViewState();
                    }
                }
                return _staticSelectedStyle; 
            }
        } 
 

        [WebCategory("Appearance")] 
        [DefaultValue(typeof(Unit), "")]
        [Themeable(true)]
        [WebSysDescription(SR.Menu_StaticSubMenuIndent)]
        public Unit StaticSubMenuIndent { 
            get {
                object o = ViewState["StaticSubMenuIndent"]; 
                if (o == null) { 
                    return Unit.Empty;
                } 
                return (Unit)o;
            }
            set {
                if (value.Value < 0) { 
                    throw new ArgumentOutOfRangeException("value");
                } 
                ViewState["StaticSubMenuIndent"] = value; 
            }
        } 

        [
        Browsable(false),
        DefaultValue(null), 
        PersistenceMode(PersistenceMode.InnerProperty),
        TemplateContainer(typeof(MenuItemTemplateContainer)), 
        WebSysDescription(SR.Menu_StaticTemplate) 
        ]
        public ITemplate StaticItemTemplate { 
            get {
                return _staticTemplate;
            }
            set { 
                _staticTemplate = value;
            } 
        } 

 
        [DefaultValue("")]
        [Editor("System.Web.UI.Design.ImageUrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor))]
        [UrlProperty()]
        [WebCategory("Appearance")] 
        [WebSysDescription(SR.Menu_StaticTopSeparatorImageUrl)]
        public string StaticTopSeparatorImageUrl { 
            get { 
                object s = ViewState["StaticTopSeparatorImageUrl"];
                if (s == null) { 
                    return String.Empty;
                }
                return (string)s;
            } 
            set {
                ViewState["StaticTopSeparatorImageUrl"] = value; 
            } 
        }
 

        /// 
        ///     Gets and sets the target window that the MenuItems 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; 
            }
        } 


        protected override HtmlTextWriterTag TagKey {
            get { 
                return HtmlTextWriterTag.Table;
            } 
        } 

        #region events 

        /// 
        ///     Triggered when an item has been clicked.
        ///  
        [WebCategory("Behavior")]
        [WebSysDescription(SR.Menu_MenuItemClick)] 
        public event MenuEventHandler MenuItemClick { 
            add {
                Events.AddHandler(_menuItemClickedEvent, value); 
            }
            remove {
                Events.RemoveHandler(_menuItemClickedEvent, value);
            } 
        }
 
 
        /// 
        ///     Triggered when a MenuItem has been databound. 
        /// 
        [WebCategory("Behavior")]
        [WebSysDescription(SR.Menu_MenuItemDataBound)]
        public event MenuEventHandler MenuItemDataBound { 
            add {
                Events.AddHandler(_menuItemDataBoundEvent, value); 
            } 
            remove {
                Events.RemoveHandler(_menuItemDataBoundEvent, value); 
            }
        }
        #endregion
 
        protected override void AddAttributesToRender(HtmlTextWriter writer) {
            VerifyRenderingInServerForm(); 
 
            string oldAccessKey = AccessKey;
            try { 
                AccessKey = String.Empty;
                base.AddAttributesToRender(writer);
            }
            finally { 
                AccessKey = oldAccessKey;
            } 
        } 

        // returns true if the style contains a class name 
        private static bool AppendCssClassName(StringBuilder builder, MenuItemStyle style, bool hyperlink) {
            bool containsClassName = false;
            if (style != null) {
                // We have to merge with any CssClass specified on the Style itself 
                if (style.CssClass.Length != 0) {
                    builder.Append(style.CssClass); 
                    builder.Append(' '); 
                    containsClassName = true;
                } 

                string className = (hyperlink ?
                    style.HyperLinkStyle.RegisteredCssClass :
                    style.RegisteredCssClass); 
                if (className.Length > 0) {
                    builder.Append(className); 
                    builder.Append(' '); 
                }
            } 
            return containsClassName;
        }

        private static void AppendMenuCssClassName(StringBuilder builder, SubMenuStyle style) { 
            if (style != null) {
                // We have to merge with any CssClass specified on the Style itself 
                if (style.CssClass.Length != 0) { 
                    builder.Append(style.CssClass);
                    builder.Append(' '); 
                }
                string className = style.RegisteredCssClass;
                if (className.Length > 0) {
                    builder.Append(className); 
                    builder.Append(' ');
                } 
            } 
        }
 
        private static T CacheGetItem(List cacheList, int index) where T : class {
            Debug.Assert(cacheList != null);
            if (index < cacheList.Count) return cacheList[index];
            return null; 
        }
 
        private static void CacheSetItem(List cacheList, int index, T item) where T : class { 
            if (cacheList.Count > index) {
                cacheList[index] = item; 
            }
            else {
                for (int i = cacheList.Count; i < index; i++) {
                    cacheList.Add(null); 
                }
                cacheList.Add(item); 
            } 
        }
 
        protected internal override void CreateChildControls() {
            Controls.Clear();

            if ((StaticItemTemplate != null) || (DynamicItemTemplate != null)) { 
                if (RequiresDataBinding &&
                    (!String.IsNullOrEmpty(DataSourceID) || DataSource != null)) { 
                    EnsureDataBound(); 
                }
                else { 
                    // Creating child controls from the Items tree
                    CreateChildControlsFromItems(/* dataBinding */ false);
                    ClearChildViewState();
                } 
            }
        } 
 

        private void CreateChildControlsFromItems(bool dataBinding) { 
            if (StaticItemTemplate != null || DynamicItemTemplate != null) {
                int childPosition = 0;
                foreach (MenuItem child in Items) {
                    CreateTemplatedControls(StaticItemTemplate, child, childPosition++, 0, dataBinding); 
                }
            } 
        } 

        ///  
        ///     Creates a menu node index that is unique for this menu
        /// 
        internal int CreateItemIndex() {
            return _nodeIndex++; 
        }
 
        private void CreateTemplatedControls(ITemplate template, MenuItem item, int position, int depth, bool dataBinding) { 

            if (template != null) { 
                MenuItemTemplateContainer container = new MenuItemTemplateContainer(position, item);
                item.Container = (MenuItemTemplateContainer)container;
                template.InstantiateIn(container);
                Controls.Add(container); 
                if (dataBinding) {
                    container.DataBind(); 
                } 
            }
            int childPosition = 0; 
            foreach (MenuItem child in item.ChildItems) {
                int nextDepth = depth + 1;
                if (template == DynamicItemTemplate) {
                    CreateTemplatedControls(DynamicItemTemplate, child, childPosition++, nextDepth, dataBinding); 
                }
                else { 
                    if (nextDepth < StaticDisplayLevels) { 
                        CreateTemplatedControls(template, child, childPosition++, nextDepth, dataBinding);
                    } 
                    else if (DynamicItemTemplate != null) {
                        CreateTemplatedControls(DynamicItemTemplate, child, childPosition++, nextDepth, dataBinding);
                    }
                } 
            }
        } 
 
        /// Data bound controls should override PerformDataBinding instead
        /// of DataBind.  If DataBind if overridden, the OnDataBinding and OnDataBound events will 
        /// fire in the wrong order.  However, for backwards compat on ListControl and AdRotator, we
        /// can't seal this method.  It is sealed on all new BaseDataBoundControl-derived controls.
        public override sealed void DataBind() {
            base.DataBind(); 
        }
 
 
        /// 
        ///     Databinds the specified node to the datasource 
        /// 
        private void DataBindItem(MenuItem item) {
            HierarchicalDataSourceView view = GetData(item.DataPath);
            // Do nothing if no datasource was set 
            if (!IsBoundUsingDataSourceID && (DataSource == null)) {
                return; 
            } 

            if (view == null) { 
                throw new InvalidOperationException(SR.GetString(SR.Menu_DataSourceReturnedNullView, ID));
            }
            IHierarchicalEnumerable enumerable = view.Select();
            item.ChildItems.Clear(); 
            if (enumerable != null) {
                // If we're bound to a SiteMapDataSource, automatically select the node 
                if (IsBoundUsingDataSourceID) { 
                    SiteMapDataSource siteMapDataSource = GetDataSource() as SiteMapDataSource;
                    if (siteMapDataSource != null) { 
                        SiteMapNode currentNode = siteMapDataSource.Provider.CurrentNode;
                        if (currentNode != null) {
                            _currentSiteMapNodeUrl = currentNode.Url;
                        } 
                    }
                } 
 
                try {
                    DataBindRecursive(item, enumerable); 
                }
                finally {
                    _currentSiteMapNodeUrl = null;
                } 
            }
        } 
 

        ///  
        ///     Databinds recursively, using the Menu's Bindings collection, until there is no more data.
        /// 
        private void DataBindRecursive(MenuItem node, IHierarchicalEnumerable enumerable) {
            // Since we are binding children, get the level below the current node's depth 
            int depth = node.Depth + 1;
 
            // Don't databind beyond the maximum specified depth 
            if ((MaximumDynamicDisplayLevels != -1) && (depth >= MaximumDepth)) {
                return; 
            }

            foreach (object item in enumerable) {
                IHierarchyData data = enumerable.GetHierarchyData(item); 

                string text = null; 
                string value = null; 
                string navigateUrl = String.Empty;
                string imageUrl = String.Empty; 
                string popOutImageUrl = String.Empty;
                string separatorImageUrl = String.Empty;
                string target = String.Empty;
                bool enabled = true; 
                bool enabledSet = false;
                bool selectable = true; 
                bool selectableSet = false; 
                string toolTip = String.Empty;
 
                string dataMember = String.Empty;

                dataMember = data.Type;
 
                MenuItemBinding level = DataBindings.GetBinding(dataMember, depth);
 
                if (level != null) { 

                    PropertyDescriptorCollection props = TypeDescriptor.GetProperties(item); 

                    // Bind Text, using the static value if necessary
                    string textField = level.TextField;
                    if (textField.Length > 0) { 
                        PropertyDescriptor desc = props.Find(textField, true);
                        if (desc != null) { 
                            object objData = desc.GetValue(item); 
                            if (objData != null) {
                                if (level.FormatString.Length > 0) { 
                                    text = string.Format(CultureInfo.CurrentCulture, level.FormatString, objData);
                                }
                                else {
                                    text = objData.ToString(); 
                                }
                            } 
                        } 
                        else {
                            throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidDataBinding, textField, "TextField")); 
                        }
                    }

                    if (String.IsNullOrEmpty(text) && !String.IsNullOrEmpty(level.Text)) { 
                        text = level.Text;
                    } 
 
                    // Bind Value, using the static value if necessary
                    string valueField = level.ValueField; 
                    if (valueField.Length > 0) {
                        PropertyDescriptor desc = props.Find(valueField, true);
                        if (desc != null) {
                            object objData = desc.GetValue(item); 
                            if (objData != null) {
                                value = objData.ToString(); 
                            } 
                        }
                        else { 
                            throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidDataBinding, valueField, "ValueField"));
                        }
                    }
 
                    if (String.IsNullOrEmpty(value) && !String.IsNullOrEmpty(level.Value)) {
                        value = level.Value; 
                    } 

                    // Bind Target, using the static value if necessary 
                    string targetField = level.TargetField;
                    if (targetField.Length > 0) {
                        PropertyDescriptor desc = props.Find(targetField, true);
                        if (desc != null) { 
                            object objData = desc.GetValue(item);
                            if (objData != null) { 
                                target = objData.ToString(); 
                            }
                        } 
                        else {
                            throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidDataBinding, targetField, "TargetField"));
                        }
                    } 

                    if (String.IsNullOrEmpty(target)) { 
                        target = level.Target; 
                    }
 
                    // Bind ImageUrl, using the static value if necessary
                    string imageUrlField = level.ImageUrlField;
                    if (imageUrlField.Length > 0) {
                        PropertyDescriptor desc = props.Find(imageUrlField, true); 
                        if (desc != null) {
                            object objData = desc.GetValue(item); 
                            if (objData != null) { 
                                imageUrl = objData.ToString();
                            } 
                        }
                        else {
                            throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidDataBinding, imageUrlField, "ImageUrlField"));
                        } 
                    }
 
                    if (String.IsNullOrEmpty(imageUrl)) { 
                        imageUrl = level.ImageUrl;
                    } 

                    // Bind NavigateUrl, using the static value if necessary
                    string navigateUrlField = level.NavigateUrlField;
                    if (navigateUrlField.Length > 0) { 
                        PropertyDescriptor desc = props.Find(navigateUrlField, true);
                        if (desc != null) { 
                            object objData = desc.GetValue(item); 
                            if (objData != null) {
                                navigateUrl = objData.ToString(); 
                            }
                        }
                        else {
                            throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidDataBinding, navigateUrlField, "NavigateUrlField")); 
                        }
                    } 
 
                    if (String.IsNullOrEmpty(navigateUrl)) {
                        navigateUrl = level.NavigateUrl; 
                    }

                    // Bind PopOutImageUrl, using the static value if necessary
                    string popOutImageUrlField = level.PopOutImageUrlField; 
                    if (popOutImageUrlField.Length > 0) {
                        PropertyDescriptor desc = props.Find(popOutImageUrlField, true); 
                        if (desc != null) { 
                            object objData = desc.GetValue(item);
                            if (objData != null) { 
                                popOutImageUrl = objData.ToString();
                            }
                        }
                        else { 
                            throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidDataBinding, popOutImageUrlField, "PopOutImageUrlField"));
                        } 
                    } 

                    if (String.IsNullOrEmpty(popOutImageUrl)) { 
                        popOutImageUrl = level.PopOutImageUrl;
                    }

                    // Bind SeperatorImageUrl, using the static value if necessary 
                    string separatorImageUrlField = level.SeparatorImageUrlField;
                    if (separatorImageUrlField.Length > 0) { 
                        PropertyDescriptor desc = props.Find(separatorImageUrlField, true); 
                        if (desc != null) {
                            object objData = desc.GetValue(item); 
                            if (objData != null) {
                                separatorImageUrl = objData.ToString();
                            }
                        } 
                        else {
                            throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidDataBinding, separatorImageUrlField, "SeparatorImageUrlField")); 
                        } 
                    }
 
                    if (String.IsNullOrEmpty(separatorImageUrl)) {
                        separatorImageUrl = level.SeparatorImageUrl;
                    }
 
                    // Bind ToolTip, using the static value if necessary
                    string toolTipField = level.ToolTipField; 
                    if (toolTipField.Length > 0) { 
                        PropertyDescriptor desc = props.Find(toolTipField, true);
                        if (desc != null) { 
                            object objData = desc.GetValue(item);
                            if (objData != null) {
                                toolTip = objData.ToString();
                            } 
                        }
                        else { 
                            throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidDataBinding, toolTipField, "ToolTipField")); 
                        }
                    } 

                    if (String.IsNullOrEmpty(toolTip)) {
                        toolTip = level.ToolTip;
                    } 

                    // Bind Enabled, using the static value if necessary 
                    string enabledField = level.EnabledField; 
                    if (enabledField.Length > 0) {
                        PropertyDescriptor desc = props.Find(enabledField, true); 
                        if (desc != null) {
                            object objData = desc.GetValue(item);
                            if (objData != null) {
                                if (objData is bool) { 
                                    enabled = (bool)objData;
                                    enabledSet = true; 
                                } 
                                else if (bool.TryParse(objData.ToString(), out enabled)) {
                                    enabledSet = true; 
                                }
                            }
                        }
                        else { 
                            throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidDataBinding, enabledField, "EnabledField"));
                        } 
                    } 

                    if (!enabledSet) { 
                        enabled = level.Enabled;
                    }

                    // Bind Selectable, using the static value if necessary 
                    string selectableField = level.SelectableField;
                    if (selectableField.Length > 0) { 
                        PropertyDescriptor desc = props.Find(selectableField, true); 
                        if (desc != null) {
                            object objData = desc.GetValue(item); 
                            if (objData != null) {
                                if (objData is bool) {
                                    selectable = (bool)objData;
                                    selectableSet = true; 
                                }
                                else if (bool.TryParse(objData.ToString(), out selectable)) { 
                                    selectableSet = true; 
                                }
                            } 
                        }
                        else {
                            throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidDataBinding, selectableField, "SelectableField"));
                        } 
                    }
 
                    if (!selectableSet) { 
                        selectable = level.Selectable;
                    } 
                }
                else if (item is INavigateUIData) {
                    INavigateUIData navigateUIData = (INavigateUIData)item;
                    text = navigateUIData.Name; 
                    value = navigateUIData.Value;
                    navigateUrl = navigateUIData.NavigateUrl; 
                    if (String.IsNullOrEmpty(navigateUrl)) { 
                        selectable = false;
                    } 
                    toolTip = navigateUIData.Description;
                }

                if (text == null) { 
                    text = item.ToString();
                } 
 
                MenuItem newItem = null;
                // Allow String.Empty for the text, but not null 
                if ((text != null) || (value != null)) {
                    newItem = new MenuItem(text, value, imageUrl, navigateUrl, target);
                }
 
                if (newItem != null) {
                    if (toolTip.Length > 0) { 
                        newItem.ToolTip = toolTip; 
                    }
                    if (popOutImageUrl.Length > 0) { 
                        newItem.PopOutImageUrl = popOutImageUrl;
                    }
                    if (separatorImageUrl.Length > 0) {
                        newItem.SeparatorImageUrl = separatorImageUrl; 
                    }
                    newItem.Enabled = enabled; 
                    newItem.Selectable = selectable; 

                    newItem.SetDataPath(data.Path); 
                    newItem.SetDataBound(true);

                    node.ChildItems.Add(newItem);
 
                    if (String.Equals(data.Path, _currentSiteMapNodeUrl, StringComparison.OrdinalIgnoreCase)) {
                        newItem.Selected = true; 
                    } 

                    // Make sure we call user code if they've hooked the populate event 
                    newItem.SetDataItem(data.Item);
                    OnMenuItemDataBound(new MenuEventArgs(newItem));
                    newItem.SetDataItem(null);
 
                    if (data.HasChildren && (depth < MaximumDepth)) {
                        IHierarchicalEnumerable newEnumerable = data.GetChildren(); 
                        if (newEnumerable != null) { 
                            DataBindRecursive(newItem, newEnumerable);
                        } 
                    }
                }
            }
        } 

        protected override void EnsureDataBound() { 
            base.EnsureDataBound(); 
            if (!_subControlsDataBound) {
                foreach (Control ctrl in Controls) { 
                    ctrl.DataBind();
                }
                _subControlsDataBound = true;
            } 
        }
 
        public MenuItem FindItem(string valuePath) { 
            if (valuePath == null) {
                return null; 
            }
            return Items.FindItem(valuePath.Split(PathSeparator), 0);
        }
 
        internal string GetCssClassName(MenuItem item, bool hyperLink) {
            bool discarded; 
            return GetCssClassName(item, hyperLink, out discarded); 
        }
 
        internal string GetCssClassName(MenuItem item, bool hyperlink, out bool containsClassName) {
            if (item == null) {
                throw new ArgumentNullException("item");
            } 

            containsClassName = false; 
            int depth = item.Depth; 
            string baseClassName = CacheGetItem(
                hyperlink ? CachedMenuItemHyperLinkClassNames : CachedMenuItemClassNames, 
                depth);
            if (CachedLevelsContainingCssClass.Contains(depth)) {
                containsClassName = true;
            } 

            if (!item.Selected && (baseClassName != null)) { 
                return baseClassName; 
            }
 
            StringBuilder builder = new StringBuilder();
            if (baseClassName != null) {
                if (!item.Selected) return baseClassName;
                builder.Append(baseClassName); 
                builder.Append(' ');
            } 
            else { 
                // No cached style, so build it
                if (hyperlink) { 
                    builder.Append(RootMenuItemStyle.RegisteredCssClass);
                    builder.Append(' ');
                }
 
                if (depth < StaticDisplayLevels) {
                    containsClassName |= AppendCssClassName(builder, _staticItemStyle, hyperlink); 
                } 
                else {
                    containsClassName |= AppendCssClassName(builder, _dynamicItemStyle, hyperlink); 
                }
                if ((depth < LevelMenuItemStyles.Count) && (LevelMenuItemStyles[depth] != null)) {
                    containsClassName |= AppendCssClassName(builder, LevelMenuItemStyles[depth], hyperlink);
                } 

                baseClassName = builder.ToString().Trim(); 
                CacheSetItem( 
                    hyperlink ? CachedMenuItemHyperLinkClassNames : CachedMenuItemClassNames,
                    depth, 
                    baseClassName);

                if (containsClassName && !CachedLevelsContainingCssClass.Contains(depth)) {
                    CachedLevelsContainingCssClass.Add(depth); 
                }
            } 
 
            if (item.Selected) {
                if (depth < StaticDisplayLevels) { 
                    containsClassName |= AppendCssClassName(builder, _staticSelectedStyle, hyperlink);
                }
                else {
                    containsClassName |= AppendCssClassName(builder, _dynamicSelectedStyle, hyperlink); 
                }
                if ((depth < LevelSelectedStyles.Count) && (LevelSelectedStyles[depth] != null)) { 
                    MenuItemStyle style = LevelSelectedStyles[depth]; 
                    containsClassName |= AppendCssClassName(builder, style, hyperlink);
                } 
                return builder.ToString().Trim();
            }
            return baseClassName;
        } 

        /// Used by GetDesignModeState to find the first dynamic submenu in Items 
        private MenuItem GetOneDynamicItem(MenuItem item) { 
            if (item.Depth >= StaticDisplayLevels) {
                return item; 
            }
            for (int i = 0; i < item.ChildItems.Count; i++) {
                MenuItem result = GetOneDynamicItem(item.ChildItems[i]);
                if (result != null) { 
                    return result;
                } 
            } 
            return null;
        } 


        /// 
        ///  
        /// The designer can get the static and the dynamic mode html by using the
        /// _getDesignTimeStaticHtml and _getDesignTimeDynamicHtml defined string keys 
        /// of the dictionary. 
        /// 
        [SecurityPermission(SecurityAction.Demand, Unrestricted = true)] 
        protected override IDictionary GetDesignModeState() {
            IDictionary dictionary = base.GetDesignModeState();
            Debug.Assert(dictionary != null && DesignMode);
 
            CreateChildControls();
            foreach (Control c in Controls) { 
                c.DataBind(); 
            }
 
            // Create the html for the static part
            using (StringWriter staticHtmlBuilder = new StringWriter(CultureInfo.CurrentCulture)) {
                using (HtmlTextWriter htmlWriter = GetDesignTimeWriter(staticHtmlBuilder)) {
                    Renderer.RenderBeginTag(htmlWriter, true); 
                    Renderer.RenderContents(htmlWriter, true);
                    Renderer.RenderEndTag(htmlWriter, true); 
                    dictionary[_getDesignTimeStaticHtml] = staticHtmlBuilder.ToString(); 
                }
            } 
            // Remember the static depth so we can lower it if necessary to make it faster and avoid overflows
            int oldStaticDisplayLevels = StaticDisplayLevels;
            try {
                // Find a dynamic sub-menu 
                MenuItem dynamicSubMenu = GetOneDynamicItem(RootItem);
                if (dynamicSubMenu == null) { 
                    // We need to forge a whole new dynamic submenu 
                    // First lower the static display levels
                    _dataBound = false; 
                    StaticDisplayLevels = 1;
                    dynamicSubMenu = new MenuItem();
                    dynamicSubMenu.SetDepth(0);
                    dynamicSubMenu.SetOwner(this); 
                    // Create a single dynamic submenu, with one submenu
                    string dummyText = SR.GetString(SR.Menu_DesignTimeDummyItemText); 
                    for (int i = 0; i < 5; i++) { 
                        MenuItem newItem = new MenuItem(dummyText);
                        if (DynamicItemTemplate != null) { 
                            MenuItemTemplateContainer container = new MenuItemTemplateContainer(i, newItem);
                            newItem.Container = container;
                            DynamicItemTemplate.InstantiateIn(container);
                            container.Site = this.Site; 
                            container.DataBind();
                        } 
                        dynamicSubMenu.ChildItems.Add(newItem); 
                    }
                    dynamicSubMenu.ChildItems[1].ChildItems.Add(new MenuItem()); 
                    // Delete cached styles to ensure consistency
                    _cachedLevelsContainingCssClass = null;
                    _cachedMenuItemStyles = null;
                    _cachedSubMenuStyles = null; 
                    _cachedMenuItemClassNames = null;
                    _cachedMenuItemHyperLinkClassNames = null; 
                    _cachedSubMenuClassNames = null; 
                }
                else { 
                    dynamicSubMenu = dynamicSubMenu.Parent;
                }
                // Create the html for the dynamic part
                using (StringWriter dynamicHtmlBuilder = new StringWriter(CultureInfo.CurrentCulture)) { 
                    using (HtmlTextWriter htmlWriter = GetDesignTimeWriter(dynamicHtmlBuilder)) {
                        // Render the control's position on the outer table 
                        Attributes.AddAttributes(htmlWriter); 
                        // Rendering a table around the div so that the designer sees it as a block
                        htmlWriter.RenderBeginTag(HtmlTextWriterTag.Table); 
                        htmlWriter.RenderBeginTag(HtmlTextWriterTag.Tr);
                        htmlWriter.RenderBeginTag(HtmlTextWriterTag.Td);

                        dynamicSubMenu.Render(htmlWriter, true, false, false); 

                        htmlWriter.RenderEndTag(); 
                        htmlWriter.RenderEndTag(); 
                        htmlWriter.RenderEndTag();
                        dictionary[_getDesignTimeDynamicHtml] = dynamicHtmlBuilder.ToString(); 
                    }
                }
            }
            finally { 
                if (StaticDisplayLevels != oldStaticDisplayLevels) {
                    StaticDisplayLevels = oldStaticDisplayLevels; 
                } 
            }
 
            return dictionary;
        }

        private HtmlTextWriter GetDesignTimeWriter(StringWriter stringWriter) { 
            if (_designTimeTextWriterType == null) {
                return new HtmlTextWriter(stringWriter); 
            } 
            else {
                Debug.Assert(_designTimeTextWriterType.IsSubclassOf(typeof(HtmlTextWriter))); 
                ConstructorInfo constructor = _designTimeTextWriterType.GetConstructor(new Type[] { typeof(TextWriter) });
                if (constructor == null) {
                    return new HtmlTextWriter(stringWriter);
                } 
                return (HtmlTextWriter)(constructor.Invoke(new object[] { stringWriter }));
            } 
        } 

 
        /// 
        ///     Gets the URL for the specified image, properly pathing the image filename depending on which image it is
        /// 
        internal string GetImageUrl(int index) { 
            if (ImageUrls[index] == null) {
                switch (index) { 
                    case ScrollUpImageIndex: 
                        ImageUrls[index] = ScrollUpImageUrlInternal;
                        break; 
                    case ScrollDownImageIndex:
                        ImageUrls[index] = ScrollDownImageUrlInternal;
                        break;
                    case PopOutImageIndex: 
                        ImageUrls[index] = PopoutImageUrlInternal;
                        break; 
                } 

                ImageUrls[index] = ResolveClientUrl(ImageUrls[index]); 
            }

            return ImageUrls[index];
        } 

        internal MenuItemStyle GetMenuItemStyle(MenuItem item) { 
            if (item == null) { 
                throw new ArgumentNullException("item");
            } 

            int depth = item.Depth;
            MenuItemStyle typedStyle = CacheGetItem(CachedMenuItemStyles, depth);
 
            if (!item.Selected && typedStyle != null) return typedStyle;
 
            if (typedStyle == null) { 
                typedStyle = new MenuItemStyle();
                typedStyle.CopyFrom(RootMenuItemStyle); 
                if (depth < StaticDisplayLevels) {
                    if (_staticItemStyle != null) {
                        TreeView.GetMergedStyle(typedStyle, _staticItemStyle);
                    } 
                }
                else if (depth >= StaticDisplayLevels && _dynamicItemStyle != null) { 
                    TreeView.GetMergedStyle(typedStyle, _dynamicItemStyle); 
                }
                if ((depth < LevelMenuItemStyles.Count) && (LevelMenuItemStyles[depth] != null)) { 
                    TreeView.GetMergedStyle(typedStyle, LevelMenuItemStyles[depth]);
                }
                CacheSetItem(CachedMenuItemStyles, depth, typedStyle);
            } 

            if (item.Selected) { 
                MenuItemStyle selectedStyle = new MenuItemStyle(); 
                selectedStyle.CopyFrom(typedStyle);
                if (depth < StaticDisplayLevels) { 
                    if (_staticSelectedStyle != null) {
                        TreeView.GetMergedStyle(selectedStyle, _staticSelectedStyle);
                    }
                } 
                else if (depth >= StaticDisplayLevels && _dynamicSelectedStyle != null) {
                    TreeView.GetMergedStyle(selectedStyle, _dynamicSelectedStyle); 
                } 
                if (depth < LevelSelectedStyles.Count && LevelSelectedStyles[depth] != null) {
                    TreeView.GetMergedStyle(selectedStyle, LevelSelectedStyles[depth]); 
                }
                return selectedStyle;
            }
            return typedStyle; 
        }
 
        internal string GetSubMenuCssClassName(MenuItem item) { 
            if (item == null) {
                throw new ArgumentNullException("item"); 
            }

            int nextDepth = item.Depth + 1;
            string baseClassName = CacheGetItem(CachedSubMenuClassNames, nextDepth); 
            if (baseClassName != null) return baseClassName;
 
            StringBuilder builder = new StringBuilder(); 
            if (nextDepth < StaticDisplayLevels) {
                AppendMenuCssClassName(builder, _staticMenuStyle); 
            }
            else {
                SubMenuStyle subMenuStyle = _panelStyle as SubMenuStyle;
                if (subMenuStyle != null) { 
                    AppendMenuCssClassName(builder, subMenuStyle);
                } 
                AppendMenuCssClassName(builder, _dynamicMenuStyle); 
            }
            if ((nextDepth < LevelSubMenuStyles.Count) && (LevelSubMenuStyles[nextDepth] != null)) { 
                SubMenuStyle style = LevelSubMenuStyles[nextDepth] as SubMenuStyle;
                AppendMenuCssClassName(builder, style);
            }
 
            baseClassName = builder.ToString().Trim();
            CacheSetItem(CachedSubMenuClassNames, nextDepth, baseClassName); 
            return baseClassName; 
        }
 
        internal SubMenuStyle GetSubMenuStyle(MenuItem item) {
            if (item == null) {
                throw new ArgumentNullException("item");
            } 

            int nextDepth = item.Depth + 1; 
            SubMenuStyle subMenuStyle = CacheGetItem(CachedSubMenuStyles, nextDepth); 

            if (subMenuStyle != null) return subMenuStyle; 

            int staticDisplayLevels = StaticDisplayLevels;
            if (nextDepth >= staticDisplayLevels && !DesignMode) {
                subMenuStyle = new PopOutPanel.PopOutPanelStyle(Panel); 
            }
            else { 
                subMenuStyle = new SubMenuStyle(); 
            }
            if (nextDepth < staticDisplayLevels) { 
                if (_staticMenuStyle != null) {
                    subMenuStyle.CopyFrom(_staticMenuStyle);
                }
            } 
            else if (nextDepth >= staticDisplayLevels && _dynamicMenuStyle != null) {
                subMenuStyle.CopyFrom(_dynamicMenuStyle); 
            } 
            if (_levelStyles != null &&
                _levelStyles.Count > nextDepth && 
                _levelStyles[nextDepth] != null) {
                TreeView.GetMergedStyle(subMenuStyle, _levelStyles[nextDepth]);
            }
 
            CacheSetItem(CachedSubMenuStyles, nextDepth, subMenuStyle);
            return subMenuStyle; 
        } 

        internal void EnsureRootMenuStyle() { 
            if (_rootMenuItemStyle == null) {
                _rootMenuItemStyle = new Style();
                _rootMenuItemStyle.Font.CopyFrom(Font);
                if (!ForeColor.IsEmpty) { 
                    _rootMenuItemStyle.ForeColor = ForeColor;
                } 
                // Not defaulting to black anymore for not entirely satisfying but reasonable reasons (VSWhidbey 356729) 
                if (!ControlStyle.IsSet(System.Web.UI.WebControls.Style.PROP_FONT_UNDERLINE)) {
                    _rootMenuItemStyle.Font.Underline = false; 
                }
            }
        }
 
        protected internal override void LoadControlState(object savedState) {
            Pair state = savedState as Pair; 
            if (state == null) { 
                base.LoadControlState(savedState);
                return; 
            }
            base.LoadControlState(state.First);

            _selectedItem = null; 
            if (state.Second != null) {
                string path = state.Second as string; 
                if (path != null) { 
                    _selectedItem = Items.FindItem(path.Split(TreeView.InternalPathSeparator), 0);
                } 
            }
        }

        protected override void LoadViewState(object state) { 
            if (state != null) {
                object[] savedState = (object[])state; 
 
                if (savedState[1] != null) {
                    ((IStateManager)StaticMenuItemStyle).LoadViewState(savedState[1]); 
                }

                if (savedState[2] != null) {
                    ((IStateManager)StaticSelectedStyle).LoadViewState(savedState[2]); 
                }
 
                if (savedState[3] != null) { 
                    ((IStateManager)StaticHoverStyle).LoadViewState(savedState[3]);
                } 

                if (savedState[4] != null) {
                    ((IStateManager)StaticMenuStyle).LoadViewState(savedState[4]);
                } 

                if (savedState[5] != null) { 
                    ((IStateManager)DynamicMenuItemStyle).LoadViewState(savedState[5]); 
                }
 
                if (savedState[6] != null) {
                    ((IStateManager)DynamicSelectedStyle).LoadViewState(savedState[6]);
                }
 
                if (savedState[7] != null) {
                    ((IStateManager)DynamicHoverStyle).LoadViewState(savedState[7]); 
                } 

                if (savedState[8] != null) { 
                    ((IStateManager)DynamicMenuStyle).LoadViewState(savedState[8]);
                }

                if (savedState[9] != null) { 
                    ((IStateManager)LevelMenuItemStyles).LoadViewState(savedState[9]);
                } 
 
                if (savedState[10] != null) {
                    ((IStateManager)LevelSelectedStyles).LoadViewState(savedState[10]); 
                }

                if (savedState[11] != null) {
                    ((IStateManager)LevelSubMenuStyles).LoadViewState(savedState[11]); 
                }
 
                if (savedState[12] != null) { 
                    ((IStateManager)Items).LoadViewState(savedState[12]);
                    if (!String.IsNullOrEmpty(DataSourceID) || DataSource != null) { 
                        _dataBound = true;
                    }
                }
 
                // Restore the core viewstate last because some property changes here could
                // necessitate item rebinding (for example, MaximumDynamicDisplayLevels) 
                if (savedState[0] != null) { 
                    base.LoadViewState(savedState[0]);
                } 
            }
        }

        protected override bool OnBubbleEvent(object source, EventArgs e) { 
            MenuEventArgs me = e as MenuEventArgs;
            if (me != null && StringUtil.EqualsIgnoreCase(me.CommandName, MenuItemClickCommandName)) { 
 
                // Do not take any postback into account if the menu is disabled.
                if (!IsEnabled) return true; 

                OnMenuItemClick(me);
                if (AdapterInternal != null) {
                    MenuAdapter menuAdapter = AdapterInternal as MenuAdapter; 
                    if (menuAdapter != null) {
                        MenuItem mi = me.Item; 
                        // Need to tell the adapter about bubbled click events 
                        // for the templated case if the item has children
                        if (mi != null && 
                            mi.ChildItems.Count > 0 &&
                            mi.Depth + 1 >= StaticDisplayLevels) {

                            menuAdapter.SetPath(me.Item.InternalValuePath); 
                        }
                    } 
                } 
                RaiseBubbleEvent(this, e);
                return true; 
            }
            if (e is CommandEventArgs) {
                RaiseBubbleEvent(this, e);
                return true; 
            }
            return false; 
        } 

        protected override void OnDataBinding(EventArgs e) { 
            EnsureChildControls();
            base.OnDataBinding(e);
        }
 
        protected internal override void OnInit(EventArgs e) {
            base.OnInit(e); 
            Page.RegisterRequiresControlState(this); 
        }
 

        protected virtual void OnMenuItemClick(MenuEventArgs e) {
            SetSelectedItem(e.Item);
            MenuEventHandler handler = (MenuEventHandler)Events[_menuItemClickedEvent]; 
            if (handler != null) {
                handler(this, e); 
            } 
        }
 

        /// 
        ///     Raises the MenuItemDataBound event
        ///  
        protected virtual void OnMenuItemDataBound(MenuEventArgs e) {
            MenuEventHandler handler = (MenuEventHandler)Events[_menuItemDataBoundEvent]; 
            if (handler != null) { 
                handler(this, e);
            } 
        }

        /// 
        ///     Overridden to register for postback, and if client script is enabled, renders out 
        ///     the necessary script and hidden field to function.
        ///  
        protected internal override void OnPreRender(EventArgs e) { 
            base.OnPreRender(e);
 
            if (Items.Count > 0) {
                Renderer.PreRender(IsEnabled);
            }
        } 

        ///  
        ///     Overridden to register for postback, and if client script is enabled, renders out 
        ///     the necessary script and hidden field to function.
        ///  
        internal void OnPreRender(EventArgs e, bool registerScript) {
            base.OnPreRender(e);

            if (Items.Count > 0) { 
                Renderer.PreRender(registerScript);
            } 
        } 

        ///  
        ///     Overridden to create all the items based on the datasource provided
        /// 
        protected internal override void PerformDataBinding() {
            base.PerformDataBinding(); 

            DataBindItem(RootItem); 
 
            if (!DesignMode && _dataBound &&
                String.IsNullOrEmpty(DataSourceID) && DataSource == null) { 

                Items.Clear();
                Controls.Clear();
                ClearChildViewState(); 
                TrackViewState();
                ChildControlsCreated = true; 
                return; 
            }
 
            if (!String.IsNullOrEmpty(DataSourceID) ||
                DataSource != null) {

                Controls.Clear(); 
                ClearChildState();
                TrackViewState(); 
 
                CreateChildControlsFromItems(true);
                ChildControlsCreated = true; 
                _dataBound = true;
            }
            else if (!_subControlsDataBound) {
                foreach (Control ctrl in Controls) { 
                    ctrl.DataBind();
                } 
            } 
            _subControlsDataBound = true;
        } 

        protected internal override void Render(HtmlTextWriter writer) {
            VerifyRenderingInServerForm();
 
            if (Items.Count > 0) {
                Renderer.RenderBeginTag(writer, false); 
                Renderer.RenderContents(writer, false); 
                Renderer.RenderEndTag(writer, false);
            } 
        }

        public override void RenderBeginTag(HtmlTextWriter writer) {
            Renderer.RenderBeginTag(writer, false); 
        }
 
        protected internal override void RenderContents(HtmlTextWriter writer) { 
            Renderer.RenderContents(writer, false);
        } 

        public override void RenderEndTag(HtmlTextWriter writer) {
            Renderer.RenderEndTag(writer, false);
        } 

        internal void ResetCachedStyles() { 
            // Reset all these cached values so things can pick up changes in the designer 
            if (_dynamicItemStyle != null) {
                _dynamicItemStyle.ResetCachedStyles(); 
            }
            if (_staticItemStyle != null) {
                _staticItemStyle.ResetCachedStyles();
            } 
            if (_dynamicSelectedStyle != null) {
                _dynamicSelectedStyle.ResetCachedStyles(); 
            } 
            if (_staticSelectedStyle != null) {
                _staticSelectedStyle.ResetCachedStyles(); 
            }
            if (_staticHoverStyle != null) {
                _staticHoverHyperLinkStyle = new HyperLinkStyle(_staticHoverStyle);
            } 
            if (_dynamicHoverStyle != null) {
                _dynamicHoverHyperLinkStyle = new HyperLinkStyle(_dynamicHoverStyle); 
            } 

            foreach (MenuItemStyle style in LevelMenuItemStyles) { 
                style.ResetCachedStyles();
            }

            foreach (MenuItemStyle style in LevelSelectedStyles) { 
                style.ResetCachedStyles();
            } 
 
            if (_imageUrls != null) {
                for (int i = 0; i < _imageUrls.Length; i++) { 
                    _imageUrls[i] = null;
                }
            }
 
            _cachedPopOutImageUrl = null;
            _cachedScrollDownImageUrl = null; 
            _cachedScrollUpImageUrl = null; 
            _cachedLevelsContainingCssClass = null;
            _cachedMenuItemClassNames = null; 
            _cachedMenuItemHyperLinkClassNames = null;
            _cachedMenuItemStyles = null;
            _cachedSubMenuClassNames = null;
            _cachedSubMenuStyles = null; 
        }
 
        protected internal override object SaveControlState() { 
            object baseState = base.SaveControlState();
            if (_selectedItem != null) { 
                return new Pair(baseState, _selectedItem.InternalValuePath);
            }
            else {
                return baseState; 
            }
        } 
 
        protected override object SaveViewState() {
            object[] state = new object[13]; 

            state[0] = base.SaveViewState();

            bool hasViewState = (state[0] != null); 

            if (_staticItemStyle != null) { 
                state[1] = ((IStateManager)_staticItemStyle).SaveViewState(); 
                hasViewState |= (state[1] != null);
            } 

            if (_staticSelectedStyle != null) {
                state[2] = ((IStateManager)_staticSelectedStyle).SaveViewState();
                hasViewState |= (state[2] != null); 
            }
 
            if (_staticHoverStyle != null) { 
                state[3] = ((IStateManager)_staticHoverStyle).SaveViewState();
                hasViewState |= (state[3] != null); 
            }

            if (_staticMenuStyle != null) {
                state[4] = ((IStateManager)_staticMenuStyle).SaveViewState(); 
                hasViewState |= (state[4] != null);
            } 
 
            if (_dynamicItemStyle != null) {
                state[5] = ((IStateManager)_dynamicItemStyle).SaveViewState(); 
                hasViewState |= (state[5] != null);
            }

            if (_dynamicSelectedStyle != null) { 
                state[6] = ((IStateManager)_dynamicSelectedStyle).SaveViewState();
                hasViewState |= (state[6] != null); 
            } 

            if (_dynamicHoverStyle != null) { 
                state[7] = ((IStateManager)_dynamicHoverStyle).SaveViewState();
                hasViewState |= (state[7] != null);
            }
 
            if (_dynamicMenuStyle != null) {
                state[8] = ((IStateManager)_dynamicMenuStyle).SaveViewState(); 
                hasViewState |= (state[8] != null); 
            }
 
            if (_levelMenuItemStyles != null) {
                state[9] = ((IStateManager)_levelMenuItemStyles).SaveViewState();
                hasViewState |= (state[9] != null);
            } 

            if (_levelSelectedStyles != null) { 
                state[10] = ((IStateManager)_levelSelectedStyles).SaveViewState(); 
                hasViewState |= (state[10] != null);
            } 

            if (_levelStyles != null) {
                state[11] = ((IStateManager)_levelStyles).SaveViewState();
                hasViewState |= (state[11] != null); 
            }
 
            state[12] = ((IStateManager)Items).SaveViewState(); 
            hasViewState |= (state[12] != null);
 
            if (hasViewState) {
                return state;
            }
            else { 
                return null;
            } 
        } 

        [SecurityPermission(SecurityAction.Demand, Unrestricted = true)] 
        protected override void SetDesignModeState(IDictionary data) {
            if (data.Contains("DesignTimeTextWriterType")) {
                Type writerType = data["DesignTimeTextWriterType"] as Type;
                if (writerType != null && writerType.IsSubclassOf(typeof(HtmlTextWriter))) { 
                    _designTimeTextWriterType = writerType;
                } 
            } 
            base.SetDesignModeState(data);
        } 


        /// 
        /// Allows a derived Menu to set the DataBound proprety on a node 
        /// 
        protected void SetItemDataBound(MenuItem node, bool dataBound) { 
            node.SetDataBound(dataBound); 
        }
 

        /// 
        /// Allows a derived Menu to set the DataItem on a node
        ///  
        protected void SetItemDataItem(MenuItem node, object dataItem) {
            node.SetDataItem(dataItem); 
        } 

 
        /// 
        /// Allows a derived Menu to set the DataPath on a node
        /// 
        protected void SetItemDataPath(MenuItem node, string dataPath) { 
            node.SetDataPath(dataPath);
        } 
 
        internal void SetSelectedItem(MenuItem node) {
            Debug.Assert(node == null || node.Owner == this); 

            if (_selectedItem != node) {
                if (node != null) {
                    if (node.Depth >= MaximumDepth) { 
                        throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidDepth));
                    } 
                    if (!(node.IsEnabledNoOwner && node.Selectable)) { 
                        throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidSelection));
                    } 
                }

                // Unselect the previously selected item
                if ((_selectedItem != null) && (_selectedItem.Selected)) { 
                    _selectedItem.SetSelected(false);
                } 
                _selectedItem = node; 
                // Notify the new selected item that it's now selected
                if ((_selectedItem != null) && !_selectedItem.Selected) { 
                    _selectedItem.SetSelected(true);
                }
            }
        } 

 
        ///  
        /// 
        ///    Marks the starting point to begin tracking and saving changes to the 
        ///    control as part of the control viewstate.
        /// 
        protected override void TrackViewState() {
            base.TrackViewState(); 

            if (_staticItemStyle != null) { 
                ((IStateManager)_staticItemStyle).TrackViewState(); 
            }
            if (_staticSelectedStyle != null) { 
                ((IStateManager)_staticSelectedStyle).TrackViewState();
            }
            if (_staticHoverStyle != null) {
                ((IStateManager)_staticHoverStyle).TrackViewState(); 
            }
            if (_staticMenuStyle != null) { 
                ((IStateManager)_staticMenuStyle).TrackViewState(); 
            }
            if (_dynamicItemStyle != null) { 
                ((IStateManager)_dynamicItemStyle).TrackViewState();
            }
            if (_dynamicSelectedStyle != null) {
                ((IStateManager)_dynamicSelectedStyle).TrackViewState(); 
            }
            if (_dynamicHoverStyle != null) { 
                ((IStateManager)_dynamicHoverStyle).TrackViewState(); 
            }
            if (_dynamicMenuStyle != null) { 
                ((IStateManager)_dynamicMenuStyle).TrackViewState();
            }
            if (_levelMenuItemStyles != null) {
                ((IStateManager)_levelMenuItemStyles).TrackViewState(); 
            }
            if (_levelSelectedStyles != null) { 
                ((IStateManager)_levelSelectedStyles).TrackViewState(); 
            }
            if (_levelStyles != null) { 
                ((IStateManager)_levelStyles).TrackViewState();
            }
            if (_bindings != null) {
                ((IStateManager)_bindings).TrackViewState(); 
            }
 
            ((IStateManager)Items).TrackViewState(); 
        }
 
        internal void VerifyRenderingInServerForm() {
            if (Page != null) {
                Page.VerifyRenderingInServerForm(this);
            } 
        }
 
        #region IPostBackEventHandler implementation 

        ///  
        void IPostBackEventHandler.RaisePostBackEvent(string eventArgument) {
            RaisePostBackEvent(eventArgument);
        }
 
        protected internal virtual void RaisePostBackEvent(string eventArgument) {
            ValidateEvent(UniqueID, eventArgument); 
 
            // Do not take any postback into account if the menu is disabled.
            if (!IsEnabled) return; 

            EnsureChildControls();
            if (AdapterInternal != null) {
                IPostBackEventHandler pbeh = AdapterInternal as IPostBackEventHandler; 
                if (pbeh != null) {
                    pbeh.RaisePostBackEvent(eventArgument); 
                } 
            }
            else { 
                InternalRaisePostBackEvent(eventArgument);
            }
        }
 
        internal void InternalRaisePostBackEvent(string eventArgument) {
            if (eventArgument.Length == 0) { 
                return; 
            }
 
            // Get the path of the node specified in the eventArgument
            string nodePath = HttpUtility.HtmlDecode(eventArgument);
            // Check the number of separator characters in the argument (should not be more than the max depth)
            int matches = 0; 
            for (int i = 0; i < nodePath.Length; i++) {
                if (nodePath[i] == TreeView.InternalPathSeparator) { 
                    if (++matches >= MaximumDepth) { 
                        throw new InvalidOperationException(SR.GetString(SR.Menu_InvalidDepth));
                    } 
                }
            }
            // Find that node in the tree
            MenuItem node = Items.FindItem(nodePath.Split(TreeView.InternalPathSeparator), 0); 

            if (node != null) { 
                OnMenuItemClick(new MenuEventArgs(node)); 
            }
        } 
        #endregion
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

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