2 // System.Web.UI.WebControls.Menu.cs
5 // Lluis Sanchez Gual (lluis@novell.com)
6 // Igor Zelmanovich (igorz@mainsoft.com)
8 // (C) 2004 Novell, Inc (http://www.novell.com)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 using System.Collections;
37 using System.ComponentModel;
39 using System.Web.Handlers;
40 using System.Collections.Specialized;
43 using System.Collections.Generic;
45 namespace System.Web.UI.WebControls
47 [DefaultEvent ("MenuItemClick")]
48 [ControlValueProperty ("SelectedValue")]
49 [Designer ("System.Web.UI.Design.WebControls.MenuDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
50 public class Menu : HierarchicalDataBoundControl, IPostBackEventHandler, INamingContainer
52 MenuItemStyle dynamicMenuItemStyle;
53 SubMenuStyle dynamicMenuStyle;
54 MenuItemStyle dynamicSelectedStyle;
55 MenuItemStyle staticMenuItemStyle;
56 SubMenuStyle staticMenuStyle;
57 MenuItemStyle staticSelectedStyle;
58 Style staticHoverStyle;
59 Style dynamicHoverStyle;
61 MenuItemStyleCollection levelMenuItemStyles;
62 MenuItemStyleCollection levelSelectedStyles;
63 SubMenuStyleCollection levelSubMenuStyles;
64 ITemplate staticItemTemplate;
65 ITemplate dynamicItemTemplate;
67 MenuItemCollection items;
68 MenuItemBindingCollection dataBindings;
69 MenuItem selectedItem;
70 string selectedItemPath;
73 Hashtable _menuItemControls;
74 bool _requiresChildControlsDataBinding;
75 SiteMapNode _currSiteMapNode;
76 int registeredStylesCounter = -1;
77 List<Style> levelSelectedLinkStyles;
78 List<Style> levelMenuItemLinkStyles;
80 Style controlLinkStyle;
81 Style dynamicMenuItemLinkStyle;
82 Style staticMenuItemLinkStyle;
83 Style dynamicSelectedLinkStyle;
84 Style staticSelectedLinkStyle;
85 Style dynamicHoverLinkStyle;
86 Style staticHoverLinkStyle;
88 private static readonly object MenuItemClickEvent = new object();
89 private static readonly object MenuItemDataBoundEvent = new object();
91 public static readonly string MenuItemClickCommandName = "Click";
93 public event MenuEventHandler MenuItemClick {
94 add { Events.AddHandler (MenuItemClickEvent, value); }
95 remove { Events.RemoveHandler (MenuItemClickEvent, value); }
98 public event MenuEventHandler MenuItemDataBound {
99 add { Events.AddHandler (MenuItemDataBoundEvent, value); }
100 remove { Events.RemoveHandler (MenuItemDataBoundEvent, value); }
103 protected virtual void OnMenuItemClick (MenuEventArgs e)
105 if (Events != null) {
106 MenuEventHandler eh = (MenuEventHandler) Events [MenuItemClickEvent];
107 if (eh != null) eh (this, e);
111 protected virtual void OnMenuItemDataBound (MenuEventArgs e)
113 if (Events != null) {
114 MenuEventHandler eh = (MenuEventHandler) Events [MenuItemDataBoundEvent];
115 if (eh != null) eh (this, e);
119 [DefaultValueAttribute (null)]
120 [PersistenceMode (PersistenceMode.InnerProperty)]
121 [EditorAttribute ("System.Web.UI.Design.WebControls.MenuBindingsEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
122 [MergablePropertyAttribute (false)]
123 public MenuItemBindingCollection DataBindings {
125 if (dataBindings == null) {
126 dataBindings = new MenuItemBindingCollection ();
127 if (IsTrackingViewState)
128 ((IStateManager)dataBindings).TrackViewState();
135 [ThemeableAttribute (false)]
136 public int DisappearAfter {
138 object o = ViewState ["DisappearAfter"];
139 if (o != null) return (int)o;
143 ViewState["DisappearAfter"] = value;
147 [ThemeableAttribute (true)]
150 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
151 public string DynamicBottomSeparatorImageUrl {
153 object o = ViewState ["dbsiu"];
154 if (o != null) return (string)o;
158 ViewState["dbsiu"] = value;
162 [DefaultValueAttribute ("")]
163 public string DynamicItemFormatString {
165 object o = ViewState ["DynamicItemFormatString"];
166 if (o != null) return (string)o;
170 ViewState["DynamicItemFormatString"] = value;
176 [WebCategory ("Appearance")]
177 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
178 public string DynamicTopSeparatorImageUrl {
180 object o = ViewState ["dtsiu"];
181 if (o != null) return (string)o;
185 ViewState["dtsiu"] = value;
191 [WebCategory ("Appearance")]
192 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
193 public string StaticBottomSeparatorImageUrl {
195 object o = ViewState ["sbsiu"];
196 if (o != null) return (string)o;
200 ViewState["sbsiu"] = value;
206 [WebCategory ("Appearance")]
207 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
208 public string StaticTopSeparatorImageUrl {
210 object o = ViewState ["stsiu"];
211 if (o != null) return (string)o;
215 ViewState["stsiu"] = value;
219 [DefaultValue (Orientation.Vertical)]
220 public Orientation Orientation {
222 object o = ViewState ["Orientation"];
223 if (o != null) return (Orientation) o;
224 return Orientation.Vertical;
227 ViewState["Orientation"] = value;
232 [ThemeableAttribute (true)]
233 public int StaticDisplayLevels {
235 object o = ViewState ["StaticDisplayLevels"];
236 if (o != null) return (int)o;
240 if (value < 1) throw new ArgumentOutOfRangeException ();
241 ViewState["StaticDisplayLevels"] = value;
245 [DefaultValueAttribute ("")]
246 public string StaticItemFormatString {
248 object o = ViewState ["StaticItemFormatString"];
249 if (o != null) return (string)o;
253 ViewState["StaticItemFormatString"] = value;
257 [DefaultValue (typeof (Unit), "16px")]
258 [ThemeableAttribute (true)]
259 public Unit StaticSubMenuIndent {
261 object o = ViewState ["StaticSubMenuIndent"];
262 if (o != null) return (Unit)o;
263 return new Unit (16);
266 ViewState["StaticSubMenuIndent"] = value;
270 [ThemeableAttribute (true)]
272 public int MaximumDynamicDisplayLevels {
274 object o = ViewState ["MaximumDynamicDisplayLevels"];
275 if (o != null) return (int)o;
279 if (value < 0) throw new ArgumentOutOfRangeException ();
280 ViewState["MaximumDynamicDisplayLevels"] = value;
285 public int DynamicVerticalOffset {
287 object o = ViewState ["DynamicVerticalOffset"];
288 if (o != null) return (int)o;
292 ViewState["DynamicVerticalOffset"] = value;
297 public int DynamicHorizontalOffset {
299 object o = ViewState ["DynamicHorizontalOffset"];
300 if (o != null) return (int)o;
304 ViewState["DynamicHorizontalOffset"] = value;
308 [DefaultValue (true)]
309 public bool DynamicEnableDefaultPopOutImage {
311 object o = ViewState ["dedpoi"];
312 if (o != null) return (bool)o;
316 ViewState["dedpoi"] = value;
320 [DefaultValue (true)]
321 public bool StaticEnableDefaultPopOutImage {
323 object o = ViewState ["sedpoi"];
324 if (o != null) return (bool)o;
328 ViewState["sedpoi"] = value;
332 [DefaultValueAttribute (null)]
333 [PersistenceMode (PersistenceMode.InnerProperty)]
334 [Editor ("System.Web.UI.Design.MenuItemCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
335 [MergablePropertyAttribute (false)]
336 public MenuItemCollection Items {
339 items = new MenuItemCollection (this);
340 if (IsTrackingViewState)
341 ((IStateManager)items).TrackViewState();
348 public char PathSeparator {
350 object o = ViewState ["PathSeparator"];
351 if(o != null) return (char)o;
355 ViewState ["PathSeparator"] = value;
359 [DefaultValue (false)]
360 public bool ItemWrap {
362 object o = ViewState ["ItemWrap"];
363 if(o != null) return (bool)o;
367 ViewState ["ItemWrap"] = value;
371 private Style PopOutBoxStyle {
373 if (popOutBoxStyle == null) {
374 popOutBoxStyle = new Style ();
375 popOutBoxStyle.BackColor = Color.White;
377 return popOutBoxStyle;
381 private Style ControlLinkStyle {
383 if (controlLinkStyle == null) {
384 controlLinkStyle = new Style ();
385 controlLinkStyle.AlwaysRenderTextDecoration = true;
387 return controlLinkStyle;
391 private Style DynamicMenuItemLinkStyle {
393 if (dynamicMenuItemLinkStyle == null) {
394 dynamicMenuItemLinkStyle = new Style ();
396 return dynamicMenuItemLinkStyle;
400 private Style StaticMenuItemLinkStyle {
402 if (staticMenuItemLinkStyle == null) {
403 staticMenuItemLinkStyle = new Style ();
405 return staticMenuItemLinkStyle;
409 private Style DynamicSelectedLinkStyle {
411 if (dynamicSelectedLinkStyle == null) {
412 dynamicSelectedLinkStyle = new Style ();
414 return dynamicSelectedLinkStyle;
418 private Style StaticSelectedLinkStyle {
420 if (staticSelectedLinkStyle == null) {
421 staticSelectedLinkStyle = new Style ();
423 return staticSelectedLinkStyle;
427 private Style DynamicHoverLinkStyle {
429 if (dynamicHoverLinkStyle == null) {
430 dynamicHoverLinkStyle = new Style ();
432 return dynamicHoverLinkStyle;
436 private Style StaticHoverLinkStyle {
438 if (staticHoverLinkStyle == null) {
439 staticHoverLinkStyle = new Style ();
441 return staticHoverLinkStyle;
445 [PersistenceMode (PersistenceMode.InnerProperty)]
446 [NotifyParentProperty (true)]
447 [DefaultValue (null)]
448 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
449 public MenuItemStyle DynamicMenuItemStyle {
451 if (dynamicMenuItemStyle == null) {
452 dynamicMenuItemStyle = new MenuItemStyle ();
453 if (IsTrackingViewState)
454 dynamicMenuItemStyle.TrackViewState();
456 return dynamicMenuItemStyle;
460 [PersistenceMode (PersistenceMode.InnerProperty)]
461 [NotifyParentProperty (true)]
462 [DefaultValue (null)]
463 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
464 public MenuItemStyle DynamicSelectedStyle {
466 if (dynamicSelectedStyle == null) {
467 dynamicSelectedStyle = new MenuItemStyle ();
468 if (IsTrackingViewState)
469 dynamicSelectedStyle.TrackViewState();
471 return dynamicSelectedStyle;
475 [PersistenceMode (PersistenceMode.InnerProperty)]
476 [NotifyParentProperty (true)]
477 [DefaultValue (null)]
478 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
479 public SubMenuStyle DynamicMenuStyle {
481 if (dynamicMenuStyle == null) {
482 dynamicMenuStyle = new SubMenuStyle ();
483 if (IsTrackingViewState)
484 dynamicMenuStyle.TrackViewState();
486 return dynamicMenuStyle;
490 [PersistenceMode (PersistenceMode.InnerProperty)]
491 [NotifyParentProperty (true)]
492 [DefaultValue (null)]
493 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
494 public MenuItemStyle StaticMenuItemStyle {
496 if (staticMenuItemStyle == null) {
497 staticMenuItemStyle = new MenuItemStyle ();
498 if (IsTrackingViewState)
499 staticMenuItemStyle.TrackViewState();
501 return staticMenuItemStyle;
505 [PersistenceMode (PersistenceMode.InnerProperty)]
506 [NotifyParentProperty (true)]
507 [DefaultValue (null)]
508 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
509 public MenuItemStyle StaticSelectedStyle {
511 if (staticSelectedStyle == null) {
512 staticSelectedStyle = new MenuItemStyle ();
513 if (IsTrackingViewState)
514 staticSelectedStyle.TrackViewState();
516 return staticSelectedStyle;
520 [PersistenceMode (PersistenceMode.InnerProperty)]
521 [NotifyParentProperty (true)]
522 [DefaultValue (null)]
523 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
524 public SubMenuStyle StaticMenuStyle {
526 if (staticMenuStyle == null) {
527 staticMenuStyle = new SubMenuStyle ();
528 if (IsTrackingViewState)
529 staticMenuStyle.TrackViewState();
531 return staticMenuStyle;
535 [DefaultValue (null)]
536 [PersistenceMode (PersistenceMode.InnerProperty)]
537 [Editor ("System.Web.UI.Design.WebControls.MenuItemStyleCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
538 public MenuItemStyleCollection LevelMenuItemStyles {
540 if (levelMenuItemStyles == null) {
541 levelMenuItemStyles = new MenuItemStyleCollection ();
542 if (IsTrackingViewState)
543 ((IStateManager)levelMenuItemStyles).TrackViewState();
545 return levelMenuItemStyles;
549 [DefaultValue (null)]
550 [PersistenceMode (PersistenceMode.InnerProperty)]
551 [Editor ("System.Web.UI.Design.WebControls.MenuItemStyleCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
552 public MenuItemStyleCollection LevelSelectedStyles {
554 if (levelSelectedStyles == null) {
555 levelSelectedStyles = new MenuItemStyleCollection ();
556 if (IsTrackingViewState)
557 ((IStateManager)levelSelectedStyles).TrackViewState();
559 return levelSelectedStyles;
563 [DefaultValue (null)]
564 [PersistenceMode (PersistenceMode.InnerProperty)]
565 [Editor ("System.Web.UI.Design.WebControls.SubMenuStyleCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
566 public SubMenuStyleCollection LevelSubMenuStyles {
568 if (levelSubMenuStyles == null) {
569 levelSubMenuStyles = new SubMenuStyleCollection ();
570 if (IsTrackingViewState)
571 ((IStateManager)levelSubMenuStyles).TrackViewState();
573 return levelSubMenuStyles;
577 [PersistenceMode (PersistenceMode.InnerProperty)]
578 [NotifyParentProperty (true)]
579 [DefaultValue (null)]
580 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
581 public Style DynamicHoverStyle {
583 if (dynamicHoverStyle == null) {
584 dynamicHoverStyle = new Style ();
585 if (IsTrackingViewState)
586 dynamicHoverStyle.TrackViewState();
588 return dynamicHoverStyle;
592 [PersistenceMode (PersistenceMode.InnerProperty)]
593 [NotifyParentProperty (true)]
594 [DefaultValue (null)]
595 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
596 public Style StaticHoverStyle {
598 if (staticHoverStyle == null) {
599 staticHoverStyle = new Style ();
600 if (IsTrackingViewState)
601 staticHoverStyle.TrackViewState();
603 return staticHoverStyle;
609 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
610 public string ScrollDownImageUrl {
612 object o = ViewState ["sdiu"];
613 if (o != null) return (string)o;
617 ViewState["sdiu"] = value;
623 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
624 public string ScrollUpImageUrl {
626 object o = ViewState ["suiu"];
627 if (o != null) return (string)o;
631 ViewState["suiu"] = value;
636 public string ScrollDownText {
638 object o = ViewState ["ScrollDownText"];
639 if (o != null) return (string) o;
640 return Locale.GetText ("Scroll down");
643 ViewState["ScrollDownText"] = value;
648 public string ScrollUpText {
650 object o = ViewState ["ScrollUpText"];
651 if (o != null) return (string) o;
652 return Locale.GetText ("Scroll up");
655 ViewState["ScrollUpText"] = value;
659 public string DynamicPopOutImageTextFormatString
663 object o = ViewState ["dpoitf"];
664 if (o != null) return (string) o;
665 return Locale.GetText ("Expand {0}");
669 ViewState ["dpoitf"] = value;
676 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
677 public string DynamicPopOutImageUrl {
679 object o = ViewState ["dpoiu"];
680 if (o != null) return (string)o;
684 ViewState["dpoiu"] = value;
688 public string StaticPopOutImageTextFormatString
692 object o = ViewState ["spoitf"];
693 if (o != null) return (string) o;
694 return Locale.GetText ("Expand {0}");
698 ViewState ["spoitf"] = value;
705 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
706 public string StaticPopOutImageUrl {
708 object o = ViewState ["spoiu"];
709 if (o != null) return (string)o;
713 ViewState["spoiu"] = value;
718 public string Target {
720 object o = ViewState ["Target"];
721 if (o != null) return (string) o;
725 ViewState["Target"] = value;
729 [DefaultValue (null)]
730 [TemplateContainer (typeof(MenuItemTemplateContainer), BindingDirection.OneWay)]
731 [PersistenceMode (PersistenceMode.InnerProperty)]
733 public ITemplate StaticItemTemplate {
734 get { return staticItemTemplate; }
735 set { staticItemTemplate = value; }
738 [DefaultValue (null)]
739 [TemplateContainer (typeof(MenuItemTemplateContainer), BindingDirection.OneWay)]
740 [PersistenceMode (PersistenceMode.InnerProperty)]
742 public ITemplate DynamicItemTemplate {
743 get { return dynamicItemTemplate; }
744 set { dynamicItemTemplate = value; }
748 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
749 public MenuItem SelectedItem {
751 if (selectedItem == null && selectedItemPath != null) {
752 selectedItem = FindItemByPos (selectedItemPath);
761 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
762 public string SelectedValue {
763 get { return selectedItem != null ? selectedItem.Value : ""; }
767 public string SkipLinkText
770 object o = ViewState ["SkipLinkText"];
773 return "Skip Navigation Links";
776 ViewState ["SkipLinkText"] = value;
781 internal void SetSelectedItem (MenuItem item)
783 if (selectedItem == item) return;
785 selectedItemPath = item.Path;
788 public MenuItem FindItem (string valuePath)
790 if (valuePath == null) throw new ArgumentNullException ("valuePath");
791 string[] path = valuePath.Split (PathSeparator);
793 MenuItemCollection col = Items;
794 bool foundBranch = true;
795 while (col.Count > 0 && foundBranch) {
797 foreach (MenuItem item in col) {
798 if (item.Value == path [n]) {
799 if (++n == path.Length) return item;
800 col = item.ChildItems;
809 string GetBindingKey (string dataMember, int depth)
811 return dataMember + " " + depth;
814 internal MenuItemBinding FindBindingForItem (string type, int depth)
816 if (bindings == null) return null;
818 MenuItemBinding bin = (MenuItemBinding) bindings [GetBindingKey (type, depth)];
819 if (bin != null) return bin;
821 bin = (MenuItemBinding) bindings [GetBindingKey (type, -1)];
822 if (bin != null) return bin;
824 bin = (MenuItemBinding) bindings [GetBindingKey ("", depth)];
825 if (bin != null) return bin;
827 bin = (MenuItemBinding) bindings [GetBindingKey ("", -1)];
831 protected internal override void PerformDataBinding ()
833 base.PerformDataBinding ();
835 // Do not attempt to bind data if there is no
837 if (!IsBoundUsingDataSourceID && (DataSource == null)) {
838 EnsureChildControlsDataBound ();
842 InitializeDataBindings ();
844 HierarchicalDataSourceView data = GetData ("");
847 throw new InvalidOperationException ("No view returned by data source control.");
850 IHierarchicalEnumerable e = data.Select ();
851 FillBoundChildrenRecursive (e, Items);
853 CreateChildControlsForItems ();
854 ChildControlsCreated = true;
856 EnsureChildControlsDataBound ();
859 private void FillBoundChildrenRecursive (IHierarchicalEnumerable hEnumerable, MenuItemCollection itemCollection)
861 if (hEnumerable == null)
863 foreach (object obj in hEnumerable) {
864 IHierarchyData hdata = hEnumerable.GetHierarchyData (obj);
865 MenuItem item = new MenuItem ();
866 itemCollection.Add (item);
869 SiteMapNode siteMapNode = hdata as SiteMapNode;
870 if (siteMapNode != null) {
871 if (_currSiteMapNode == null)
872 _currSiteMapNode = siteMapNode.Provider.CurrentNode;
873 if (siteMapNode == _currSiteMapNode)
874 item.Selected = true;
877 OnMenuItemDataBound (new MenuEventArgs (item));
879 if (hdata == null || !hdata.HasChildren)
882 IHierarchicalEnumerable e = hdata.GetChildren ();
883 FillBoundChildrenRecursive (e, item.ChildItems);
887 protected void SetItemDataBound (MenuItem node, bool dataBound)
889 node.SetDataBound (dataBound);
892 protected void SetItemDataPath (MenuItem node, string dataPath)
894 node.SetDataPath (dataPath);
897 protected void SetItemDataItem (MenuItem node, object dataItem)
899 node.SetDataItem (dataItem);
902 protected internal virtual void RaisePostBackEvent (string eventArgument)
907 EnsureChildControls();
908 MenuItem item = FindItemByPos (eventArgument);
909 if (item == null) return;
910 item.Selected = true;
911 OnMenuItemClick (new MenuEventArgs (item));
914 void IPostBackEventHandler.RaisePostBackEvent (string eventArgument)
916 RaisePostBackEvent (eventArgument);
919 MenuItem FindItemByPos (string path)
921 string[] indexes = path.Split ('_');
922 MenuItem item = null;
924 foreach (string index in indexes) {
925 int i = int.Parse (index);
927 if (i >= Items.Count) return null;
930 if (i >= item.ChildItems.Count) return null;
931 item = item.ChildItems [i];
937 protected override HtmlTextWriterTag TagKey {
938 get { return HtmlTextWriterTag.Table; }
941 protected override void TrackViewState()
945 base.TrackViewState();
946 if (dataBindings != null) {
947 ((IStateManager)dataBindings).TrackViewState ();
950 ((IStateManager)items).TrackViewState();
952 if (dynamicMenuItemStyle != null)
953 dynamicMenuItemStyle.TrackViewState ();
954 if (dynamicMenuStyle != null)
955 dynamicMenuStyle.TrackViewState ();
956 if (levelMenuItemStyles != null && levelMenuItemStyles.Count > 0)
957 ((IStateManager)levelMenuItemStyles).TrackViewState();
958 if (levelSelectedStyles != null && levelMenuItemStyles.Count > 0)
959 ((IStateManager)levelSelectedStyles).TrackViewState();
960 if (levelSubMenuStyles != null && levelSubMenuStyles.Count > 0)
961 ((IStateManager)levelSubMenuStyles).TrackViewState();
962 if (dynamicSelectedStyle != null)
963 dynamicSelectedStyle.TrackViewState();
964 if (staticMenuItemStyle != null)
965 staticMenuItemStyle.TrackViewState ();
966 if (staticMenuStyle != null)
967 staticMenuStyle.TrackViewState ();
968 if (staticSelectedStyle != null)
969 staticSelectedStyle.TrackViewState();
970 if (staticHoverStyle != null)
971 staticHoverStyle.TrackViewState();
972 if (dynamicHoverStyle != null)
973 dynamicHoverStyle.TrackViewState();
976 protected override object SaveViewState()
978 object[] states = new object [14];
979 states[0] = base.SaveViewState ();
980 states[1] = dataBindings == null ? null : ((IStateManager)dataBindings).SaveViewState();
981 states[2] = items == null ? null : ((IStateManager)items).SaveViewState();
982 states[3] = dynamicMenuItemStyle == null ? null : dynamicMenuItemStyle.SaveViewState();
983 states[4] = dynamicMenuStyle == null ? null : dynamicMenuStyle.SaveViewState();
984 states[5] = levelMenuItemStyles == null ? null : ((IStateManager)levelMenuItemStyles).SaveViewState();
985 states[6] = levelSelectedStyles == null ? null : ((IStateManager)levelSelectedStyles).SaveViewState();
986 states[7] = dynamicSelectedStyle == null ? null : dynamicSelectedStyle.SaveViewState();
987 states[8] = (staticMenuItemStyle == null ? null : staticMenuItemStyle.SaveViewState());
988 states[9] = staticMenuStyle == null ? null : staticMenuStyle.SaveViewState();
989 states[10] = staticSelectedStyle == null ? null : staticSelectedStyle.SaveViewState();
990 states[11] = staticHoverStyle == null ? null : staticHoverStyle.SaveViewState();
991 states[12] = dynamicHoverStyle == null ? null : dynamicHoverStyle.SaveViewState();
992 states[13] = levelSubMenuStyles == null ? null : ((IStateManager)levelSubMenuStyles).SaveViewState();
994 for (int i = states.Length - 1; i >= 0; i--) {
995 if (states [i] != null)
1002 protected override void LoadViewState (object savedState)
1004 if (savedState == null)
1007 object [] states = (object []) savedState;
1008 base.LoadViewState (states[0]);
1010 if (states[1] != null)
1011 ((IStateManager)DataBindings).LoadViewState(states[1]);
1012 if (states[2] != null)
1013 ((IStateManager)Items).LoadViewState(states[2]);
1014 if (states[3] != null)
1015 DynamicMenuItemStyle.LoadViewState (states[3]);
1016 if (states[4] != null)
1017 DynamicMenuStyle.LoadViewState (states[4]);
1018 if (states[5] != null)
1019 ((IStateManager)LevelMenuItemStyles).LoadViewState(states[5]);
1020 if (states[6] != null)
1021 ((IStateManager)LevelSelectedStyles).LoadViewState(states[6]);
1022 if (states[7] != null)
1023 DynamicSelectedStyle.LoadViewState (states[7]);
1024 if (states[8] != null)
1025 StaticMenuItemStyle.LoadViewState (states[8]);
1026 if (states[9] != null)
1027 StaticMenuStyle.LoadViewState (states[9]);
1028 if (states[10] != null)
1029 StaticSelectedStyle.LoadViewState (states[10]);
1030 if (states[11] != null)
1031 StaticHoverStyle.LoadViewState (states[11]);
1032 if (states[12] != null)
1033 DynamicHoverStyle.LoadViewState (states[12]);
1034 if (states[13] != null)
1035 ((IStateManager)LevelSubMenuStyles).LoadViewState(states[13]);
1038 protected internal override void OnInit (EventArgs e)
1040 Page.RegisterRequiresControlState (this);
1044 protected internal override void LoadControlState (object ob)
1046 if (ob == null) return;
1047 object[] state = (object[]) ob;
1048 base.LoadControlState (state[0]);
1049 selectedItemPath = state[1] as string;
1052 protected internal override object SaveControlState ()
1054 object bstate = base.SaveControlState ();
1055 object mstate = selectedItemPath;
1057 if (bstate != null || mstate != null)
1058 return new object[] { bstate, mstate };
1063 protected internal override void CreateChildControls ()
1065 if (!IsBoundUsingDataSourceID && (DataSource == null)) {
1066 CreateChildControlsForItems ();
1073 private void CreateChildControlsForItems () {
1075 // Check for HasChildViewState to avoid unnecessary calls to ClearChildViewState.
1076 if (HasChildViewState)
1077 ClearChildViewState ();
1078 _menuItemControls = new Hashtable ();
1079 CreateChildControlsForItems (Items);
1080 _requiresChildControlsDataBinding = true;
1083 private void CreateChildControlsForItems (MenuItemCollection items ) {
1084 foreach (MenuItem item in items) {
1085 bool isDynamicItem = IsDynamicItem (item);
1086 if (isDynamicItem && dynamicItemTemplate != null) {
1087 MenuItemTemplateContainer cter = new MenuItemTemplateContainer (item.Index, item);
1088 dynamicItemTemplate.InstantiateIn (cter);
1089 _menuItemControls [item] = cter;
1090 Controls.Add (cter);
1092 else if (!isDynamicItem && staticItemTemplate != null) {
1093 MenuItemTemplateContainer cter = new MenuItemTemplateContainer (item.Index, item);
1094 staticItemTemplate.InstantiateIn (cter);
1095 _menuItemControls [item] = cter;
1096 Controls.Add (cter);
1098 if (item.HasChildData)
1099 CreateChildControlsForItems (item.ChildItems);
1103 protected override void EnsureDataBound ()
1105 base.EnsureDataBound ();
1107 EnsureChildControlsDataBound ();
1110 private void EnsureChildControlsDataBound () {
1111 if (!_requiresChildControlsDataBinding)
1113 DataBindChildren ();
1114 _requiresChildControlsDataBinding = false;
1117 [MonoTODO ("Not implemented")]
1118 protected override IDictionary GetDesignModeState ()
1120 throw new NotImplementedException ();
1123 [MonoTODO ("Not implemented")]
1124 protected override void SetDesignModeState (IDictionary data)
1126 throw new NotImplementedException ();
1129 public override ControlCollection Controls {
1130 get { return base.Controls; }
1133 public sealed override void DataBind ()
1138 protected override bool OnBubbleEvent (object source, EventArgs args)
1140 if (!(args is CommandEventArgs))
1143 MenuEventArgs menuArgs = args as MenuEventArgs;
1144 if (menuArgs != null && string.Equals (menuArgs.CommandName, MenuItemClickCommandName))
1145 OnMenuItemClick (menuArgs);
1149 protected override void OnDataBinding (EventArgs e)
1151 EnsureChildControls ();
1152 base.OnDataBinding (e);
1155 const string onPreRenderScript = "var {0} = new Object ();\n{0}.webForm = {1};\n{0}.disappearAfter = {2};\n{0}.vertical = {3};";
1157 protected internal override void OnPreRender (EventArgs e)
1159 base.OnPreRender (e);
1161 if (!Page.ClientScript.IsClientScriptIncludeRegistered (typeof(Menu), "Menu.js")) {
1162 string url = Page.ClientScript.GetWebResourceUrl (typeof(Menu), "Menu.js");
1163 Page.ClientScript.RegisterClientScriptInclude (typeof(Menu), "Menu.js", url);
1166 string cmenu = ClientID + "_data";
1167 string script = String.Format (onPreRenderScript,
1169 Page.IsMultiForm ? Page.theForm : "window",
1170 ClientScriptManager.GetScriptLiteral (DisappearAfter),
1171 ClientScriptManager.GetScriptLiteral (Orientation == Orientation.Vertical));
1173 if (DynamicHorizontalOffset != 0)
1174 script += String.Concat (cmenu, ".dho = ", ClientScriptManager.GetScriptLiteral (DynamicHorizontalOffset), ";\n");
1175 if (DynamicVerticalOffset != 0)
1176 script += String.Concat (cmenu, ".dvo = ", ClientScriptManager.GetScriptLiteral (DynamicVerticalOffset), ";\n");
1178 // The order in which styles are defined matters when more than one class
1179 // is assigned to an element
1180 RegisterStyle (PopOutBoxStyle);
1181 RegisterStyle (ControlStyle, ControlLinkStyle);
1183 if (staticMenuItemStyle != null)
1184 RegisterStyle (StaticMenuItemStyle, StaticMenuItemLinkStyle);
1186 if (staticMenuStyle != null)
1187 RegisterStyle (StaticMenuStyle);
1189 if (dynamicMenuItemStyle != null)
1190 RegisterStyle (DynamicMenuItemStyle, DynamicMenuItemLinkStyle);
1192 if (dynamicMenuStyle != null)
1193 RegisterStyle (DynamicMenuStyle);
1195 if (levelMenuItemStyles != null && levelMenuItemStyles.Count > 0) {
1196 levelMenuItemLinkStyles = new List<Style> (levelMenuItemStyles.Count);
1197 foreach (Style style in levelMenuItemStyles) {
1198 Style linkStyle = new Style ();
1199 levelMenuItemLinkStyles.Add (linkStyle);
1200 RegisterStyle (style, linkStyle);
1204 if (levelSubMenuStyles != null)
1205 foreach (Style style in levelSubMenuStyles)
1206 RegisterStyle (style);
1208 if (staticSelectedStyle != null)
1209 RegisterStyle (staticSelectedStyle, StaticSelectedLinkStyle);
1211 if (dynamicSelectedStyle != null)
1212 RegisterStyle (dynamicSelectedStyle, DynamicSelectedLinkStyle);
1214 if (levelSelectedStyles != null && levelSelectedStyles.Count > 0) {
1215 levelSelectedLinkStyles = new List<Style> (levelSelectedStyles.Count);
1216 foreach (Style style in levelSelectedStyles) {
1217 Style linkStyle = new Style ();
1218 levelSelectedLinkStyles.Add (linkStyle);
1219 RegisterStyle (style, linkStyle);
1223 if (staticHoverStyle != null) {
1224 if (Page.Header == null)
1225 throw new InvalidOperationException ("Using Menu.StaticHoverStyle requires Page.Header to be non-null (e.g. <head runat=\"server\" />).");
1226 RegisterStyle (staticHoverStyle, StaticHoverLinkStyle);
1227 script += string.Concat (cmenu, ".staticHover = ", ClientScriptManager.GetScriptLiteral (staticHoverStyle.RegisteredCssClass), ";\n");
1228 script += string.Concat (cmenu, ".staticLinkHover = ", ClientScriptManager.GetScriptLiteral (StaticHoverLinkStyle.RegisteredCssClass), ";\n");
1231 if (dynamicHoverStyle != null) {
1232 if (Page.Header == null)
1233 throw new InvalidOperationException ("Using Menu.DynamicHoverStyle requires Page.Header to be non-null (e.g. <head runat=\"server\" />).");
1234 RegisterStyle (dynamicHoverStyle, DynamicHoverLinkStyle);
1235 script += string.Concat (cmenu, ".dynamicHover = ", ClientScriptManager.GetScriptLiteral (dynamicHoverStyle.RegisteredCssClass), ";\n");
1236 script += string.Concat (cmenu, ".dynamicLinkHover = ", ClientScriptManager.GetScriptLiteral (DynamicHoverLinkStyle.RegisteredCssClass), ";\n");
1239 Page.ClientScript.RegisterWebFormClientScript ();
1240 Page.ClientScript.RegisterStartupScript (typeof(Menu), ClientID, script, true);
1244 void InitializeDataBindings () {
1245 if (dataBindings != null && dataBindings.Count > 0) {
1246 bindings = new Hashtable ();
1247 foreach (MenuItemBinding bin in dataBindings) {
1248 string key = GetBindingKey (bin.DataMember, bin.Depth);
1249 bindings [key] = bin;
1256 string IncrementStyleClassName () {
1257 registeredStylesCounter++;
1258 return ClientID + "_" + registeredStylesCounter;
1261 void RegisterStyle (Style baseStyle, Style linkStyle) {
1262 linkStyle.CopyTextStylesFrom (baseStyle);
1263 linkStyle.BorderStyle = BorderStyle.None;
1264 RegisterStyle (linkStyle);
1265 RegisterStyle (baseStyle);
1268 void RegisterStyle (Style baseStyle)
1270 if (Page.Header == null)
1272 string className = IncrementStyleClassName ();
1273 baseStyle.SetRegisteredCssClass (className);
1274 Page.Header.StyleSheet.CreateStyleRule (baseStyle, this, "." + className);
1277 protected internal override void Render (HtmlTextWriter writer)
1279 if (Items.Count > 0)
1280 base.Render (writer);
1283 protected override void AddAttributesToRender (HtmlTextWriter writer)
1285 writer.AddAttribute ("cellpadding", "0", false);
1286 writer.AddAttribute ("cellspacing", "0", false);
1287 writer.AddAttribute ("border", "0", false);
1288 if (Page.Header != null) {
1289 // styles are registered
1290 if (staticMenuStyle != null) {
1291 AddCssClass (ControlStyle, staticMenuStyle.CssClass);
1292 AddCssClass (ControlStyle, staticMenuStyle.RegisteredCssClass);
1294 if (levelSubMenuStyles != null && levelSubMenuStyles.Count > 0) {
1295 AddCssClass (ControlStyle, levelSubMenuStyles [0].CssClass);
1296 AddCssClass (ControlStyle, levelSubMenuStyles [0].RegisteredCssClass);
1300 // styles are not registered
1301 if (staticMenuStyle != null){
1302 ControlStyle.CopyFrom (staticMenuStyle);
1304 if (levelSubMenuStyles != null && levelSubMenuStyles.Count > 0) {
1305 ControlStyle.CopyFrom (levelSubMenuStyles [0]);
1308 base.AddAttributesToRender (writer);
1311 void AddCssClass (Style style, string cssClass) {
1312 style.AddCssClass (cssClass);
1315 public override void RenderBeginTag (HtmlTextWriter writer)
1317 if (SkipLinkText != "") {
1318 System.Web.UI.HtmlControls.HtmlAnchor anchor = new System.Web.UI.HtmlControls.HtmlAnchor ();
1319 anchor.HRef = "#" + ClientID + "_SkipLink";
1321 Image img = new Image ();
1322 ClientScriptManager csm = new ClientScriptManager (null);
1323 img.ImageUrl = csm.GetWebResourceUrl (typeof (SiteMapPath), "transparent.gif");
1324 img.Attributes.Add ("height", "0");
1325 img.Attributes.Add ("width", "0");
1326 img.AlternateText = SkipLinkText;
1328 anchor.Controls.Add (img);
1329 anchor.Render (writer);
1331 base.RenderBeginTag (writer);
1334 public override void RenderEndTag (HtmlTextWriter writer)
1336 base.RenderEndTag (writer);
1338 if (StaticDisplayLevels == 1 && MaximumDynamicDisplayLevels > 0)
1339 RenderDynamicMenu (writer, Items);
1341 if (SkipLinkText != "") {
1342 System.Web.UI.HtmlControls.HtmlAnchor anchor = new System.Web.UI.HtmlControls.HtmlAnchor ();
1343 anchor.ID = ClientID + "_SkipLink";
1344 anchor.Render (writer);
1348 protected internal override void RenderContents (HtmlTextWriter writer)
1350 RenderMenuBody (writer, Items, Orientation == Orientation.Vertical, false, false);
1353 void RenderDynamicMenu (HtmlTextWriter writer, MenuItemCollection items) {
1354 for (int n = 0; n < items.Count; n++) {
1355 if (DisplayChildren (items [n])) {
1356 RenderDynamicMenu (writer, items [n]);
1357 RenderDynamicMenu (writer, items [n].ChildItems);
1362 MenuRenderHtmlTemplate _dynamicTemplate;
1363 MenuRenderHtmlTemplate GetDynamicMenuTemplate (MenuItem item)
1365 if (_dynamicTemplate != null)
1366 return _dynamicTemplate;
1368 _dynamicTemplate = new MenuRenderHtmlTemplate ();
1369 HtmlTextWriter writer = _dynamicTemplate.GetMenuTemplateWriter ();
1371 if (Page.Header != null) {
1372 writer.AddAttribute (HtmlTextWriterAttribute.Class, MenuRenderHtmlTemplate.GetMarker (0));
1375 writer.AddAttribute (HtmlTextWriterAttribute.Style, MenuRenderHtmlTemplate.GetMarker (0));
1378 writer.AddStyleAttribute ("visibility", "hidden");
1379 writer.AddStyleAttribute ("position", "absolute");
1380 writer.AddStyleAttribute ("z-index", "1");
1381 writer.AddStyleAttribute ("left", "0px");
1382 writer.AddStyleAttribute ("top", "0px");
1383 writer.AddAttribute ("id", MenuRenderHtmlTemplate.GetMarker (1));
1384 writer.RenderBeginTag (HtmlTextWriterTag.Div);
1387 writer.AddAttribute ("id", MenuRenderHtmlTemplate.GetMarker (2));
1388 writer.AddStyleAttribute ("display", "block");
1389 writer.AddStyleAttribute ("text-align", "center");
1390 writer.AddAttribute ("onmouseover", string.Concat ("Menu_OverScrollBtn ('", ClientID, "','", MenuRenderHtmlTemplate.GetMarker (3), "','u')"));
1391 writer.AddAttribute ("onmouseout", string.Concat ("Menu_OutScrollBtn ('", ClientID, "','", MenuRenderHtmlTemplate.GetMarker (4), "','u')"));
1392 writer.RenderBeginTag (HtmlTextWriterTag.Div);
1394 writer.AddAttribute ("src", MenuRenderHtmlTemplate.GetMarker (5)); //src
1395 writer.AddAttribute ("alt", MenuRenderHtmlTemplate.GetMarker (6)); //ScrollUpText
1396 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1397 writer.RenderEndTag (); // IMG
1399 writer.RenderEndTag (); // DIV scroll button
1401 writer.AddAttribute ("id", MenuRenderHtmlTemplate.GetMarker (7));
1402 writer.RenderBeginTag (HtmlTextWriterTag.Div);
1403 writer.AddAttribute ("id", MenuRenderHtmlTemplate.GetMarker (8));
1404 writer.RenderBeginTag (HtmlTextWriterTag.Div);
1406 // call of RenderMenu
1407 writer.Write (MenuRenderHtmlTemplate.GetMarker (9));
1409 writer.RenderEndTag (); // DIV Content
1410 writer.RenderEndTag (); // DIV Scroll container
1413 writer.AddAttribute ("id", MenuRenderHtmlTemplate.GetMarker (0));
1414 writer.AddStyleAttribute ("display", "block");
1415 writer.AddStyleAttribute ("text-align", "center");
1416 writer.AddAttribute ("onmouseover", string.Concat ("Menu_OverScrollBtn ('", ClientID, "','", MenuRenderHtmlTemplate.GetMarker (1), "','d')"));
1417 writer.AddAttribute ("onmouseout", string.Concat ("Menu_OutScrollBtn ('", ClientID, "','", MenuRenderHtmlTemplate.GetMarker (2), "','d')"));
1418 writer.RenderBeginTag (HtmlTextWriterTag.Div);
1420 writer.AddAttribute ("src", MenuRenderHtmlTemplate.GetMarker (3)); //src
1421 writer.AddAttribute ("alt", MenuRenderHtmlTemplate.GetMarker (4)); //ScrollDownText
1422 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1423 writer.RenderEndTag (); // IMG
1425 writer.RenderEndTag (); // DIV scroll button
1427 writer.RenderEndTag (); // DIV menu
1429 _dynamicTemplate.Parse ();
1430 return _dynamicTemplate;
1433 void RenderDynamicMenu (HtmlTextWriter writer, MenuItem item)
1435 _dynamicTemplate = GetDynamicMenuTemplate (item);
1437 string idPrefix = ClientID + "_" + item.Path;
1438 string [] param = new string [9];
1439 param [0] = GetCssMenuStyle (true, item.Depth + 1);
1440 param [1] = idPrefix + "s";
1441 param [2] = idPrefix + "cu";
1442 param [3] = item.Path;
1443 param [4] = item.Path;
1444 param [5] = ScrollUpImageUrl != "" ? ScrollUpImageUrl : Page.ClientScript.GetWebResourceUrl (typeof (Menu), "arrow_up.gif");
1445 param [6] = ScrollUpText;
1446 param [7] = idPrefix + "cb";
1447 param [8] = idPrefix + "cc";
1449 _dynamicTemplate.RenderTemplate (writer, param, 0, param.Length);
1451 RenderMenu (writer, item.ChildItems, true, true, item.Depth + 1, false);
1453 string [] param2 = new string [5];
1454 param2 [0] = idPrefix + "cd";
1455 param2 [1] = item.Path;
1456 param2 [2] = item.Path;
1457 param2 [3] = ScrollDownImageUrl != "" ? ScrollDownImageUrl : Page.ClientScript.GetWebResourceUrl (typeof (Menu), "arrow_down.gif");
1458 param2 [4] = ScrollDownText;
1460 _dynamicTemplate.RenderTemplate (writer, param2, param.Length + 1, param2.Length);
1464 string GetCssMenuStyle (bool dynamic, int menuLevel)
1466 if (Page.Header != null) {
1467 // styles are registered
1468 StringBuilder sb = new StringBuilder ();
1470 if (!dynamic && staticMenuStyle != null) {
1471 sb.Append (staticMenuStyle.CssClass);
1473 sb.Append (staticMenuStyle.RegisteredCssClass);
1475 if (dynamic && dynamicMenuStyle != null) {
1476 sb.Append (PopOutBoxStyle.RegisteredCssClass);
1478 sb.Append (dynamicMenuStyle.CssClass);
1480 sb.Append (dynamicMenuStyle.RegisteredCssClass);
1482 if (levelSubMenuStyles != null && levelSubMenuStyles.Count > menuLevel) {
1483 sb.Append (levelSubMenuStyles [menuLevel].CssClass);
1485 sb.Append (levelSubMenuStyles [menuLevel].RegisteredCssClass);
1487 return sb.ToString ();
1490 // styles are not registered
1491 SubMenuStyle style = new SubMenuStyle ();
1493 if (!dynamic && staticMenuStyle != null) {
1494 style.CopyFrom (staticMenuStyle);
1496 if (dynamic && dynamicMenuStyle != null) {
1497 style.CopyFrom (PopOutBoxStyle);
1498 style.CopyFrom (dynamicMenuStyle);
1500 if (levelSubMenuStyles != null && levelSubMenuStyles.Count > menuLevel) {
1501 style.CopyFrom (levelSubMenuStyles [menuLevel]);
1503 return style.GetStyleAttributes (null).Value;
1507 void RenderMenuBeginTagAttributes (HtmlTextWriter writer, bool dynamic, int menuLevel) {
1508 writer.AddAttribute ("cellpadding", "0", false);
1509 writer.AddAttribute ("cellspacing", "0", false);
1510 writer.AddAttribute ("border", "0", false);
1513 SubMenuStyle style = new SubMenuStyle ();
1514 FillMenuStyle (dynamic, menuLevel, style);
1515 style.AddAttributesToRender (writer);
1519 private void FillMenuStyle (bool dynamic, int menuLevel, SubMenuStyle style) {
1520 if (Page.Header != null) {
1521 // styles are registered
1522 if (!dynamic && staticMenuStyle != null) {
1523 AddCssClass (style, staticMenuStyle.CssClass);
1524 AddCssClass (style, staticMenuStyle.RegisteredCssClass);
1526 if (dynamic && dynamicMenuStyle != null) {
1527 AddCssClass (style, dynamicMenuStyle.CssClass);
1528 AddCssClass (style, dynamicMenuStyle.RegisteredCssClass);
1530 if (levelSubMenuStyles != null && levelSubMenuStyles.Count > menuLevel) {
1531 AddCssClass (style, levelSubMenuStyles [menuLevel].CssClass);
1532 AddCssClass (style, levelSubMenuStyles [menuLevel].RegisteredCssClass);
1536 // styles are not registered
1537 if (!dynamic && staticMenuStyle != null) {
1538 style.CopyFrom (staticMenuStyle);
1540 if (dynamic && dynamicMenuStyle != null) {
1541 style.CopyFrom (dynamicMenuStyle);
1543 if (levelSubMenuStyles != null && levelSubMenuStyles.Count > menuLevel) {
1544 style.CopyFrom (levelSubMenuStyles [menuLevel]);
1549 void RenderMenu (HtmlTextWriter writer, MenuItemCollection items, bool vertical, bool dynamic, int menuLevel, bool notLast)
1551 RenderMenuBeginTag (writer, dynamic, menuLevel);
1552 RenderMenuBody (writer, items, vertical, dynamic, notLast);
1553 RenderMenuEndTag (writer);
1556 void RenderMenuBeginTag (HtmlTextWriter writer, bool dynamic, int menuLevel)
1558 RenderMenuBeginTagAttributes (writer, dynamic, menuLevel);
1559 writer.RenderBeginTag (HtmlTextWriterTag.Table);
1562 void RenderMenuEndTag (HtmlTextWriter writer)
1564 writer.RenderEndTag ();
1567 void RenderMenuBody (HtmlTextWriter writer, MenuItemCollection items, bool vertical, bool dynamic, bool notLast) {
1569 writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1571 int count = items.Count;
1572 for (int n = 0; n < count; n++) {
1573 MenuItem item = items [n];
1574 Adapters.MenuAdapter adapter = Adapter as Adapters.MenuAdapter;
1575 if (adapter != null)
1576 adapter.RenderItem (writer, item, n);
1578 RenderMenuItem (writer, item, (n + 1 == count) ? notLast : true, n == 0);
1582 writer.RenderEndTag (); // TR
1585 void RenderMenuItemSpacing (HtmlTextWriter writer, Unit itemSpacing, bool vertical) {
1587 writer.AddStyleAttribute ("height", itemSpacing.ToString ());
1588 writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1589 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1590 writer.RenderEndTag ();
1591 writer.RenderEndTag ();
1594 writer.AddStyleAttribute ("width", itemSpacing.ToString ());
1595 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1596 writer.RenderEndTag ();
1600 private bool IsDynamicItem (MenuItem item) {
1601 return item.Depth + 1 > StaticDisplayLevels;
1604 private bool DisplayChildren (MenuItem item) {
1605 return (item.Depth + 1 < StaticDisplayLevels + MaximumDynamicDisplayLevels) && item.ChildItems.Count > 0;
1608 static string MakeHandlerJavaScript (string handlerName, string param1, string param2, string param3)
1610 return "javascript:Menu_" + handlerName + "('" + param1 + "','" + param2 + "'," + param3 + ")";
1613 internal void RenderItem (HtmlTextWriter writer, MenuItem item, int position) {
1614 // notLast should be true if item or any of its ancestors is not a
1616 bool notLast = false;
1618 MenuItem child = item;
1619 while (null != (parent = child.Parent)) {
1620 if (child.Index != parent.ChildItems.Count - 1) {
1627 RenderMenuItem (writer, item, notLast, position == 0);
1630 void RenderMenuItem (HtmlTextWriter writer, MenuItem item, bool notLast, bool isFirst) {
1631 bool displayChildren = DisplayChildren (item);
1632 bool dynamicChildren = displayChildren && (item.Depth + 1 >= StaticDisplayLevels);
1633 bool isDynamicItem = IsDynamicItem (item);
1634 bool vertical = (Orientation == Orientation.Vertical) || isDynamicItem;
1636 Unit itemSpacing = GetItemSpacing (item, isDynamicItem);
1638 if (itemSpacing != Unit.Empty && (item.Depth > 0 || !isFirst))
1639 RenderMenuItemSpacing (writer, itemSpacing, vertical);
1641 if(!String.IsNullOrEmpty(item.ToolTip))
1642 writer.AddAttribute (HtmlTextWriterAttribute.Title, item.ToolTip);
1644 writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1646 string parentId = isDynamicItem ? "'" + item.Parent.Path + "'" : "null";
1647 if (dynamicChildren) {
1648 writer.AddAttribute ("onmouseover",
1649 "javascript:Menu_OverItem ('" + ClientID + "','" + item.Path + "'," + parentId + ")");
1650 writer.AddAttribute ("onmouseout",
1651 "javascript:Menu_OutItem ('" + ClientID + "','" + item.Path + "')");
1652 } else if (isDynamicItem) {
1653 writer.AddAttribute ("onmouseover",
1654 "javascript:Menu_OverDynamicLeafItem ('" + ClientID + "','" + item.Path + "'," + parentId + ")");
1655 writer.AddAttribute ("onmouseout",
1656 "javascript:Menu_OutItem ('" + ClientID + "','" + item.Path + "'," + parentId + ")");
1658 writer.AddAttribute ("onmouseover",
1659 "javascript:Menu_OverStaticLeafItem ('" + ClientID + "','" + item.Path + "')");
1660 writer.AddAttribute ("onmouseout",
1661 "javascript:Menu_OutItem ('" + ClientID + "','" + item.Path + "')");
1664 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1666 // Top separator image
1668 if (isDynamicItem && DynamicTopSeparatorImageUrl != "") {
1669 writer.AddAttribute ("src", ResolveClientUrl (DynamicTopSeparatorImageUrl));
1670 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1671 writer.RenderEndTag (); // IMG
1673 else if (!isDynamicItem && StaticTopSeparatorImageUrl != "") {
1674 writer.AddAttribute ("src", ResolveClientUrl (StaticTopSeparatorImageUrl));
1675 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1676 writer.RenderEndTag (); // IMG
1681 MenuItemStyle style = new MenuItemStyle ();
1682 if (Page.Header != null) {
1683 // styles are registered
1684 if (!isDynamicItem && staticMenuItemStyle != null) {
1685 AddCssClass (style, staticMenuItemStyle.CssClass);
1686 AddCssClass (style, staticMenuItemStyle.RegisteredCssClass);
1688 if (isDynamicItem && dynamicMenuItemStyle != null) {
1689 AddCssClass (style, dynamicMenuItemStyle.CssClass);
1690 AddCssClass (style, dynamicMenuItemStyle.RegisteredCssClass);
1692 if (levelMenuItemStyles != null && levelMenuItemStyles.Count > item.Depth) {
1693 AddCssClass (style, levelMenuItemStyles [item.Depth].CssClass);
1694 AddCssClass (style, levelMenuItemStyles [item.Depth].RegisteredCssClass);
1696 if (item == SelectedItem) {
1697 if (!isDynamicItem && staticSelectedStyle != null) {
1698 AddCssClass (style, staticSelectedStyle.CssClass);
1699 AddCssClass (style, staticSelectedStyle.RegisteredCssClass);
1701 if (isDynamicItem && dynamicSelectedStyle != null) {
1702 AddCssClass (style, dynamicSelectedStyle.CssClass);
1703 AddCssClass (style, dynamicSelectedStyle.RegisteredCssClass);
1705 if (levelSelectedStyles != null && levelSelectedStyles.Count > item.Depth) {
1706 AddCssClass (style, levelSelectedStyles [item.Depth].CssClass);
1707 AddCssClass (style, levelSelectedStyles [item.Depth].RegisteredCssClass);
1712 // styles are not registered
1713 if (!isDynamicItem && staticMenuItemStyle != null) {
1714 style.CopyFrom (staticMenuItemStyle);
1716 if (isDynamicItem && dynamicMenuItemStyle != null) {
1717 style.CopyFrom (dynamicMenuItemStyle);
1719 if (levelMenuItemStyles != null && levelMenuItemStyles.Count > item.Depth) {
1720 style.CopyFrom (levelMenuItemStyles [item.Depth]);
1722 if (item == SelectedItem) {
1723 if (!isDynamicItem && staticSelectedStyle != null) {
1724 style.CopyFrom (staticSelectedStyle);
1726 if (isDynamicItem && dynamicSelectedStyle != null) {
1727 style.CopyFrom (dynamicSelectedStyle);
1729 if (levelSelectedStyles != null && levelSelectedStyles.Count > item.Depth) {
1730 style.CopyFrom (levelSelectedStyles [item.Depth]);
1734 style.AddAttributesToRender (writer);
1736 writer.AddAttribute ("id", GetItemClientId (item, "i"));
1738 writer.AddAttribute ("cellpadding", "0", false);
1739 writer.AddAttribute ("cellspacing", "0", false);
1740 writer.AddAttribute ("border", "0", false);
1741 writer.AddAttribute ("width", "100%", false);
1742 writer.RenderBeginTag (HtmlTextWriterTag.Table);
1743 writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1748 writer.AddStyleAttribute (HtmlTextWriterStyle.Width, "100%");
1750 writer.AddStyleAttribute ("white-space", "nowrap");
1751 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1753 RenderItemHref (writer, item);
1755 Style linkStyle = new Style ();
1756 if (Page.Header != null) {
1757 // styles are registered
1758 AddCssClass (linkStyle, ControlLinkStyle.RegisteredCssClass);
1760 if (!isDynamicItem && staticMenuItemStyle != null) {
1761 AddCssClass (linkStyle, staticMenuItemStyle.CssClass);
1762 AddCssClass (linkStyle, staticMenuItemLinkStyle.RegisteredCssClass);
1764 if (isDynamicItem && dynamicMenuItemStyle != null) {
1765 AddCssClass (linkStyle, dynamicMenuItemStyle.CssClass);
1766 AddCssClass (linkStyle, dynamicMenuItemLinkStyle.RegisteredCssClass);
1768 if (levelMenuItemStyles != null && levelMenuItemStyles.Count > item.Depth) {
1769 AddCssClass (linkStyle, levelMenuItemStyles [item.Depth].CssClass);
1770 AddCssClass (linkStyle, levelMenuItemLinkStyles [item.Depth].RegisteredCssClass);
1772 if (item == SelectedItem) {
1773 if (!isDynamicItem && staticSelectedStyle != null) {
1774 AddCssClass (linkStyle, staticSelectedStyle.CssClass);
1775 AddCssClass (linkStyle, staticSelectedLinkStyle.RegisteredCssClass);
1777 if (isDynamicItem && dynamicSelectedStyle != null) {
1778 AddCssClass (linkStyle, dynamicSelectedStyle.CssClass);
1779 AddCssClass (linkStyle, dynamicSelectedLinkStyle.RegisteredCssClass);
1781 if (levelSelectedStyles != null && levelSelectedStyles.Count > item.Depth) {
1782 AddCssClass (linkStyle, levelSelectedStyles [item.Depth].CssClass);
1783 AddCssClass (linkStyle, levelSelectedLinkStyles [item.Depth].RegisteredCssClass);
1788 // styles are not registered
1789 linkStyle.CopyFrom (ControlLinkStyle);
1791 if (!isDynamicItem && staticMenuItemStyle != null) {
1792 linkStyle.CopyFrom (staticMenuItemLinkStyle);
1794 if (isDynamicItem && dynamicMenuItemStyle != null) {
1795 linkStyle.CopyFrom (dynamicMenuItemLinkStyle);
1797 if (levelMenuItemStyles != null && levelMenuItemStyles.Count > item.Depth) {
1798 linkStyle.CopyFrom (levelMenuItemLinkStyles [item.Depth]);
1800 if (item == SelectedItem) {
1801 if (!isDynamicItem && staticSelectedStyle != null) {
1802 linkStyle.CopyFrom (staticSelectedLinkStyle);
1804 if (isDynamicItem && dynamicSelectedStyle != null) {
1805 linkStyle.CopyFrom (dynamicSelectedLinkStyle);
1807 if (levelSelectedStyles != null && levelSelectedStyles.Count > item.Depth) {
1808 linkStyle.CopyFrom (levelSelectedLinkStyles [item.Depth]);
1812 linkStyle.AlwaysRenderTextDecoration = true;
1814 linkStyle.AddAttributesToRender (writer);
1816 writer.AddAttribute ("id", GetItemClientId (item, "l"));
1818 if (item.Depth > 0 && !isDynamicItem) {
1819 Unit indent = new Unit (StaticSubMenuIndent.Value * item.Depth, StaticSubMenuIndent.Type);
1820 writer.AddStyleAttribute ("margin-left", indent.ToString ());
1822 writer.RenderBeginTag (HtmlTextWriterTag.A);
1823 RenderItemContent (writer, item, isDynamicItem);
1824 writer.RenderEndTag (); // A
1826 writer.RenderEndTag (); // TD
1830 if (dynamicChildren) {
1831 string popOutImage = GetPopOutImage (item, isDynamicItem);
1832 if (popOutImage != null) {
1833 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1834 writer.AddAttribute ("src", ResolveClientUrl (popOutImage));
1835 writer.AddAttribute ("border", "0");
1836 string toolTip = String.Format (isDynamicItem ? DynamicPopOutImageTextFormatString : StaticPopOutImageTextFormatString, item.Text);
1837 writer.AddAttribute (HtmlTextWriterAttribute.Alt, toolTip);
1838 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1839 writer.RenderEndTag (); // IMG
1840 writer.RenderEndTag (); // TD
1844 writer.RenderEndTag (); // TR
1845 writer.RenderEndTag (); // TABLE
1847 // Bottom separator image
1849 string separatorImg = item.SeparatorImageUrl;
1850 if (separatorImg.Length == 0) {
1852 separatorImg = DynamicBottomSeparatorImageUrl;
1854 separatorImg = StaticBottomSeparatorImageUrl;
1856 if (separatorImg.Length > 0) {
1857 writer.AddAttribute ("src", ResolveClientUrl (separatorImg));
1858 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1859 writer.RenderEndTag (); // IMG
1862 writer.RenderEndTag (); // TD
1864 writer.RenderEndTag (); // TR
1866 if (itemSpacing != Unit.Empty)
1867 RenderMenuItemSpacing (writer, itemSpacing, vertical);
1868 else if (!vertical && (notLast || (displayChildren && !dynamicChildren))) {
1869 writer.AddStyleAttribute ("width", "3px");
1870 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1871 writer.RenderEndTag ();
1876 if (displayChildren && !dynamicChildren) {
1878 writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1879 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1880 writer.AddAttribute ("width", "100%");
1881 RenderMenu (writer, item.ChildItems, Orientation == Orientation.Vertical, false, item.Depth + 1, notLast);
1882 if (item.Depth + 2 == StaticDisplayLevels)
1883 RenderDynamicMenu (writer, item.ChildItems);
1884 writer.RenderEndTag (); // TD
1886 writer.RenderEndTag (); // TR
1891 void RenderItemContent (HtmlTextWriter writer, MenuItem item, bool isDynamicItem) {
1892 if (_menuItemControls!=null && _menuItemControls [item] != null) {
1893 ((Control) _menuItemControls [item]).Render (writer);
1897 if (!String.IsNullOrEmpty (item.ImageUrl)) {
1898 writer.AddAttribute (HtmlTextWriterAttribute.Src, ResolveClientUrl (item.ImageUrl));
1899 writer.AddAttribute (HtmlTextWriterAttribute.Alt, item.ToolTip);
1900 writer.AddStyleAttribute (HtmlTextWriterStyle.BorderStyle, "none");
1901 writer.AddStyleAttribute (HtmlTextWriterStyle.VerticalAlign, "middle");
1902 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1903 writer.RenderEndTag (); // IMG
1906 if (isDynamicItem && DynamicItemFormatString.Length > 0) {
1907 writer.Write (String.Format (DynamicItemFormatString, item.Text));
1909 else if (!isDynamicItem && StaticItemFormatString.Length > 0) {
1910 writer.Write (String.Format (StaticItemFormatString, item.Text));
1913 writer.Write (item.Text);
1918 Unit GetItemSpacing (MenuItem item, bool dynamic)
1920 Unit itemSpacing = Unit.Empty;
1922 if (item.Selected) {
1923 if (levelSelectedStyles != null && item.Depth < levelSelectedStyles.Count) {
1924 itemSpacing = levelSelectedStyles [item.Depth].ItemSpacing;
1925 if (itemSpacing != Unit.Empty) return itemSpacing;
1928 if (dynamic && dynamicSelectedStyle != null)
1929 itemSpacing = dynamicSelectedStyle.ItemSpacing;
1930 else if (!dynamic && staticSelectedStyle != null)
1931 itemSpacing = staticSelectedStyle.ItemSpacing;
1932 if (itemSpacing != Unit.Empty)
1936 if (levelMenuItemStyles != null && item.Depth < levelMenuItemStyles.Count) {
1937 itemSpacing = levelMenuItemStyles [item.Depth].ItemSpacing;
1938 if (itemSpacing != Unit.Empty) return itemSpacing;
1941 if (dynamic && dynamicMenuItemStyle != null)
1942 return dynamicMenuItemStyle.ItemSpacing;
1943 else if (!dynamic && staticMenuItemStyle != null)
1944 return staticMenuItemStyle.ItemSpacing;
1949 string GetPopOutImage (MenuItem item, bool isDynamicItem)
1951 if (item.PopOutImageUrl != "")
1952 return item.PopOutImageUrl;
1954 if (isDynamicItem) {
1955 if (DynamicPopOutImageUrl != "")
1956 return DynamicPopOutImageUrl;
1957 if (DynamicEnableDefaultPopOutImage)
1958 return Page.ClientScript.GetWebResourceUrl (typeof (Menu), "arrow_plus.gif");
1960 if (StaticPopOutImageUrl != "")
1961 return StaticPopOutImageUrl;
1962 if (StaticEnableDefaultPopOutImage)
1963 return Page.ClientScript.GetWebResourceUrl (typeof (Menu), "arrow_plus.gif");
1968 void RenderItemHref (HtmlTextWriter writer, MenuItem item)
1970 if (!item.BranchEnabled) {
1971 writer.AddAttribute ("disabled", "true", false);
1973 else if (!item.Selectable) {
1974 writer.AddAttribute ("href", "#", false);
1975 writer.AddStyleAttribute ("cursor", "text");
1977 else if (item.NavigateUrl != "") {
1978 string target = item.Target != "" ? item.Target : Target;
1980 string navUrl = ResolveClientUrl (item.NavigateUrl, String.Compare (target, "_blank", StringComparison.InvariantCultureIgnoreCase) != 0);
1982 string navUrl = ResolveClientUrl (item.NavigateUrl);
1984 writer.AddAttribute ("href", navUrl);
1986 writer.AddAttribute ("target", target);
1989 writer.AddAttribute ("href", GetClientEvent (item));
1994 string GetItemClientId (MenuItem item, string sufix)
1996 return ClientID + "_" + item.Path + sufix;
1999 string GetClientEvent (MenuItem item)
2001 return Page.ClientScript.GetPostBackClientHyperlink (this, item.Path);
2004 class MenuTemplateWriter : TextWriter
2009 public MenuTemplateWriter (char [] buffer)
2014 public override Encoding Encoding
2016 get { return Encoding.Unicode; }
2019 public override void Write (char value)
2021 if (_ptr == _buffer.Length)
2024 _buffer [_ptr++] = value;
2027 public override void Write (string value)
2032 if (_ptr + value.Length >= _buffer.Length)
2035 for (int i = 0; i < value.Length; i++)
2036 _buffer [_ptr++] = value [i];
2039 private void EnsureCapacity ()
2041 char [] tmpBuffer = new char [_buffer.Length * 2];
2042 Array.Copy (_buffer, tmpBuffer, _buffer.Length);
2044 _buffer = tmpBuffer;
2048 class MenuRenderHtmlTemplate
2050 public const string Marker = "\u093a\u093b\u0971";
2051 char [] _templateHtml;
2053 MenuTemplateWriter _templateWriter;
2054 ArrayList idxs = new ArrayList (32);
2056 public MenuRenderHtmlTemplate ()
2058 _templateHtml = new char [1024];
2059 _templateWriter = new MenuTemplateWriter (_templateHtml);
2062 public static string GetMarker (int num)
2064 char charNum = (char) ((int) '\u0971' + num);
2065 return string.Concat (Marker, charNum);
2068 public HtmlTextWriter GetMenuTemplateWriter()
2070 return new HtmlTextWriter (_templateWriter);
2073 public void Parse ()
2076 for (int i = 0; i < _templateHtml.Length; i++) {
2077 if (_templateHtml [i] == '\0') {
2082 if (_templateHtml [i] != Marker [mpos]) {
2088 if (mpos == Marker.Length) {
2090 idxs.Add (i - Marker.Length + 1);
2095 public void RenderTemplate (HtmlTextWriter writer, string [] dynamicParts, int start, int count)
2097 if (idxs.Count == 0)
2101 int partEnd = (start == 0) ? -Marker.Length - 1 : (int) idxs [start - 1];
2105 int total = start + count;
2106 for (; i < total; i++) {
2108 partStart = partEnd + Marker.Length + 1;
2109 partEnd = (int) idxs [i];
2111 // write static part
2112 writer.Write (_templateHtml, partStart, partEnd - partStart);
2114 // write synamic part
2115 di = (int) _templateHtml [partEnd + Marker.Length] - 0x971;
2116 writer.Write (dynamicParts [di]);
2119 partStart = partEnd + Marker.Length + 1;
2120 partEnd = (int) idxs [i];
2122 writer.Write (_templateHtml, partStart, partEnd - partStart);