2 // System.Web.UI.WebControls.Menu.cs
5 // Lluis Sanchez Gual (lluis@novell.com)
7 // (C) 2004 Novell, Inc (http://www.novell.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System.Collections;
36 using System.ComponentModel;
38 using System.Web.Handlers;
39 using System.Collections.Specialized;
42 namespace System.Web.UI.WebControls
44 [DefaultEvent ("MenuItemClick")]
45 [ControlValueProperty ("SelectedValue")]
46 [Designer ("System.Web.UI.Design.WebControls.MenuDesigner, System.Design, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.ComponentModel.Design.IDesigner")]
47 public class Menu : HierarchicalDataBoundControl, IPostBackEventHandler, INamingContainer
49 MenuItemStyle dynamicMenuItemStyle;
50 SubMenuStyle dynamicMenuStyle;
51 MenuItemStyle dynamicSelectedStyle;
52 MenuItemStyle staticMenuItemStyle;
53 SubMenuStyle staticMenuStyle;
54 MenuItemStyle staticSelectedStyle;
55 Style staticHoverStyle;
56 Style dynamicHoverStyle;
58 MenuItemStyleCollection levelMenuItemStyles;
59 MenuItemStyleCollection levelSelectedStyles;
60 ITemplate staticItemTemplate;
61 ITemplate dynamicItemTemplate;
63 MenuItemCollection items;
64 MenuItemBindingCollection dataBindings;
65 MenuItem selectedItem;
66 string selectedItemPath;
68 ArrayList dynamicMenus;
70 private static readonly object MenuItemClickEvent = new object();
72 public event MenuEventHandler MenuItemClick {
73 add { Events.AddHandler (MenuItemClickEvent, value); }
74 remove { Events.RemoveHandler (MenuItemClickEvent, value); }
77 protected virtual void OnMenuItemClick (MenuEventArgs e)
80 MenuEventHandler eh = (MenuEventHandler) Events [MenuItemClickEvent];
81 if (eh != null) eh (this, e);
85 [PersistenceMode (PersistenceMode.InnerProperty)]
86 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
87 [Editor ("System.Web.UI.Design.MenuItemBindingsEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
88 public virtual MenuItemBindingCollection DataBindings {
90 if (dataBindings == null) {
91 dataBindings = new MenuItemBindingCollection ();
92 if (IsTrackingViewState)
93 ((IStateManager)dataBindings).TrackViewState();
100 [ThemeableAttribute (false)]
101 public virtual int DisappearAfter {
103 object o = ViewState ["DisappearAfter"];
104 if (o != null) return (int)o;
108 ViewState["DisappearAfter"] = value;
112 [ThemeableAttribute (false)]
115 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
116 public virtual string DynamicBottomSeparatorImageUrl {
118 object o = ViewState ["dbsiu"];
119 if (o != null) return (string)o;
123 ViewState["dbsiu"] = value;
129 [WebCategory ("Appearance")]
130 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
131 public virtual string DynamicTopSeparatorImageUrl {
133 object o = ViewState ["dtsiu"];
134 if (o != null) return (string)o;
138 ViewState["dtsiu"] = value;
144 [WebCategory ("Appearance")]
145 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
146 public virtual string StaticBottomSeparatorImageUrl {
148 object o = ViewState ["sbsiu"];
149 if (o != null) return (string)o;
153 ViewState["sbsiu"] = value;
159 [WebCategory ("Appearance")]
160 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
161 public virtual string StaticTopSeparatorImageUrl {
163 object o = ViewState ["stsiu"];
164 if (o != null) return (string)o;
168 ViewState["stsiu"] = value;
172 [DefaultValue (Orientation.Vertical)]
173 public virtual Orientation Orientation {
175 object o = ViewState ["Orientation"];
176 if (o != null) return (Orientation) o;
177 return Orientation.Vertical;
180 ViewState["Orientation"] = value;
185 [ThemeableAttribute (false)]
186 public virtual int StaticDisplayLevels {
188 object o = ViewState ["StaticDisplayLevels"];
189 if (o != null) return (int)o;
193 if (value < 1) throw new ArgumentOutOfRangeException ();
194 ViewState["StaticDisplayLevels"] = value;
198 [DefaultValue ("16px")]
199 [ThemeableAttribute (false)]
200 public Unit StaticSubMenuIndent {
202 object o = ViewState ["StaticSubMenuIndent"];
203 if (o != null) return (Unit)o;
204 return new Unit (16);
207 ViewState["StaticSubMenuIndent"] = value;
211 [ThemeableAttribute (false)]
213 public virtual int MaximumDynamicDisplayLevels {
215 object o = ViewState ["MaximumDynamicDisplayLevels"];
216 if (o != null) return (int)o;
220 if (value < 0) throw new ArgumentOutOfRangeException ();
221 ViewState["MaximumDynamicDisplayLevels"] = value;
226 public virtual int DynamicVerticalOffset {
228 object o = ViewState ["DynamicVerticalOffset"];
229 if (o != null) return (int)o;
233 ViewState["DynamicVerticalOffset"] = value;
238 public virtual int DynamicHorizontalOffset {
240 object o = ViewState ["DynamicHorizontalOffset"];
241 if (o != null) return (int)o;
245 ViewState["DynamicHorizontalOffset"] = value;
249 [DefaultValue (true)]
250 public virtual bool DynamicEnableDefaultPopOutImage {
252 object o = ViewState ["dedpoi"];
253 if (o != null) return (bool)o;
257 ViewState["dedpoi"] = value;
261 [DefaultValue (true)]
262 public virtual bool StaticEnableDefaultPopOutImage {
264 object o = ViewState ["sedpoi"];
265 if (o != null) return (bool)o;
269 ViewState["sedpoi"] = value;
273 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
274 [PersistenceMode (PersistenceMode.InnerProperty)]
275 [Editor ("System.Web.UI.Design.MenuItemCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
276 public virtual MenuItemCollection Items {
279 items = new MenuItemCollection (this);
280 if (IsTrackingViewState)
281 ((IStateManager)items).TrackViewState();
288 public virtual char PathSeparator {
290 object o = ViewState ["PathSeparator"];
291 if(o != null) return (char)o;
295 ViewState ["PathSeparator"] = value;
299 [DefaultValue (false)]
300 public virtual bool ItemWrap {
302 object o = ViewState ["ItemWrap"];
303 if(o != null) return (bool)o;
307 ViewState ["ItemWrap"] = value;
311 [PersistenceMode (PersistenceMode.InnerProperty)]
312 [NotifyParentProperty (true)]
313 [DefaultValue (null)]
314 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
315 public virtual MenuItemStyle DynamicMenuItemStyle {
317 if (dynamicMenuItemStyle == null) {
318 dynamicMenuItemStyle = new MenuItemStyle ();
319 if (IsTrackingViewState)
320 dynamicMenuItemStyle.TrackViewState();
322 return dynamicMenuItemStyle;
326 [PersistenceMode (PersistenceMode.InnerProperty)]
327 [NotifyParentProperty (true)]
328 [DefaultValue (null)]
329 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
330 public virtual MenuItemStyle DynamicSelectedStyle {
332 if (dynamicSelectedStyle == null) {
333 dynamicSelectedStyle = new MenuItemStyle ();
334 if (IsTrackingViewState)
335 dynamicSelectedStyle.TrackViewState();
337 return dynamicSelectedStyle;
341 [PersistenceMode (PersistenceMode.InnerProperty)]
342 [NotifyParentProperty (true)]
343 [DefaultValue (null)]
344 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
345 public virtual SubMenuStyle DynamicMenuStyle {
347 if (dynamicMenuStyle == null) {
348 dynamicMenuStyle = new SubMenuStyle ();
349 if (IsTrackingViewState)
350 dynamicMenuStyle.TrackViewState();
352 return dynamicMenuStyle;
356 [PersistenceMode (PersistenceMode.InnerProperty)]
357 [NotifyParentProperty (true)]
358 [DefaultValue (null)]
359 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
360 public virtual MenuItemStyle StaticMenuItemStyle {
362 if (staticMenuItemStyle == null) {
363 staticMenuItemStyle = new MenuItemStyle ();
364 if (IsTrackingViewState)
365 staticMenuItemStyle.TrackViewState();
367 return staticMenuItemStyle;
371 [PersistenceMode (PersistenceMode.InnerProperty)]
372 [NotifyParentProperty (true)]
373 [DefaultValue (null)]
374 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
375 public virtual MenuItemStyle StaticSelectedStyle {
377 if (staticSelectedStyle == null) {
378 staticSelectedStyle = new MenuItemStyle ();
379 if (IsTrackingViewState)
380 staticSelectedStyle.TrackViewState();
382 return staticSelectedStyle;
386 [PersistenceMode (PersistenceMode.InnerProperty)]
387 [NotifyParentProperty (true)]
388 [DefaultValue (null)]
389 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
390 public virtual SubMenuStyle StaticMenuStyle {
392 if (staticMenuStyle == null) {
393 staticMenuStyle = new SubMenuStyle ();
394 if (IsTrackingViewState)
395 staticMenuStyle.TrackViewState();
397 return staticMenuStyle;
401 [PersistenceMode (PersistenceMode.InnerProperty)]
402 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
403 [Editor ("System.Web.UI.Design.WebControls.MenuItemStyleCollectionEditor,System.Design, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
404 public virtual MenuItemStyleCollection LevelMenuItemStyles {
406 if (levelMenuItemStyles == null) {
407 levelMenuItemStyles = new MenuItemStyleCollection ();
408 if (IsTrackingViewState)
409 ((IStateManager)levelMenuItemStyles).TrackViewState();
411 return levelMenuItemStyles;
415 [PersistenceMode (PersistenceMode.InnerProperty)]
416 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
417 public virtual MenuItemStyleCollection LevelSelectedStyles {
419 if (levelSelectedStyles == null) {
420 levelSelectedStyles = new MenuItemStyleCollection ();
421 if (IsTrackingViewState)
422 ((IStateManager)levelSelectedStyles).TrackViewState();
424 return levelSelectedStyles;
428 [PersistenceMode (PersistenceMode.InnerProperty)]
429 [NotifyParentProperty (true)]
430 [DefaultValue (null)]
431 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
432 public virtual Style DynamicHoverStyle {
434 if (dynamicHoverStyle == null) {
435 dynamicHoverStyle = new Style ();
436 if (IsTrackingViewState)
437 dynamicHoverStyle.TrackViewState();
439 return dynamicHoverStyle;
443 [PersistenceMode (PersistenceMode.InnerProperty)]
444 [NotifyParentProperty (true)]
445 [DefaultValue (null)]
446 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
447 public virtual Style StaticHoverStyle {
449 if (staticHoverStyle == null) {
450 staticHoverStyle = new Style ();
451 if (IsTrackingViewState)
452 staticHoverStyle.TrackViewState();
454 return staticHoverStyle;
460 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
461 public virtual string ScrollDownImageUrl {
463 object o = ViewState ["sdiu"];
464 if (o != null) return (string)o;
468 ViewState["sdiu"] = value;
474 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
475 public virtual string ScrollUpImageUrl {
477 object o = ViewState ["suiu"];
478 if (o != null) return (string)o;
482 ViewState["suiu"] = value;
487 public virtual string ScrollDownText {
489 object o = ViewState ["ScrollDownText"];
490 if (o != null) return (string) o;
494 ViewState["ScrollDownText"] = value;
499 public virtual string ScrollUpText {
501 object o = ViewState ["ScrollUpText"];
502 if (o != null) return (string) o;
506 ViewState["ScrollUpText"] = value;
512 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
513 public virtual string DynamicPopOutImageUrl {
515 object o = ViewState ["dpoiu"];
516 if (o != null) return (string)o;
520 ViewState["dpoiu"] = value;
526 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
527 public virtual string StaticPopOutImageUrl {
529 object o = ViewState ["spoiu"];
530 if (o != null) return (string)o;
534 ViewState["spoiu"] = value;
539 public virtual string Target {
541 object o = ViewState ["Target"];
542 if (o != null) return (string) o;
546 ViewState["Target"] = value;
550 [DefaultValue (null)]
551 [TemplateContainer (typeof(MenuItemTemplateContainer), BindingDirection.OneWay)]
552 [PersistenceMode (PersistenceMode.InnerProperty)]
554 public ITemplate StaticItemTemplate {
555 get { return staticItemTemplate; }
556 set { staticItemTemplate = value; }
559 [DefaultValue (null)]
560 [TemplateContainer (typeof(MenuItemTemplateContainer), BindingDirection.OneWay)]
561 [PersistenceMode (PersistenceMode.InnerProperty)]
563 public ITemplate DynamicItemTemplate {
564 get { return dynamicItemTemplate; }
565 set { dynamicItemTemplate = value; }
569 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
570 public MenuItem SelectedItem {
572 if (selectedItem == null && selectedItemPath != null) {
573 selectedItem = FindItemByPos (selectedItemPath);
582 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
583 public string SelectedValue {
584 get { return selectedItem != null ? selectedItem.Value : null; }
587 internal void SetSelectedItem (MenuItem item)
589 if (selectedItem == item) return;
591 selectedItemPath = item.Path;
594 public MenuItem FindItem (string valuePath)
596 if (valuePath == null) throw new ArgumentNullException ("valuePath");
597 string[] path = valuePath.Split (PathSeparator);
599 MenuItemCollection col = Items;
600 bool foundBranch = true;
601 while (col.Count > 0 && foundBranch) {
603 foreach (MenuItem item in col) {
604 if (item.Value == path [n]) {
605 if (++n == path.Length) return item;
606 col = item.ChildItems;
615 string GetBindingKey (string dataMember, int depth)
617 return dataMember + " " + depth;
620 internal MenuItemBinding FindBindingForItem (string type, int depth)
622 if (bindings == null) return null;
624 MenuItemBinding bin = (MenuItemBinding) bindings [GetBindingKey (type, depth)];
625 if (bin != null) return bin;
627 bin = (MenuItemBinding) bindings [GetBindingKey (type, -1)];
628 if (bin != null) return bin;
630 bin = (MenuItemBinding) bindings [GetBindingKey ("", depth)];
631 if (bin != null) return bin;
633 bin = (MenuItemBinding) bindings [GetBindingKey ("", -1)];
637 protected internal override void PerformDataBinding ()
639 base.PerformDataBinding ();
640 HierarchicalDataSourceView data = GetData ("");
641 IHierarchicalEnumerable e = data.Select ();
642 foreach (object obj in e) {
643 IHierarchyData hdata = e.GetHierarchyData (obj);
644 MenuItem item = new MenuItem ();
650 public void RaisePostBackEvent (string eventArgument)
652 MenuItem item = FindItemByPos (eventArgument);
653 if (item == null) return;
654 item.Selected = true;
655 OnMenuItemClick (new MenuEventArgs (item));
658 MenuItem FindItemByPos (string path)
660 string[] indexes = path.Split ('_');
661 MenuItem item = null;
663 foreach (string index in indexes) {
664 int i = int.Parse (index);
666 if (i >= Items.Count) return null;
669 if (i >= item.ChildItems.Count) return null;
670 item = item.ChildItems [i];
676 protected override HtmlTextWriterTag TagKey {
677 get { return HtmlTextWriterTag.Table; }
680 protected override void TrackViewState()
684 base.TrackViewState();
685 if (dataBindings != null) {
686 ((IStateManager)dataBindings).TrackViewState ();
689 ((IStateManager)items).TrackViewState();
691 if (dynamicMenuItemStyle != null)
692 dynamicMenuItemStyle.TrackViewState ();
693 if (dynamicMenuStyle != null)
694 dynamicMenuStyle.TrackViewState ();
695 if (levelMenuItemStyles != null)
696 ((IStateManager)levelMenuItemStyles).TrackViewState();
697 if (levelSelectedStyles != null)
698 ((IStateManager)levelSelectedStyles).TrackViewState();
699 if (dynamicSelectedStyle != null)
700 dynamicSelectedStyle.TrackViewState();
701 if (staticMenuItemStyle != null)
702 staticMenuItemStyle.TrackViewState ();
703 if (staticMenuStyle != null)
704 staticMenuStyle.TrackViewState ();
705 if (staticSelectedStyle != null)
706 staticSelectedStyle.TrackViewState();
707 if (staticHoverStyle != null)
708 staticHoverStyle.TrackViewState();
709 if (dynamicHoverStyle != null)
710 dynamicHoverStyle.TrackViewState();
713 protected override object SaveViewState()
715 object[] states = new object [13];
716 states[0] = base.SaveViewState ();
717 states[1] = dataBindings == null ? null : ((IStateManager)dataBindings).SaveViewState();
718 states[2] = items == null ? null : ((IStateManager)items).SaveViewState();
719 states[3] = dynamicMenuItemStyle == null ? null : dynamicMenuItemStyle.SaveViewState();
720 states[4] = dynamicMenuStyle == null ? null : dynamicMenuStyle.SaveViewState();
721 states[5] = levelMenuItemStyles == null ? null : ((IStateManager)levelMenuItemStyles).SaveViewState();
722 states[6] = levelSelectedStyles == null ? null : ((IStateManager)levelSelectedStyles).SaveViewState();
723 states[7] = dynamicSelectedStyle == null ? null : dynamicSelectedStyle.SaveViewState();
724 states[8] = (staticMenuItemStyle == null ? null : staticMenuItemStyle.SaveViewState());
725 states[9] = staticMenuStyle == null ? null : staticMenuStyle.SaveViewState();
726 states[10] = staticSelectedStyle == null ? null : staticSelectedStyle.SaveViewState();
727 states[11] = staticHoverStyle == null ? null : staticHoverStyle.SaveViewState();
728 states[12] = dynamicHoverStyle == null ? null : dynamicHoverStyle.SaveViewState();
730 for (int i = states.Length - 1; i >= 0; i--) {
731 if (states [i] != null)
738 protected override void LoadViewState (object savedState)
740 if (savedState == null)
743 object [] states = (object []) savedState;
744 base.LoadViewState (states[0]);
746 if (states[1] != null)
747 ((IStateManager)DataBindings).LoadViewState(states[1]);
748 if (states[2] != null)
749 ((IStateManager)Items).LoadViewState(states[2]);
750 if (states[3] != null)
751 DynamicMenuItemStyle.LoadViewState (states[3]);
752 if (states[4] != null)
753 DynamicMenuStyle.LoadViewState (states[4]);
754 if (states[5] != null)
755 ((IStateManager)LevelMenuItemStyles).LoadViewState(states[5]);
756 if (states[6] != null)
757 ((IStateManager)LevelSelectedStyles).LoadViewState(states[6]);
758 if (states[7] != null)
759 DynamicSelectedStyle.LoadViewState (states[7]);
760 if (states[8] != null)
761 StaticMenuItemStyle.LoadViewState (states[8]);
762 if (states[9] != null)
763 StaticMenuStyle.LoadViewState (states[9]);
764 if (states[10] != null)
765 StaticSelectedStyle.LoadViewState (states[10]);
766 if (states[11] != null)
767 StaticHoverStyle.LoadViewState (states[11]);
768 if (states[12] != null)
769 DynamicHoverStyle.LoadViewState (states[12]);
772 protected override void OnInit (EventArgs e)
774 Page.RegisterRequiresControlState (this);
778 protected internal override void LoadControlState (object ob)
780 if (ob == null) return;
781 object[] state = (object[]) ob;
782 base.LoadControlState (state[0]);
783 selectedItemPath = state[1] as string;
786 protected internal override object SaveControlState ()
788 object bstate = base.SaveControlState ();
789 object mstate = selectedItemPath;
791 if (bstate != null || mstate != null)
792 return new object[] { bstate, mstate };
798 protected override void CreateChildControls ()
800 base.CreateChildControls ();
804 protected override void OnPreRender (EventArgs e)
806 base.OnPreRender (e);
808 if (!Page.ClientScript.IsClientScriptIncludeRegistered (typeof(Menu), "Menu.js")) {
809 string url = Page.ClientScript.GetWebResourceUrl (typeof(Menu), "Menu.js");
810 Page.ClientScript.RegisterClientScriptInclude (typeof(Menu), "Menu.js", url);
813 string cmenu = ClientID + "_data";
814 string script = string.Format ("var {0} = new Object ();\n", cmenu);
815 script += string.Format ("{0}.disappearAfter = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (DisappearAfter));
816 script += string.Format ("{0}.vertical = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (Orientation == Orientation.Vertical));
817 if (DynamicHorizontalOffset != 0)
818 script += string.Format ("{0}.dho = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (DynamicHorizontalOffset));
819 if (DynamicVerticalOffset != 0)
820 script += string.Format ("{0}.dvo = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (DynamicVerticalOffset));
822 // The order in which styles are defined matters when more than one class
823 // is assigned to an element
825 if (dynamicMenuStyle != null)
826 RegisterItemStyle (dynamicMenuStyle);
827 if (staticMenuStyle != null)
828 RegisterItemStyle (staticMenuStyle);
830 if (staticMenuItemStyle != null)
831 RegisterItemStyle (staticMenuItemStyle);
832 if (staticSelectedStyle != null)
833 RegisterItemStyle (staticSelectedStyle);
835 if (dynamicMenuItemStyle != null)
836 RegisterItemStyle (dynamicMenuItemStyle);
837 if (dynamicSelectedStyle != null)
838 RegisterItemStyle (dynamicSelectedStyle);
840 if (levelMenuItemStyles != null)
841 foreach (Style style in levelMenuItemStyles)
842 RegisterItemStyle (style);
844 if (levelSelectedStyles != null)
845 foreach (Style style in levelSelectedStyles)
846 RegisterItemStyle (style);
848 if (dynamicHoverStyle != null)
849 RegisterItemStyle (dynamicHoverStyle);
850 if (staticHoverStyle != null)
851 RegisterItemStyle (staticHoverStyle);
853 if (staticHoverStyle != null)
854 script += string.Format ("{0}.staticHover = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (staticHoverStyle.RegisteredCssClass));
855 if (dynamicHoverStyle != null)
856 script += string.Format ("{0}.dynamicHover = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (dynamicHoverStyle.RegisteredCssClass));
858 Page.ClientScript.RegisterStartupScript (typeof(Menu), ClientID, script, true);
860 if (dataBindings != null && dataBindings.Count > 0) {
861 bindings = new Hashtable ();
862 foreach (TreeNodeBinding bin in dataBindings) {
863 string key = GetBindingKey (bin.DataMember, bin.Depth);
864 bindings [key] = bin;
871 void RegisterItemStyle (Style baseStyle)
873 Page.Header.StyleSheet.RegisterStyle (baseStyle, this);
874 Style ts = new Style ();
875 ts.CopyTextStylesFrom (baseStyle);
876 Page.Header.StyleSheet.CreateStyleRule (ts, "." + baseStyle.RegisteredCssClass + " A", this);
879 protected override void Render (HtmlTextWriter writer)
881 base.Render (writer);
884 protected override void AddAttributesToRender (HtmlTextWriter writer)
886 RenderMenuBeginTagAttributes (writer, false);
889 public override void RenderBeginTag (HtmlTextWriter writer)
891 base.RenderBeginTag (writer);
894 public override void RenderEndTag (HtmlTextWriter writer)
896 base.RenderEndTag (writer);
898 // Render dynamic menus outside the main control tag
899 for (int n=0; n<dynamicMenus.Count; n++) {
900 MenuItem item = (MenuItem) dynamicMenus [n];
901 RenderDynamicMenu (writer, item);
906 protected override void RenderContents (HtmlTextWriter writer)
908 dynamicMenus = new ArrayList ();
909 RenderMenuBody (writer, Items, Orientation == Orientation.Vertical, false);
912 void RenderDynamicMenu (HtmlTextWriter writer, MenuItem item)
914 if (dynamicMenuStyle != null)
915 writer.AddAttribute ("class", dynamicMenuStyle.RegisteredCssClass);
917 writer.AddStyleAttribute ("visibility", "hidden");
918 writer.AddStyleAttribute ("position", "absolute");
919 writer.AddStyleAttribute ("left", "0px");
920 writer.AddStyleAttribute ("top", "0px");
921 writer.AddAttribute ("id", GetItemClientId (item, "s"));
922 writer.RenderBeginTag (HtmlTextWriterTag.Div);
925 writer.AddAttribute ("id", GetItemClientId (item, "cu"));
926 writer.AddStyleAttribute ("display", "block");
927 writer.AddStyleAttribute ("text-align", "center");
928 writer.AddAttribute ("onmouseover", string.Format ("javascript:Menu_OverScrollBtn ('{0}','{1}','{2}')", ClientID, item.Path, "u"));
929 writer.AddAttribute ("onmouseout", string.Format ("javascript:Menu_OutScrollBtn ('{0}','{1}','{2}')", ClientID, item.Path, "u"));
930 writer.RenderBeginTag (HtmlTextWriterTag.Div);
932 string src = ScrollUpImageUrl != "" ? ScrollUpImageUrl : Page.ClientScript.GetWebResourceUrl (typeof(Menu), "arrow_up.gif");
933 writer.AddAttribute ("src", src);
934 writer.AddAttribute ("alt", ScrollUpText);
935 writer.RenderBeginTag (HtmlTextWriterTag.Img);
936 writer.RenderEndTag (); // IMG
938 writer.RenderEndTag (); // DIV scroll button
940 writer.AddAttribute ("id", GetItemClientId (item, "cb")); // Scroll container
941 writer.RenderBeginTag (HtmlTextWriterTag.Div);
942 writer.AddAttribute ("id", GetItemClientId (item, "cc")); // Content
943 writer.RenderBeginTag (HtmlTextWriterTag.Div);
945 RenderMenu (writer, item.ChildItems, true, true);
947 writer.RenderEndTag (); // DIV Content
948 writer.RenderEndTag (); // DIV Scroll container
951 writer.AddAttribute ("id", GetItemClientId (item, "cd"));
952 writer.AddStyleAttribute ("display", "block");
953 writer.AddStyleAttribute ("text-align", "center");
954 writer.AddAttribute ("onmouseover", string.Format ("javascript:Menu_OverScrollBtn ('{0}','{1}','{2}')", ClientID, item.Path, "d"));
955 writer.AddAttribute ("onmouseout", string.Format ("javascript:Menu_OutScrollBtn ('{0}','{1}','{2}')", ClientID, item.Path, "d"));
956 writer.RenderBeginTag (HtmlTextWriterTag.Div);
958 src = ScrollDownImageUrl != "" ? ScrollDownImageUrl : Page.ClientScript.GetWebResourceUrl (typeof(Menu), "arrow_down.gif");
959 writer.AddAttribute ("src", src);
960 writer.AddAttribute ("alt", ScrollDownText);
961 writer.RenderBeginTag (HtmlTextWriterTag.Img);
962 writer.RenderEndTag (); // IMG
964 writer.RenderEndTag (); // DIV scroll button
966 writer.RenderEndTag (); // DIV menu
969 void RenderMenuBeginTagAttributes (HtmlTextWriter writer, bool dynamic)
971 writer.AddAttribute ("cellpadding", "0");
972 writer.AddAttribute ("cellspacing", "0");
974 if (!dynamic && staticMenuStyle != null)
975 writer.AddAttribute ("class", staticMenuStyle.RegisteredCssClass);
978 void RenderMenu (HtmlTextWriter writer, MenuItemCollection items, bool vertical, bool dynamic)
980 RenderMenuBeginTag (writer, dynamic);
981 RenderMenuBody (writer, items, vertical, dynamic);
982 RenderMenuEndTag (writer);
985 void RenderMenuBeginTag (HtmlTextWriter writer, bool dynamic)
987 RenderMenuBeginTagAttributes (writer, dynamic);
988 writer.RenderBeginTag (HtmlTextWriterTag.Table);
991 void RenderMenuEndTag (HtmlTextWriter writer)
993 writer.RenderEndTag ();
996 void RenderMenuBody (HtmlTextWriter writer, MenuItemCollection items, bool vertical, bool dynamic)
998 if (!vertical) writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1000 for (int n=0; n<items.Count; n++) {
1001 MenuItem item = items [n];
1003 int itemSpacing = GetItemSpacing (item, dynamic);
1004 if (itemSpacing != 0) {
1006 writer.AddAttribute ("height", itemSpacing + "px");
1007 writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1008 writer.RenderEndTag ();
1010 writer.AddAttribute ("width", itemSpacing + "px");
1011 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1012 writer.RenderEndTag ();
1016 RenderMenuItem (writer, item);
1019 if (!vertical) writer.RenderEndTag (); // TR
1022 void RenderMenuItem (HtmlTextWriter writer, MenuItem item)
1024 bool displayChildren = (item.Depth + 1 < StaticDisplayLevels + MaximumDynamicDisplayLevels);
1025 bool dynamicChildren = displayChildren && (item.Depth + 1 >= StaticDisplayLevels) && item.ChildItems.Count > 0;
1026 bool isDynamicItem = item.Depth + 1 > StaticDisplayLevels;
1027 bool vertical = (Orientation == Orientation.Vertical) || isDynamicItem;
1030 writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1032 Style itemStyle = null;
1033 if (levelMenuItemStyles != null && item.Depth < levelMenuItemStyles.Count)
1034 itemStyle = levelMenuItemStyles [item.Depth];
1035 else if (isDynamicItem) {
1036 if (dynamicMenuItemStyle != null)
1037 itemStyle = dynamicMenuItemStyle;
1039 if (staticMenuItemStyle != null)
1040 itemStyle = staticMenuItemStyle;
1043 Style selectedStyle = null;
1044 if (item == SelectedItem) {
1045 if (levelSelectedStyles != null && item.Depth < levelSelectedStyles.Count)
1046 selectedStyle = levelSelectedStyles [item.Depth];
1047 else if (isDynamicItem) {
1048 if (dynamicSelectedStyle != null)
1049 selectedStyle = dynamicSelectedStyle;
1051 if (staticSelectedStyle != null)
1052 selectedStyle = staticSelectedStyle;
1057 if (itemStyle != null) cls += itemStyle.RegisteredCssClass + " ";
1058 if (selectedStyle != null) cls += selectedStyle.RegisteredCssClass + " ";
1060 writer.AddAttribute ("class", cls);
1062 string parentId = isDynamicItem ? "'" + item.Parent.Path + "'" : "null";
1063 if (dynamicChildren) {
1064 writer.AddAttribute ("onmouseover", string.Format ("javascript:Menu_OverItem ('{0}','{1}',{2})", ClientID, item.Path, parentId));
1065 writer.AddAttribute ("onmouseout", string.Format ("javascript:Menu_OutItem ('{0}','{1}')", ClientID, item.Path));
1066 } else if (isDynamicItem) {
1067 writer.AddAttribute ("onmouseover", string.Format ("javascript:Menu_OverDynamicLeafItem ('{0}','{1}',{2})", ClientID, item.Path, parentId));
1068 writer.AddAttribute ("onmouseout", string.Format ("javascript:Menu_OutItem ('{0}','{1}',{2})", ClientID, item.Path, parentId));
1070 writer.AddAttribute ("onmouseover", string.Format ("javascript:Menu_OverStaticLeafItem ('{0}','{1}')", ClientID, item.Path));
1071 writer.AddAttribute ("onmouseout", string.Format ("javascript:Menu_OutItem ('{0}','{1}')", ClientID, item.Path));
1074 writer.AddAttribute ("id", GetItemClientId (item, "i"));
1076 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1078 // Top separator image
1080 if (isDynamicItem && DynamicTopSeparatorImageUrl != "") {
1081 writer.AddAttribute ("src", DynamicTopSeparatorImageUrl);
1082 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1083 writer.RenderEndTag (); // IMG
1084 } else if (!isDynamicItem && StaticTopSeparatorImageUrl != "") {
1085 writer.AddAttribute ("src", StaticTopSeparatorImageUrl);
1086 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1087 writer.RenderEndTag (); // IMG
1092 writer.AddAttribute ("cellpadding", "0");
1093 writer.AddAttribute ("cellspacing", "0");
1094 writer.AddAttribute ("width", "100%");
1095 writer.RenderBeginTag (HtmlTextWriterTag.Table);
1096 writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1098 if (item.Depth > 0 && !isDynamicItem) {
1099 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1100 writer.AddStyleAttribute ("width", StaticSubMenuIndent.ToString ());
1101 writer.RenderBeginTag (HtmlTextWriterTag.Div);
1102 writer.RenderEndTag (); // DIV
1103 writer.RenderEndTag (); // TD
1106 if (item.ImageUrl != "") {
1107 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1108 RenderItemHref (writer, item);
1109 writer.RenderBeginTag (HtmlTextWriterTag.A);
1110 writer.AddAttribute ("src", item.ImageUrl);
1111 writer.AddAttribute ("border", "0");
1112 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1113 writer.RenderEndTag (); // IMG
1114 writer.RenderEndTag (); // A
1115 writer.RenderEndTag (); // TD
1120 writer.AddAttribute ("width", "100%");
1122 writer.AddAttribute ("nowrap", "nowrap");
1123 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1125 RenderItemHref (writer, item);
1126 writer.AddStyleAttribute ("text-decoration", "none");
1127 writer.RenderBeginTag (HtmlTextWriterTag.A);
1128 RenderItemContent (writer, item, isDynamicItem);
1129 writer.RenderEndTag (); // A
1131 writer.RenderEndTag (); // TD
1135 if (dynamicChildren) {
1136 string popOutImage = GetPopOutImage (item, isDynamicItem);
1137 if (popOutImage != null)
1139 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1140 writer.AddAttribute ("src", popOutImage);
1141 writer.AddAttribute ("border", "0");
1142 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1143 writer.RenderEndTag (); // IMG
1144 writer.RenderEndTag (); // TD
1148 writer.RenderEndTag (); // TR
1149 writer.RenderEndTag (); // TABLE
1151 // Bottom separator image
1153 string separatorImg = item.SeparatorImageUrl;
1154 if (separatorImg.Length == 0) {
1155 if (isDynamicItem) separatorImg = DynamicBottomSeparatorImageUrl;
1156 else separatorImg = StaticBottomSeparatorImageUrl;
1158 if (separatorImg.Length > 0) {
1159 writer.AddAttribute ("src", separatorImg);
1160 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1161 writer.RenderEndTag (); // IMG
1167 if (displayChildren) {
1168 if (dynamicChildren) dynamicMenus.Add (item);
1170 writer.AddAttribute ("width", "100%");
1171 RenderMenu (writer, item.ChildItems, true, false);
1175 writer.RenderEndTag (); // TD
1176 writer.RenderEndTag (); // TR
1178 writer.RenderEndTag (); // TD
1180 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1181 if (displayChildren) {
1182 if (dynamicChildren) dynamicMenus.Add (item);
1183 else RenderMenu (writer, item.ChildItems, false, false);
1185 writer.RenderEndTag (); // TD
1189 void RenderItemContent (HtmlTextWriter writer, MenuItem item, bool isDynamicItem)
1191 if (isDynamicItem && dynamicItemTemplate != null) {
1192 MenuItemTemplateContainer cter = new MenuItemTemplateContainer (item.Index, item);
1193 dynamicItemTemplate.InstantiateIn (cter);
1194 cter.Render (writer);
1195 } else if (!isDynamicItem && staticItemTemplate != null) {
1196 MenuItemTemplateContainer cter = new MenuItemTemplateContainer (item.Index, item);
1197 staticItemTemplate.InstantiateIn (cter);
1198 cter.Render (writer);
1200 writer.Write (item.Text);
1204 int GetItemSpacing (MenuItem item, bool dynamic)
1208 if (item.Selected) {
1209 if (levelSelectedStyles != null && item.Depth < levelSelectedStyles.Count) {
1210 itemSpacing = levelSelectedStyles [item.Depth].ItemSpacing;
1211 if (itemSpacing != 0) return itemSpacing;
1214 if (dynamic) itemSpacing = DynamicSelectedStyle.ItemSpacing;
1215 else itemSpacing = StaticSelectedStyle.ItemSpacing;
1216 if (itemSpacing != 0) return itemSpacing;
1219 if (levelMenuItemStyles != null && item.Depth < levelMenuItemStyles.Count) {
1220 itemSpacing = levelMenuItemStyles [item.Depth].ItemSpacing;
1221 if (itemSpacing != 0) return itemSpacing;
1224 if (dynamic) return DynamicMenuItemStyle.ItemSpacing;
1225 else return StaticMenuItemStyle.ItemSpacing;
1229 string GetItemSeparatorImage (MenuItem item, bool isDynamicItem)
1231 if (item.SeparatorImageUrl != "") return item.SeparatorImageUrl;
1232 if (isDynamicItem && DynamicTopSeparatorImageUrl != "")
1233 return DynamicTopSeparatorImageUrl;
1234 else if (!isDynamicItem && StaticTopSeparatorImageUrl != "")
1235 return StaticTopSeparatorImageUrl;
1239 string GetPopOutImage (MenuItem item, bool isDynamicItem)
1241 if (item.PopOutImageUrl != "")
1242 return item.PopOutImageUrl;
1244 if (isDynamicItem) {
1245 if (DynamicPopOutImageUrl != "")
1246 return DynamicPopOutImageUrl;
1247 if (DynamicEnableDefaultPopOutImage)
1248 return AssemblyResourceLoader.GetResourceUrl (typeof(Menu), "arrow_plus.gif");
1250 if (StaticPopOutImageUrl != "")
1251 return StaticPopOutImageUrl;
1252 if (StaticEnableDefaultPopOutImage)
1253 return AssemblyResourceLoader.GetResourceUrl (typeof(Menu), "arrow_plus.gif");
1258 void RenderItemHref (HtmlTextWriter writer, MenuItem item)
1260 if (item.NavigateUrl != "") {
1261 writer.AddAttribute ("href", item.NavigateUrl);
1262 if (item.Target != "")
1263 writer.AddAttribute ("target", item.Target);
1264 else if (Target != "")
1265 writer.AddAttribute ("target", Target);
1268 writer.AddAttribute ("href", GetClientEvent (item));
1272 string GetItemClientId (MenuItem item, string sufix)
1274 return ClientID + "_" + item.Path + sufix;
1277 string GetClientEvent (MenuItem item)
1279 return Page.ClientScript.GetPostBackClientHyperlink (this, item.Path);