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 CollectionCachedLevelsContainingCssClass { 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 CollectionCachedLevelsContainingCssClass { 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
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ConvertersCollection.cs
- ClientTargetSection.cs
- HttpModuleCollection.cs
- Object.cs
- ToolStripSeparator.cs
- Evidence.cs
- ConnectorMovedEventArgs.cs
- SR.cs
- BooleanKeyFrameCollection.cs
- TypeElement.cs
- AssemblyContextControlItem.cs
- SerializableAttribute.cs
- CompiledIdentityConstraint.cs
- XmlEventCache.cs
- ThicknessConverter.cs
- GroupItemAutomationPeer.cs
- HtmlTableCellCollection.cs
- serverconfig.cs
- ResXFileRef.cs
- Rect3DValueSerializer.cs
- ArrayConverter.cs
- DbProviderFactory.cs
- CreateUserWizardAutoFormat.cs
- SiteMapDataSourceView.cs
- ListenerElementsCollection.cs
- ContextInformation.cs
- PolicyLevel.cs
- ContentControl.cs
- QilChoice.cs
- BStrWrapper.cs
- BindingEditor.xaml.cs
- HierarchicalDataBoundControlAdapter.cs
- QilExpression.cs
- XmlResolver.cs
- EdmComplexTypeAttribute.cs
- BoundPropertyEntry.cs
- COAUTHIDENTITY.cs
- ShapingEngine.cs
- CryptoStream.cs
- RegexGroup.cs
- HatchBrush.cs
- CodePageUtils.cs
- PreProcessInputEventArgs.cs
- ParenExpr.cs
- TextTreeTextNode.cs
- Pair.cs
- XmlLoader.cs
- Control.cs
- DesignerRegionCollection.cs
- CopyNamespacesAction.cs
- AbstractDataSvcMapFileLoader.cs
- NetworkCredential.cs
- BindingExpressionBase.cs
- StorageEntityTypeMapping.cs
- DBPropSet.cs
- shaper.cs
- BaseCodePageEncoding.cs
- BuildProviderAppliesToAttribute.cs
- UiaCoreTypesApi.cs
- smtppermission.cs
- VectorAnimationBase.cs
- printdlgexmarshaler.cs
- DesignerSerializationVisibilityAttribute.cs
- DropSource.cs
- ModifiableIteratorCollection.cs
- XmlObjectSerializerWriteContextComplexJson.cs
- ZoneButton.cs
- ConnectionPoint.cs
- ParseHttpDate.cs
- ResourceManager.cs
- AnimatedTypeHelpers.cs
- XmlSchemaResource.cs
- ExtenderControl.cs
- PenThread.cs
- RectangleGeometry.cs
- AlignmentXValidation.cs
- HtmlProps.cs
- IImplicitResourceProvider.cs
- HttpSessionStateWrapper.cs
- FixedNode.cs
- AllMembershipCondition.cs
- EventLogPermissionEntryCollection.cs
- MetadataFile.cs
- EventArgs.cs
- SimpleHandlerBuildProvider.cs
- SmtpFailedRecipientException.cs
- MetabaseServerConfig.cs
- SafeCoTaskMem.cs
- MessageFilter.cs
- NameValueCollection.cs
- HandleCollector.cs
- TransactionProxy.cs
- COM2IProvidePropertyBuilderHandler.cs
- TreeNodeStyleCollection.cs
- DataGridViewColumnTypePicker.cs
- EditCommandColumn.cs
- AdRotator.cs
- WindowsTooltip.cs
- ResolveCriteria.cs
- ControlBuilder.cs