fixed data binding feature:
[mono.git] / mcs / class / System.Web / System.Web.UI.WebControls / Menu.cs
1 //
2 // System.Web.UI.WebControls.Menu.cs
3 //
4 // Authors:
5 //      Lluis Sanchez Gual (lluis@novell.com)
6 //
7 // (C) 2004 Novell, Inc (http://www.novell.com)
8 //
9
10 //
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:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
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.
29 //
30
31 #if NET_2_0
32
33 using System;
34 using System.Collections;
35 using System.Text;
36 using System.ComponentModel;
37 using System.Web.UI;
38 using System.Web.Handlers;
39 using System.Collections.Specialized;
40 using System.IO;
41
42 namespace System.Web.UI.WebControls
43 {
44         [DefaultEvent ("MenuItemClick")]
45         [ControlValueProperty ("SelectedValue")]
46         [Designer ("System.Web.UI.Design.WebControls.MenuDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
47         public class Menu : HierarchicalDataBoundControl, IPostBackEventHandler, INamingContainer
48         {
49                 MenuItemStyle dynamicMenuItemStyle;
50                 SubMenuStyle dynamicMenuStyle;
51                 MenuItemStyle dynamicSelectedStyle;
52                 MenuItemStyle staticMenuItemStyle;
53                 SubMenuStyle staticMenuStyle;
54                 MenuItemStyle staticSelectedStyle;
55                 Style staticHoverStyle;
56                 Style dynamicHoverStyle;
57
58                 MenuItemStyleCollection levelMenuItemStyles;
59                 MenuItemStyleCollection levelSelectedStyles;
60                 SubMenuStyleCollection levelSubMenuStyles;
61                 ITemplate staticItemTemplate;
62                 ITemplate dynamicItemTemplate;
63                 
64                 MenuItemCollection items;
65                 MenuItemBindingCollection dataBindings;
66                 MenuItem selectedItem;
67                 string selectedItemPath;
68                 Hashtable bindings;
69                 ArrayList dynamicMenus;
70
71                 Hashtable _menuItemControls;
72                 bool _requiresChildControlsDataBinding;
73
74                 private static readonly object MenuItemClickEvent = new object();
75                 private static readonly object MenuItemDataBoundEvent = new object();
76                 
77                 public static readonly string MenuItemClickCommandName = "Click";
78                 
79                 public event MenuEventHandler MenuItemClick {
80                         add { Events.AddHandler (MenuItemClickEvent, value); }
81                         remove { Events.RemoveHandler (MenuItemClickEvent, value); }
82                 }
83                 
84                 public event MenuEventHandler MenuItemDataBound {
85                         add { Events.AddHandler (MenuItemDataBoundEvent, value); }
86                         remove { Events.RemoveHandler (MenuItemDataBoundEvent, value); }
87                 }
88                 
89                 protected virtual void OnMenuItemClick (MenuEventArgs e)
90                 {
91                         if (Events != null) {
92                                 MenuEventHandler eh = (MenuEventHandler) Events [MenuItemClickEvent];
93                                 if (eh != null) eh (this, e);
94                         }
95                 }
96                 
97                 protected virtual void OnMenuItemDataBound (MenuEventArgs e)
98                 {
99                         if (Events != null) {
100                                 MenuEventHandler eh = (MenuEventHandler) Events [MenuItemDataBoundEvent];
101                                 if (eh != null) eh (this, e);
102                         }
103                 }
104
105             [DefaultValueAttribute (null)]
106                 [PersistenceMode (PersistenceMode.InnerProperty)]
107             [EditorAttribute ("System.Web.UI.Design.WebControls.MenuBindingsEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
108             [MergablePropertyAttribute (false)]
109                 public MenuItemBindingCollection DataBindings {
110                         get {
111                                 if (dataBindings == null) {
112                                         dataBindings = new MenuItemBindingCollection ();
113                                         if (IsTrackingViewState)
114                                                 ((IStateManager)dataBindings).TrackViewState();
115                                 }
116                                 return dataBindings;
117                         }
118                 }
119
120                 [DefaultValue (500)]
121                 [ThemeableAttribute (false)]
122                 public int DisappearAfter {
123                         get {
124                                 object o = ViewState ["DisappearAfter"];
125                                 if (o != null) return (int)o;
126                                 return 500;
127                         }
128                         set {
129                                 ViewState["DisappearAfter"] = value;
130                         }
131                 }
132
133                 [ThemeableAttribute (true)]
134                 [DefaultValue ("")]
135                 [UrlProperty]
136                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
137                 public string DynamicBottomSeparatorImageUrl {
138                         get {
139                                 object o = ViewState ["dbsiu"];
140                                 if (o != null) return (string)o;
141                                 return "";
142                         }
143                         set {
144                                 ViewState["dbsiu"] = value;
145                         }
146                 }
147
148             [DefaultValueAttribute ("")]
149                 public string DynamicItemFormatString {
150                         get {
151                                 object o = ViewState ["DynamicItemFormatString"];
152                                 if (o != null) return (string)o;
153                                 return "";
154                         }
155                         set {
156                                 ViewState["DynamicItemFormatString"] = value;
157                         }
158                 }
159
160                 [DefaultValue ("")]
161                 [UrlProperty]
162                 [WebCategory ("Appearance")]
163                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
164                 public string DynamicTopSeparatorImageUrl {
165                         get {
166                                 object o = ViewState ["dtsiu"];
167                                 if (o != null) return (string)o;
168                                 return "";
169                         }
170                         set {
171                                 ViewState["dtsiu"] = value;
172                         }
173                 }
174
175                 [DefaultValue ("")]
176                 [UrlProperty]
177                 [WebCategory ("Appearance")]
178                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
179                 public string StaticBottomSeparatorImageUrl {
180                         get {
181                                 object o = ViewState ["sbsiu"];
182                                 if (o != null) return (string)o;
183                                 return "";
184                         }
185                         set {
186                                 ViewState["sbsiu"] = value;
187                         }
188                 }
189
190                 [DefaultValue ("")]
191                 [UrlProperty]
192                 [WebCategory ("Appearance")]
193                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
194                 public string StaticTopSeparatorImageUrl {
195                         get {
196                                 object o = ViewState ["stsiu"];
197                                 if (o != null) return (string)o;
198                                 return "";
199                         }
200                         set {
201                                 ViewState["stsiu"] = value;
202                         }
203                 }
204
205                 [DefaultValue (Orientation.Vertical)]
206                 public Orientation Orientation {
207                         get {
208                                 object o = ViewState ["Orientation"];
209                                 if (o != null) return (Orientation) o;
210                                 return Orientation.Vertical;
211                         }
212                         set {
213                                 ViewState["Orientation"] = value;
214                         }
215                 }
216
217                 [DefaultValue (1)]
218                 [ThemeableAttribute (true)]
219                 public int StaticDisplayLevels {
220                         get {
221                                 object o = ViewState ["StaticDisplayLevels"];
222                                 if (o != null) return (int)o;
223                                 return 1;
224                         }
225                         set {
226                                 if (value < 1) throw new ArgumentOutOfRangeException ();
227                                 ViewState["StaticDisplayLevels"] = value;
228                         }
229                 }
230
231             [DefaultValueAttribute ("")]
232                 public string StaticItemFormatString {
233                         get {
234                                 object o = ViewState ["StaticItemFormatString"];
235                                 if (o != null) return (string)o;
236                                 return "";
237                         }
238                         set {
239                                 ViewState["StaticItemFormatString"] = value;
240                         }
241                 }
242
243                 [DefaultValue (typeof (Unit), "16px")]
244                 [ThemeableAttribute (true)]
245                 public Unit StaticSubMenuIndent {
246                         get {
247                                 object o = ViewState ["StaticSubMenuIndent"];
248                                 if (o != null) return (Unit)o;
249                                 return new Unit (16);
250                         }
251                         set {
252                                 ViewState["StaticSubMenuIndent"] = value;
253                         }
254                 }
255
256                 [ThemeableAttribute (true)]
257                 [DefaultValue (3)]
258                 public int MaximumDynamicDisplayLevels {
259                         get {
260                                 object o = ViewState ["MaximumDynamicDisplayLevels"];
261                                 if (o != null) return (int)o;
262                                 return 3;
263                         }
264                         set {
265                                 if (value < 0) throw new ArgumentOutOfRangeException ();
266                                 ViewState["MaximumDynamicDisplayLevels"] = value;
267                         }
268                 }
269
270                 [DefaultValue (0)]
271                 public int DynamicVerticalOffset {
272                         get {
273                                 object o = ViewState ["DynamicVerticalOffset"];
274                                 if (o != null) return (int)o;
275                                 return 0;
276                         }
277                         set {
278                                 ViewState["DynamicVerticalOffset"] = value;
279                         }
280                 }
281
282                 [DefaultValue (0)]
283                 public int DynamicHorizontalOffset {
284                         get {
285                                 object o = ViewState ["DynamicHorizontalOffset"];
286                                 if (o != null) return (int)o;
287                                 return 0;
288                         }
289                         set {
290                                 ViewState["DynamicHorizontalOffset"] = value;
291                         }
292                 }
293
294                 [DefaultValue (true)]
295                 public bool DynamicEnableDefaultPopOutImage {
296                         get {
297                                 object o = ViewState ["dedpoi"];
298                                 if (o != null) return (bool)o;
299                                 return true;
300                         }
301                         set {
302                                 ViewState["dedpoi"] = value;
303                         }
304                 }
305
306                 [DefaultValue (true)]
307                 public bool StaticEnableDefaultPopOutImage {
308                         get {
309                                 object o = ViewState ["sedpoi"];
310                                 if (o != null) return (bool)o;
311                                 return true;
312                         }
313                         set {
314                                 ViewState["sedpoi"] = value;
315                         }
316                 }
317
318                 [DefaultValueAttribute (null)]
319                 [PersistenceMode (PersistenceMode.InnerProperty)]
320                 [Editor ("System.Web.UI.Design.MenuItemCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
321                 [MergablePropertyAttribute (false)]
322                 public MenuItemCollection Items {
323                         get {
324                                 if (items == null) {
325                                         items = new MenuItemCollection (this);
326                                         if (IsTrackingViewState)
327                                                 ((IStateManager)items).TrackViewState();
328                                 }
329                                 return items;
330                         }
331                 }
332
333                 [DefaultValue ('/')]
334                 public char PathSeparator {
335                         get {
336                                 object o = ViewState ["PathSeparator"];
337                                 if(o != null) return (char)o;
338                                 return '/';
339                         }
340                         set {
341                                 ViewState ["PathSeparator"] = value;
342                         }
343                 }
344
345                 [DefaultValue (false)]
346                 public bool ItemWrap {
347                         get {
348                                 object o = ViewState ["ItemWrap"];
349                                 if(o != null) return (bool)o;
350                                 return false;
351                         }
352                         set {
353                                 ViewState ["ItemWrap"] = value;
354                         }
355                 }
356
357                 [PersistenceMode (PersistenceMode.InnerProperty)]
358                 [NotifyParentProperty (true)]
359                 [DefaultValue (null)]
360                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
361                 public MenuItemStyle DynamicMenuItemStyle {
362                         get {
363                                 if (dynamicMenuItemStyle == null) {
364                                         dynamicMenuItemStyle = new MenuItemStyle ();
365                                         if (IsTrackingViewState)
366                                                 dynamicMenuItemStyle.TrackViewState();
367                                 }
368                                 return dynamicMenuItemStyle;
369                         }
370                 }
371                 
372                 [PersistenceMode (PersistenceMode.InnerProperty)]
373                 [NotifyParentProperty (true)]
374                 [DefaultValue (null)]
375                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
376                 public MenuItemStyle DynamicSelectedStyle {
377                         get {
378                                 if (dynamicSelectedStyle == null) {
379                                         dynamicSelectedStyle = new MenuItemStyle ();
380                                         if (IsTrackingViewState)
381                                                 dynamicSelectedStyle.TrackViewState();
382                                 }
383                                 return dynamicSelectedStyle;
384                         }
385                 }
386                 
387                 [PersistenceMode (PersistenceMode.InnerProperty)]
388                 [NotifyParentProperty (true)]
389                 [DefaultValue (null)]
390                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
391                 public SubMenuStyle DynamicMenuStyle {
392                         get {
393                                 if (dynamicMenuStyle == null) {
394                                         dynamicMenuStyle = new SubMenuStyle ();
395                                         if (IsTrackingViewState)
396                                                 dynamicMenuStyle.TrackViewState();
397                                 }
398                                 return dynamicMenuStyle;
399                         }
400                 }
401                 
402                 [PersistenceMode (PersistenceMode.InnerProperty)]
403                 [NotifyParentProperty (true)]
404                 [DefaultValue (null)]
405                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
406                 public MenuItemStyle StaticMenuItemStyle {
407                         get {
408                                 if (staticMenuItemStyle == null) {
409                                         staticMenuItemStyle = new MenuItemStyle ();
410                                         if (IsTrackingViewState)
411                                                 staticMenuItemStyle.TrackViewState();
412                                 }
413                                 return staticMenuItemStyle;
414                         }
415                 }
416                 
417                 [PersistenceMode (PersistenceMode.InnerProperty)]
418                 [NotifyParentProperty (true)]
419                 [DefaultValue (null)]
420                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
421                 public MenuItemStyle StaticSelectedStyle {
422                         get {
423                                 if (staticSelectedStyle == null) {
424                                         staticSelectedStyle = new MenuItemStyle ();
425                                         if (IsTrackingViewState)
426                                                 staticSelectedStyle.TrackViewState();
427                                 }
428                                 return staticSelectedStyle;
429                         }
430                 }
431                 
432                 [PersistenceMode (PersistenceMode.InnerProperty)]
433                 [NotifyParentProperty (true)]
434                 [DefaultValue (null)]
435                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
436                 public SubMenuStyle StaticMenuStyle {
437                         get {
438                                 if (staticMenuStyle == null) {
439                                         staticMenuStyle = new SubMenuStyle ();
440                                         if (IsTrackingViewState)
441                                                 staticMenuStyle.TrackViewState();
442                                 }
443                                 return staticMenuStyle;
444                         }
445                 }
446
447                 [DefaultValue (null)]
448                 [PersistenceMode (PersistenceMode.InnerProperty)]
449             [Editor ("System.Web.UI.Design.WebControls.MenuItemStyleCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
450                 public MenuItemStyleCollection LevelMenuItemStyles {
451                         get {
452                                 if (levelMenuItemStyles == null) {
453                                         levelMenuItemStyles = new MenuItemStyleCollection ();
454                                         if (IsTrackingViewState)
455                                                 ((IStateManager)levelMenuItemStyles).TrackViewState();
456                                 }
457                                 return levelMenuItemStyles;
458                         }
459                 }
460
461                 [DefaultValue (null)]
462                 [PersistenceMode (PersistenceMode.InnerProperty)]
463             [Editor ("System.Web.UI.Design.WebControls.MenuItemStyleCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
464                 public MenuItemStyleCollection LevelSelectedStyles {
465                         get {
466                                 if (levelSelectedStyles == null) {
467                                         levelSelectedStyles = new MenuItemStyleCollection ();
468                                         if (IsTrackingViewState)
469                                                 ((IStateManager)levelSelectedStyles).TrackViewState();
470                                 }
471                                 return levelSelectedStyles;
472                         }
473                 }
474
475                 [DefaultValue (null)]
476                 [PersistenceMode (PersistenceMode.InnerProperty)]
477             [Editor ("System.Web.UI.Design.WebControls.SubMenuStyleCollectionEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
478                 public SubMenuStyleCollection LevelSubMenuStyles {
479                         get {
480                                 if (levelSubMenuStyles == null) {
481                                         levelSubMenuStyles = new SubMenuStyleCollection ();
482                                         if (IsTrackingViewState)
483                                                 ((IStateManager)levelSubMenuStyles).TrackViewState();
484                                 }
485                                 return levelSubMenuStyles;
486                         }
487                 }
488
489                 [PersistenceMode (PersistenceMode.InnerProperty)]
490                 [NotifyParentProperty (true)]
491                 [DefaultValue (null)]
492                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
493                 public Style DynamicHoverStyle {
494                         get {
495                                 if (dynamicHoverStyle == null) {
496                                         dynamicHoverStyle = new Style ();
497                                         if (IsTrackingViewState)
498                                                 dynamicHoverStyle.TrackViewState();
499                                 }
500                                 return dynamicHoverStyle;
501                         }
502                 }
503                 
504                 [PersistenceMode (PersistenceMode.InnerProperty)]
505                 [NotifyParentProperty (true)]
506                 [DefaultValue (null)]
507                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
508                 public Style StaticHoverStyle {
509                         get {
510                                 if (staticHoverStyle == null) {
511                                         staticHoverStyle = new Style ();
512                                         if (IsTrackingViewState)
513                                                 staticHoverStyle.TrackViewState();
514                                 }
515                                 return staticHoverStyle;
516                         }
517                 }
518                 
519                 [DefaultValue ("")]
520                 [UrlProperty]
521                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
522                 public string ScrollDownImageUrl {
523                         get {
524                                 object o = ViewState ["sdiu"];
525                                 if (o != null) return (string)o;
526                                 return "";
527                         }
528                         set {
529                                 ViewState["sdiu"] = value;
530                         }
531                 }
532
533                 [DefaultValue ("")]
534                 [UrlProperty]
535                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
536                 public string ScrollUpImageUrl {
537                         get {
538                                 object o = ViewState ["suiu"];
539                                 if (o != null) return (string)o;
540                                 return "";
541                         }
542                         set {
543                                 ViewState["suiu"] = value;
544                         }
545                 }
546
547                 [Localizable (true)]
548                 public string ScrollDownText {
549                         get {
550                                 object o = ViewState ["ScrollDownText"];
551                                 if (o != null) return (string) o;
552                                 return Locale.GetText ("Scroll down");
553                         }
554                         set {
555                                 ViewState["ScrollDownText"] = value;
556                         }
557                 }
558
559                 [Localizable (true)]
560                 public string ScrollUpText {
561                         get {
562                                 object o = ViewState ["ScrollUpText"];
563                                 if (o != null) return (string) o;
564                                 return Locale.GetText ("Scroll up");
565                         }
566                         set {
567                                 ViewState["ScrollUpText"] = value;
568                         }
569                 }
570
571                 [MonoTODO]
572                 public string DynamicPopOutImageTextFormatString 
573                 {
574                         get
575                         {
576                                 object o = ViewState ["dpoitf"];
577                                 if (o != null) return (string) o;
578                                 return Locale.GetText ("Expand {0}");
579                         }
580                         set
581                         {
582                                 ViewState ["dpoitf"] = value;
583                         }
584                 }
585                 
586
587                 [DefaultValue ("")]
588                 [UrlProperty]
589                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
590                 public string DynamicPopOutImageUrl {
591                         get {
592                                 object o = ViewState ["dpoiu"];
593                                 if (o != null) return (string)o;
594                                 return "";
595                         }
596                         set {
597                                 ViewState["dpoiu"] = value;
598                         }
599                 }
600
601                 [MonoTODO]
602                 public string StaticPopOutImageTextFormatString
603                 {
604                         get
605                         {
606                                 object o = ViewState ["spoitf"];
607                                 if (o != null) return (string) o;
608                                 return Locale.GetText ("Expand {0}");
609                         }
610                         set
611                         {
612                                 ViewState ["spoitf"] = value;
613                         }
614                 }
615                 
616
617                 [DefaultValue ("")]
618                 [UrlProperty]
619                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
620                 public string StaticPopOutImageUrl {
621                         get {
622                                 object o = ViewState ["spoiu"];
623                                 if (o != null) return (string)o;
624                                 return "";
625                         }
626                         set {
627                                 ViewState["spoiu"] = value;
628                         }
629                 }
630
631                 [DefaultValue ("")]
632                 public string Target {
633                         get {
634                                 object o = ViewState ["Target"];
635                                 if (o != null) return (string) o;
636                                 return "";
637                         }
638                         set {
639                                 ViewState["Target"] = value;
640                         }
641                 }
642
643                 [DefaultValue (null)]
644                 [TemplateContainer (typeof(MenuItemTemplateContainer), BindingDirection.OneWay)]
645                 [PersistenceMode (PersistenceMode.InnerProperty)]
646             [Browsable (false)]
647                 public ITemplate StaticItemTemplate {
648                         get { return staticItemTemplate; }
649                         set { staticItemTemplate = value; }
650                 }
651                 
652                 [DefaultValue (null)]
653                 [TemplateContainer (typeof(MenuItemTemplateContainer), BindingDirection.OneWay)]
654                 [PersistenceMode (PersistenceMode.InnerProperty)]
655             [Browsable (false)]
656                 public ITemplate DynamicItemTemplate {
657                         get { return dynamicItemTemplate; }
658                         set { dynamicItemTemplate = value; }
659                 }
660                 
661                 [Browsable (false)]
662                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
663                 public MenuItem SelectedItem {
664                         get {
665                                 if (selectedItem == null && selectedItemPath != null) {
666                                         selectedItem = FindItemByPos (selectedItemPath);
667                                 }
668                                 
669                                 return selectedItem;
670                         }
671                 }
672
673                 [Browsable (false)]
674                 [DefaultValue ("")]
675                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
676                 public string SelectedValue {
677                         get { return selectedItem != null ? selectedItem.Value : ""; }
678                 }
679
680                 [MonoTODO]
681                 [Localizable (true)]
682                 public string SkipLinkText 
683                 {
684                         get {
685                                 object o = ViewState ["SkipLinkText"];
686                                 if (o != null)
687                                         return (string) o;
688                                 return "Skip Navigation Links";
689                         }
690                         set {
691                                 ViewState ["SkipLinkText"] = value;
692                         }
693                 }
694                 
695
696                 internal void SetSelectedItem (MenuItem item)
697                 {
698                         if (selectedItem == item) return;
699                         selectedItem = item;
700                         selectedItemPath = item.Path;
701                 }
702                 
703                 public MenuItem FindItem (string valuePath)
704                 {
705                         if (valuePath == null) throw new ArgumentNullException ("valuePath");
706                         string[] path = valuePath.Split (PathSeparator);
707                         int n = 0;
708                         MenuItemCollection col = Items;
709                         bool foundBranch = true;
710                         while (col.Count > 0 && foundBranch) {
711                                 foundBranch = false;
712                                 foreach (MenuItem item in col) {
713                                         if (item.Value == path [n]) {
714                                                 if (++n == path.Length) return item;
715                                                 col = item.ChildItems;
716                                                 foundBranch = true;
717                                                 break;
718                                         }
719                                 }
720                         }
721                         return null;
722                 }
723                 
724                 string GetBindingKey (string dataMember, int depth)
725                 {
726                         return dataMember + " " + depth;
727                 }
728                 
729                 internal MenuItemBinding FindBindingForItem (string type, int depth)
730                 {
731                         if (bindings == null) return null;
732
733                         MenuItemBinding bin = (MenuItemBinding) bindings [GetBindingKey (type, depth)];
734                         if (bin != null) return bin;
735                         
736                         bin = (MenuItemBinding) bindings [GetBindingKey (type, -1)];
737                         if (bin != null) return bin;
738                         
739                         bin = (MenuItemBinding) bindings [GetBindingKey ("", depth)];
740                         if (bin != null) return bin;
741                         
742                         bin = (MenuItemBinding) bindings [GetBindingKey ("", -1)];
743                         return bin;
744                 }
745                 
746                 protected internal override void PerformDataBinding ()
747                 {
748                         base.PerformDataBinding ();
749
750                         // Do not attempt to bind data if there is no
751                         // data source set.
752                         if (!IsBoundUsingDataSourceID && (DataSource == null)) {
753                                 EnsureChildControlsDataBound ();
754                                 return;
755                         }
756                         
757                         HierarchicalDataSourceView data = GetData ("");
758
759                         if (data == null) {
760                                 throw new InvalidOperationException ("No view returned by data source control.");
761                         }
762                         Items.Clear ();
763                         IHierarchicalEnumerable e = data.Select ();
764                         FillBoundChildrenRecursive (e, Items);
765
766                         CreateChildControlsForItems ();
767                         ChildControlsCreated = true;
768
769                         EnsureChildControlsDataBound ();
770                 }
771
772                 private void FillBoundChildrenRecursive (IHierarchicalEnumerable hEnumerable, MenuItemCollection itemCollection) {
773                         foreach (object obj in hEnumerable) {
774                                 IHierarchyData hdata = hEnumerable.GetHierarchyData (obj);
775                                 MenuItem item = new MenuItem ();
776                                 itemCollection.Add (item);
777                                 item.Bind (hdata);
778                                 OnMenuItemDataBound (new MenuEventArgs (item));
779
780                                 if (hdata == null || !hdata.HasChildren)
781                                         continue;
782
783                                 IHierarchicalEnumerable e = hdata.GetChildren ();
784                                 FillBoundChildrenRecursive (e, item.ChildItems);
785                         }
786                 }
787                 
788                 protected void SetItemDataBound (MenuItem node, bool dataBound)
789                 {
790                         node.SetDataBound (dataBound);
791                 }
792                 
793                 protected void SetItemDataPath (MenuItem node, string dataPath)
794                 {
795                         node.SetDataPath (dataPath);
796                 }
797                 
798                 protected void SetItemDataItem (MenuItem node, object dataItem)
799                 {
800                         node.SetDataItem (dataItem);
801                 }
802                 
803                 protected internal virtual void RaisePostBackEvent (string eventArgument)
804                 {
805                         if (!Enabled)
806                                 return;
807
808                         EnsureChildControls();
809                         MenuItem item = FindItemByPos (eventArgument);
810                         if (item == null) return;
811                         item.Selected = true;
812                         OnMenuItemClick (new MenuEventArgs (item));
813                 }
814
815                 void IPostBackEventHandler.RaisePostBackEvent (string eventArgument)
816                 {
817                         RaisePostBackEvent (eventArgument);
818                 }
819                 
820                 MenuItem FindItemByPos (string path)
821                 {
822                         string[] indexes = path.Split ('_');
823                         MenuItem item = null;
824                         
825                         foreach (string index in indexes) {
826                                 int i = int.Parse (index);
827                                 if (item == null) {
828                                         if (i >= Items.Count) return null;
829                                         item = Items [i];
830                                 } else {
831                                         if (i >= item.ChildItems.Count) return null;
832                                         item = item.ChildItems [i];
833                                 }
834                         }
835                         return item;
836                 }
837                 
838                 protected override HtmlTextWriterTag TagKey {
839                         get { return HtmlTextWriterTag.Table; }
840                 }
841                 
842                 protected override void TrackViewState()
843                 {
844                         EnsureDataBound ();
845                         
846                         base.TrackViewState();
847                         if (dataBindings != null) {
848                                 ((IStateManager)dataBindings).TrackViewState ();
849                         }
850                         if (items != null) {
851                                 ((IStateManager)items).TrackViewState();
852                         }
853                         if (dynamicMenuItemStyle != null)
854                                 dynamicMenuItemStyle.TrackViewState ();
855                         if (dynamicMenuStyle != null)
856                                 dynamicMenuStyle.TrackViewState ();
857                         if (levelMenuItemStyles != null)
858                                 ((IStateManager)levelMenuItemStyles).TrackViewState();
859                         if (levelSelectedStyles != null)
860                                 ((IStateManager)levelSelectedStyles).TrackViewState();
861                         if (levelSubMenuStyles != null)
862                                 ((IStateManager)levelSubMenuStyles).TrackViewState();
863                         if (dynamicSelectedStyle != null)
864                                 dynamicSelectedStyle.TrackViewState();
865                         if (staticMenuItemStyle != null)
866                                 staticMenuItemStyle.TrackViewState ();
867                         if (staticMenuStyle != null)
868                                 staticMenuStyle.TrackViewState ();
869                         if (staticSelectedStyle != null)
870                                 staticSelectedStyle.TrackViewState();
871                         if (staticHoverStyle != null)
872                                 staticHoverStyle.TrackViewState();
873                         if (dynamicHoverStyle != null)
874                                 dynamicHoverStyle.TrackViewState();
875                 }
876
877                 protected override object SaveViewState()
878                 {
879                         object[] states = new object [14];
880                         states[0] = base.SaveViewState ();
881                         states[1] = dataBindings == null ? null : ((IStateManager)dataBindings).SaveViewState();
882                         states[2] = items == null ? null : ((IStateManager)items).SaveViewState();
883                         states[3] = dynamicMenuItemStyle == null ? null : dynamicMenuItemStyle.SaveViewState();
884                         states[4] = dynamicMenuStyle == null ? null : dynamicMenuStyle.SaveViewState();
885                         states[5] = levelMenuItemStyles == null ? null : ((IStateManager)levelMenuItemStyles).SaveViewState();
886                         states[6] = levelSelectedStyles == null ? null : ((IStateManager)levelSelectedStyles).SaveViewState();
887                         states[7] = dynamicSelectedStyle == null ? null : dynamicSelectedStyle.SaveViewState();
888                         states[8] = (staticMenuItemStyle == null ? null : staticMenuItemStyle.SaveViewState());
889                         states[9] = staticMenuStyle == null ? null : staticMenuStyle.SaveViewState();
890                         states[10] = staticSelectedStyle == null ? null : staticSelectedStyle.SaveViewState();
891                         states[11] = staticHoverStyle == null ? null : staticHoverStyle.SaveViewState();
892                         states[12] = dynamicHoverStyle == null ? null : dynamicHoverStyle.SaveViewState();
893                         states[13] = levelSubMenuStyles == null ? null : ((IStateManager)levelSubMenuStyles).SaveViewState();
894
895                         for (int i = states.Length - 1; i >= 0; i--) {
896                                 if (states [i] != null)
897                                         return states;
898                         }
899
900                         return null;
901                 }
902
903                 protected override void LoadViewState (object savedState)
904                 {
905                         if (savedState == null)
906                                 return;
907
908                         object [] states = (object []) savedState;
909                         base.LoadViewState (states[0]);
910                         
911                         if (states[1] != null)
912                                 ((IStateManager)DataBindings).LoadViewState(states[1]);
913                         if (states[2] != null)
914                                 ((IStateManager)Items).LoadViewState(states[2]);
915                         if (states[3] != null)
916                                 DynamicMenuItemStyle.LoadViewState (states[3]);
917                         if (states[4] != null)
918                                 DynamicMenuStyle.LoadViewState (states[4]);
919                         if (states[5] != null)
920                                 ((IStateManager)LevelMenuItemStyles).LoadViewState(states[5]);
921                         if (states[6] != null)
922                                 ((IStateManager)LevelSelectedStyles).LoadViewState(states[6]);
923                         if (states[7] != null)
924                                 DynamicSelectedStyle.LoadViewState (states[7]);
925                         if (states[8] != null)
926                                 StaticMenuItemStyle.LoadViewState (states[8]);
927                         if (states[9] != null)
928                                 StaticMenuStyle.LoadViewState (states[9]);
929                         if (states[10] != null)
930                                 StaticSelectedStyle.LoadViewState (states[10]);
931                         if (states[11] != null)
932                                 StaticHoverStyle.LoadViewState (states[11]);
933                         if (states[12] != null)
934                                 DynamicHoverStyle.LoadViewState (states[12]);
935                         if (states[13] != null)
936                                 ((IStateManager)LevelSubMenuStyles).LoadViewState(states[13]);
937                 }
938                 
939                 protected internal override void OnInit (EventArgs e)
940                 {
941                         Page.RegisterRequiresControlState (this);
942                         base.OnInit (e);
943                 }
944                 
945                 protected internal override void LoadControlState (object ob)
946                 {
947                         if (ob == null) return;
948                         object[] state = (object[]) ob;
949                         base.LoadControlState (state[0]);
950                         selectedItemPath = state[1] as string;
951                 }
952                 
953                 protected internal override object SaveControlState ()
954                 {
955                         object bstate = base.SaveControlState ();
956                         object mstate = selectedItemPath;
957                         
958                         if (bstate != null || mstate != null)
959                                 return new object[] { bstate, mstate };
960                         else
961                                 return null;
962                 }
963                 
964                 protected internal override void CreateChildControls ()
965                 {
966                         if (!IsBoundUsingDataSourceID && (DataSource == null)) {
967                                 CreateChildControlsForItems ();
968                         }
969                         else {
970                                 EnsureDataBound ();
971                         }
972                 }
973
974                 private void CreateChildControlsForItems () {
975                         Controls.Clear ();
976                         // Check for HasChildViewState to avoid unnecessary calls to ClearChildViewState.
977                         if (HasChildViewState)
978                                 ClearChildViewState ();
979                         _menuItemControls = new Hashtable ();
980                         CreateChildControlsForItems (Items);
981                         _requiresChildControlsDataBinding = true;
982                 }
983
984                 private void CreateChildControlsForItems (MenuItemCollection items ) {
985                         foreach (MenuItem item in items) {
986                                 bool isDynamicItem = IsDynamicItem (item);
987                                 if (isDynamicItem && dynamicItemTemplate != null) {
988                                         MenuItemTemplateContainer cter = new MenuItemTemplateContainer (item.Index, item);
989                                         dynamicItemTemplate.InstantiateIn (cter);
990                                         _menuItemControls [item] = cter;
991                                         Controls.Add (cter);
992                                 }
993                                 else if (!isDynamicItem && staticItemTemplate != null) {
994                                         MenuItemTemplateContainer cter = new MenuItemTemplateContainer (item.Index, item);
995                                         staticItemTemplate.InstantiateIn (cter);
996                                         _menuItemControls [item] = cter;
997                                         Controls.Add (cter);
998                                 }
999                                 if (item.HasChildData)
1000                                         CreateChildControlsForItems (item.ChildItems);
1001                         }
1002                 }
1003
1004                 protected override void EnsureDataBound ()
1005                 {
1006                         base.EnsureDataBound ();
1007                         
1008                         EnsureChildControlsDataBound ();
1009                 }
1010
1011                 private void EnsureChildControlsDataBound () {
1012                         if (!_requiresChildControlsDataBinding)
1013                                 return;
1014                         DataBindChildren ();
1015                         _requiresChildControlsDataBinding = false;
1016                 }
1017
1018                 [MonoTODO]
1019                 protected override IDictionary GetDesignModeState ()
1020                 {
1021                         throw new NotImplementedException ();
1022                 }
1023
1024                 [MonoTODO]
1025                 protected override void SetDesignModeState (IDictionary data)
1026                 {
1027                         throw new NotImplementedException ();
1028                 }
1029                                 
1030                 public override ControlCollection Controls {
1031                         get { return base.Controls; }
1032                 }
1033                 
1034                 public sealed override void DataBind ()
1035                 {
1036                         base.DataBind ();
1037                 }
1038                 
1039                 [MonoTODO]
1040                 protected override bool OnBubbleEvent (object source, EventArgs e)
1041                 {
1042                         throw new NotImplementedException ();
1043                 }
1044
1045                 protected override void OnDataBinding (EventArgs e)
1046                 {
1047                         EnsureChildControls ();
1048                         base.OnDataBinding (e);
1049                 }
1050                 
1051                 protected internal override void OnPreRender (EventArgs e)
1052                 {
1053                         base.OnPreRender (e);
1054                         
1055                         if (!Page.ClientScript.IsClientScriptIncludeRegistered (typeof(Menu), "Menu.js")) {
1056                                 string url = Page.ClientScript.GetWebResourceUrl (typeof(Menu), "Menu.js");
1057                                 Page.ClientScript.RegisterClientScriptInclude (typeof(Menu), "Menu.js", url);
1058                         }
1059                         
1060                         string cmenu = ClientID + "_data";
1061                         string script = string.Format ("var {0} = new Object ();\n", cmenu);
1062                         script += string.Format ("{0}.disappearAfter = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (DisappearAfter));
1063                         script += string.Format ("{0}.vertical = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (Orientation == Orientation.Vertical));
1064                         if (DynamicHorizontalOffset != 0)
1065                                 script += string.Format ("{0}.dho = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (DynamicHorizontalOffset));
1066                         if (DynamicVerticalOffset != 0)
1067                                 script += string.Format ("{0}.dvo = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (DynamicVerticalOffset));
1068                                 
1069                         // The order in which styles are defined matters when more than one class
1070                         // is assigned to an element
1071                         
1072                         if (dynamicMenuStyle != null)
1073                                 RegisterItemStyle (dynamicMenuStyle);
1074                         if (staticMenuStyle != null)
1075                                 RegisterItemStyle (staticMenuStyle);
1076                 
1077                         if (staticMenuItemStyle != null)
1078                                 RegisterItemStyle (staticMenuItemStyle);
1079
1080                         if (dynamicMenuItemStyle != null)
1081                                 RegisterItemStyle (dynamicMenuItemStyle);
1082
1083                         if (levelSubMenuStyles != null)
1084                                 foreach (Style style in levelSubMenuStyles)
1085                                         RegisterItemStyle (style);
1086
1087                         if (levelMenuItemStyles != null)
1088                                 foreach (Style style in levelMenuItemStyles)
1089                                         RegisterItemStyle (style);
1090
1091                         if (staticSelectedStyle != null)
1092                                 RegisterItemStyle (staticSelectedStyle);
1093                         if (dynamicSelectedStyle != null)
1094                                 RegisterItemStyle (dynamicSelectedStyle);
1095                                 
1096                         if (levelSelectedStyles != null)
1097                                 foreach (Style style in levelSelectedStyles)
1098                                         RegisterItemStyle (style);
1099                         
1100                         if (dynamicHoverStyle != null)
1101                                 RegisterItemStyle (dynamicHoverStyle);
1102                         if (staticHoverStyle != null)
1103                                 RegisterItemStyle (staticHoverStyle);
1104
1105                         if (staticHoverStyle != null)
1106                                 script += string.Format ("{0}.staticHover = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (staticHoverStyle.RegisteredCssClass));
1107                         if (dynamicHoverStyle != null)
1108                                 script += string.Format ("{0}.dynamicHover = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (dynamicHoverStyle.RegisteredCssClass));
1109                         
1110                         Page.ClientScript.RegisterStartupScript (typeof(Menu), ClientID, script, true);
1111
1112                         if (dataBindings != null && dataBindings.Count > 0) {
1113                                 bindings = new Hashtable ();
1114                                 foreach (TreeNodeBinding bin in dataBindings) {
1115                                         string key = GetBindingKey (bin.DataMember, bin.Depth);
1116                                         bindings [key] = bin;
1117                                 }
1118                         }
1119                         else
1120                                 bindings = null;
1121                 }
1122                 
1123                 void RegisterItemStyle (Style baseStyle)
1124                 {
1125                         Page.Header.StyleSheet.RegisterStyle (baseStyle, this);
1126                         Style ts = new Style ();
1127                         ts.CopyTextStylesFrom (baseStyle);
1128                         Page.Header.StyleSheet.CreateStyleRule (ts, this, "." + baseStyle.RegisteredCssClass + " A");
1129                 }
1130                 
1131                 protected internal override void Render (HtmlTextWriter writer)
1132                 {
1133                         if (Items.Count > 0)
1134                                 base.Render (writer);
1135                 }
1136                 
1137                 protected override void AddAttributesToRender (HtmlTextWriter writer)
1138                 {
1139                         RenderMenuBeginTagAttributes (writer, false, 0);
1140                 }
1141                 
1142                 public override void RenderBeginTag (HtmlTextWriter writer)
1143                 {
1144                         if (SkipLinkText != "") {
1145                                 System.Web.UI.HtmlControls.HtmlAnchor anchor = new System.Web.UI.HtmlControls.HtmlAnchor ();
1146                                 anchor.HRef = "#" + ClientID + "_SkipLink";
1147
1148                                 Image img = new Image ();
1149                                 ClientScriptManager csm = new ClientScriptManager (null);
1150                                 img.ImageUrl = csm.GetWebResourceUrl (typeof (SiteMapPath), "transparent.gif");
1151                                 img.Attributes.Add ("height", "0");
1152                                 img.Attributes.Add ("width", "0");
1153                                 img.AlternateText = SkipLinkText;
1154
1155                                 anchor.Controls.Add (img);
1156                                 anchor.Render (writer);
1157                         }
1158                         base.RenderBeginTag (writer);
1159                 }
1160                 
1161                 public override void RenderEndTag (HtmlTextWriter writer)
1162                 {
1163                         base.RenderEndTag (writer);
1164                         
1165                         // Render dynamic menus outside the main control tag
1166                         if (dynamicMenus != null) {
1167                                 for (int n = 0; n < dynamicMenus.Count; n++) {
1168                                         MenuItem item = (MenuItem) dynamicMenus [n];
1169                                         RenderDynamicMenu (writer, item);
1170                                 }
1171                         }
1172                         dynamicMenus = null;
1173
1174                         if (SkipLinkText != "") {
1175                                 System.Web.UI.HtmlControls.HtmlAnchor anchor = new System.Web.UI.HtmlControls.HtmlAnchor ();
1176                                 anchor.ID = "SkipLink";
1177                                 anchor.Render (writer);
1178                         }
1179                 }
1180                 
1181                 protected internal override void RenderContents (HtmlTextWriter writer)
1182                 {
1183                         dynamicMenus = new ArrayList ();
1184                         RenderMenuBody (writer, Items, Orientation == Orientation.Vertical, false);
1185                 }
1186                 
1187                 void RenderDynamicMenu (HtmlTextWriter writer, MenuItem item)
1188                 {
1189                         if (dynamicMenuStyle != null)
1190                                 writer.AddAttribute ("class", dynamicMenuStyle.RegisteredCssClass);
1191                         
1192                         writer.AddStyleAttribute ("visibility", "hidden");
1193                         writer.AddStyleAttribute ("position", "absolute");
1194                         writer.AddStyleAttribute ("left", "0px");
1195                         writer.AddStyleAttribute ("top", "0px");
1196                         writer.AddAttribute ("id", GetItemClientId (item, "s"));
1197                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
1198
1199                         // Up button
1200                         writer.AddAttribute ("id", GetItemClientId (item, "cu"));
1201                         writer.AddStyleAttribute ("display", "block");
1202                         writer.AddStyleAttribute ("text-align", "center");
1203                         writer.AddAttribute ("onmouseover", string.Format ("javascript:Menu_OverScrollBtn ('{0}','{1}','{2}')", ClientID, item.Path, "u"));
1204                         writer.AddAttribute ("onmouseout", string.Format ("javascript:Menu_OutScrollBtn ('{0}','{1}','{2}')", ClientID, item.Path, "u"));
1205                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
1206                         
1207                         string src = ScrollUpImageUrl != "" ? ScrollUpImageUrl : Page.ClientScript.GetWebResourceUrl (typeof(Menu), "arrow_up.gif");
1208                         writer.AddAttribute ("src", src);
1209                         writer.AddAttribute ("alt", ScrollUpText);
1210                         writer.RenderBeginTag (HtmlTextWriterTag.Img);
1211                         writer.RenderEndTag (); // IMG
1212                         
1213                         writer.RenderEndTag (); // DIV scroll button
1214                 
1215                         writer.AddAttribute ("id", GetItemClientId (item, "cb"));       // Scroll container
1216                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
1217                         writer.AddAttribute ("id", GetItemClientId (item, "cc"));       // Content
1218                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
1219                         
1220                         RenderMenu (writer, item.ChildItems, true, true, item.Depth + 1);
1221                         
1222                         writer.RenderEndTag (); // DIV Content
1223                         writer.RenderEndTag (); // DIV Scroll container
1224
1225                         // Down button
1226                         writer.AddAttribute ("id", GetItemClientId (item, "cd"));
1227                         writer.AddStyleAttribute ("display", "block");
1228                         writer.AddStyleAttribute ("text-align", "center");
1229                         writer.AddAttribute ("onmouseover", string.Format ("javascript:Menu_OverScrollBtn ('{0}','{1}','{2}')", ClientID, item.Path, "d"));
1230                         writer.AddAttribute ("onmouseout", string.Format ("javascript:Menu_OutScrollBtn ('{0}','{1}','{2}')", ClientID, item.Path, "d"));
1231                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
1232                         
1233                         src = ScrollDownImageUrl != "" ? ScrollDownImageUrl : Page.ClientScript.GetWebResourceUrl (typeof(Menu), "arrow_down.gif");
1234                         writer.AddAttribute ("src", src);
1235                         writer.AddAttribute ("alt", ScrollDownText);
1236                         writer.RenderBeginTag (HtmlTextWriterTag.Img);
1237                         writer.RenderEndTag (); // IMG
1238                         
1239                         writer.RenderEndTag (); // DIV scroll button
1240                         
1241                         writer.RenderEndTag (); // DIV menu
1242                 }
1243                 
1244                 void RenderMenuBeginTagAttributes (HtmlTextWriter writer, bool dynamic, int menuLevel)
1245                 {
1246                         writer.AddAttribute ("cellpadding", "0");
1247                         writer.AddAttribute ("cellspacing", "0");
1248                         writer.AddAttribute ("border", "0");
1249
1250                         string cls = menuLevel==0 ? ControlStyle.CssClass : string.Empty;
1251                         
1252                         if (!dynamic && staticMenuStyle != null)
1253                                 cls += " " + staticMenuStyle.RegisteredCssClass;
1254                                 
1255                         if (levelSubMenuStyles != null && menuLevel < levelSubMenuStyles.Count)
1256                                 cls += " " + levelSubMenuStyles [menuLevel].RegisteredCssClass;
1257                         
1258                         if (cls.Length != 0)
1259                                 writer.AddAttribute ("class", cls);
1260                 }
1261                 
1262                 void RenderMenu (HtmlTextWriter writer, MenuItemCollection items, bool vertical, bool dynamic, int menuLevel)
1263                 {
1264                         RenderMenuBeginTag (writer, dynamic, menuLevel);
1265                         RenderMenuBody (writer, items, vertical, dynamic);
1266                         RenderMenuEndTag (writer);
1267                 }
1268                 
1269                 void RenderMenuBeginTag (HtmlTextWriter writer, bool dynamic, int menuLevel)
1270                 {
1271                         RenderMenuBeginTagAttributes (writer, dynamic, menuLevel);
1272                         writer.RenderBeginTag (HtmlTextWriterTag.Table);
1273                 }
1274                 
1275                 void RenderMenuEndTag (HtmlTextWriter writer)
1276                 {
1277                         writer.RenderEndTag ();
1278                 }
1279                 
1280                 void RenderMenuBody (HtmlTextWriter writer, MenuItemCollection items, bool vertical, bool dynamic)
1281                 {
1282                         if (!vertical) writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1283                         
1284                         for (int n=0; n<items.Count; n++) {
1285                                 MenuItem item = items [n];
1286                                 if (n > 0) {
1287                                         Unit itemSpacing = GetItemSpacing (item, dynamic);
1288                                         if (itemSpacing != Unit.Empty) {
1289                                                 if (vertical) {
1290                                                         writer.AddAttribute ("height", itemSpacing.ToString());
1291                                                         writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1292                                                         writer.RenderEndTag ();
1293                                                 } else {
1294                                                         writer.AddAttribute ("width", itemSpacing.ToString());
1295                                                         writer.RenderBeginTag (HtmlTextWriterTag.Td);
1296                                                         writer.RenderEndTag ();
1297                                                 }
1298                                         }
1299                                 }
1300                                 RenderMenuItem (writer, item);
1301                         }
1302                         
1303                         if (!vertical) writer.RenderEndTag ();  // TR
1304                 }
1305
1306                 private bool IsDynamicItem (MenuItem item) {
1307                         return item.Depth + 1 > StaticDisplayLevels;
1308                 }
1309
1310                 void RenderMenuItem (HtmlTextWriter writer, MenuItem item)
1311                 {
1312                         bool displayChildren = (item.Depth + 1 < StaticDisplayLevels + MaximumDynamicDisplayLevels);
1313                         bool dynamicChildren = displayChildren && (item.Depth + 1 >= StaticDisplayLevels) && item.ChildItems.Count > 0;
1314                         bool isDynamicItem = IsDynamicItem (item);
1315                         bool vertical = (Orientation == Orientation.Vertical) || isDynamicItem;
1316
1317                         if (vertical)
1318                                 writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1319                         
1320                         Style itemStyle = null;
1321                         if (levelMenuItemStyles != null && item.Depth < levelMenuItemStyles.Count)
1322                                 itemStyle = levelMenuItemStyles [item.Depth];
1323                         else if (isDynamicItem) {
1324                                 if (dynamicMenuItemStyle != null)
1325                                         itemStyle = dynamicMenuItemStyle;
1326                         } else {
1327                                 if (staticMenuItemStyle != null)
1328                                         itemStyle = staticMenuItemStyle;
1329                         }
1330                         
1331                         Style selectedStyle = null;
1332                         if (item == SelectedItem) {
1333                                 if (levelSelectedStyles != null && item.Depth < levelSelectedStyles.Count)
1334                                         selectedStyle = levelSelectedStyles [item.Depth];
1335                                 else if (isDynamicItem) {
1336                                         if (dynamicSelectedStyle != null)
1337                                                 selectedStyle = dynamicSelectedStyle;
1338                                 } else {
1339                                         if (staticSelectedStyle != null)
1340                                                 selectedStyle = staticSelectedStyle;
1341                                 }
1342                         }
1343                         
1344                         string cls = "";
1345                         if (itemStyle != null) cls += itemStyle.RegisteredCssClass + " ";
1346                         if (selectedStyle != null) cls += selectedStyle.RegisteredCssClass + " ";
1347                         if (cls != "")
1348                                 writer.AddAttribute ("class", cls);
1349                         
1350                         string parentId = isDynamicItem ? "'" + item.Parent.Path + "'" : "null";
1351                         if (dynamicChildren) {
1352                                 writer.AddAttribute ("onmouseover", string.Format ("javascript:Menu_OverItem ('{0}','{1}',{2})", ClientID, item.Path, parentId));
1353                                 writer.AddAttribute ("onmouseout", string.Format ("javascript:Menu_OutItem ('{0}','{1}')", ClientID, item.Path));
1354                         } else if (isDynamicItem) {
1355                                 writer.AddAttribute ("onmouseover", string.Format ("javascript:Menu_OverDynamicLeafItem ('{0}','{1}',{2})", ClientID, item.Path, parentId));
1356                                 writer.AddAttribute ("onmouseout", string.Format ("javascript:Menu_OutItem ('{0}','{1}',{2})", ClientID, item.Path, parentId));
1357                         } else {
1358                                 writer.AddAttribute ("onmouseover", string.Format ("javascript:Menu_OverStaticLeafItem ('{0}','{1}')", ClientID, item.Path));
1359                                 writer.AddAttribute ("onmouseout", string.Format ("javascript:Menu_OutItem ('{0}','{1}')", ClientID, item.Path));
1360                         }
1361                         
1362                         writer.AddAttribute ("id", GetItemClientId (item, "i"));
1363                         
1364                         writer.RenderBeginTag (HtmlTextWriterTag.Td);
1365
1366                         // Top separator image
1367
1368                         if (isDynamicItem && DynamicTopSeparatorImageUrl != "") {
1369                                 writer.AddAttribute ("src", DynamicTopSeparatorImageUrl);
1370                                 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1371                                 writer.RenderEndTag (); // IMG
1372                         } else  if (!isDynamicItem && StaticTopSeparatorImageUrl != "") {
1373                                 writer.AddAttribute ("src", StaticTopSeparatorImageUrl);
1374                                 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1375                                 writer.RenderEndTag (); // IMG
1376                         }
1377                         
1378                         // Menu item box
1379                         
1380                         writer.AddAttribute ("cellpadding", "0");
1381                         writer.AddAttribute ("cellspacing", "0");
1382                         writer.AddAttribute ("width", "100%");
1383                         writer.RenderBeginTag (HtmlTextWriterTag.Table);
1384                         writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1385                         
1386                         if (item.Depth > 0 && !isDynamicItem) {
1387                                 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1388                                 writer.AddStyleAttribute ("width", StaticSubMenuIndent.ToString ());
1389                                 writer.RenderBeginTag (HtmlTextWriterTag.Div);
1390                                 writer.RenderEndTag (); // DIV
1391                                 writer.RenderEndTag (); // TD
1392                         }
1393                         
1394                         if (item.ImageUrl != "") {
1395                                 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1396                                 RenderItemHref (writer, item);
1397                                 writer.RenderBeginTag (HtmlTextWriterTag.A);
1398                                 writer.AddAttribute ("src", item.ImageUrl);
1399                                 writer.AddAttribute ("border", "0");
1400                                 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1401                                 writer.RenderEndTag (); // IMG
1402                                 writer.RenderEndTag (); // A
1403                                 writer.RenderEndTag (); // TD
1404                         }
1405                         
1406                         // Menu item text
1407                         
1408                         writer.AddAttribute ("width", "100%");
1409                         if (!ItemWrap)
1410                                 writer.AddAttribute ("nowrap", "nowrap");
1411                         writer.RenderBeginTag (HtmlTextWriterTag.Td);
1412                         
1413                         RenderItemHref (writer, item);
1414                         writer.AddStyleAttribute ("text-decoration", "none");
1415                         writer.RenderBeginTag (HtmlTextWriterTag.A);
1416                         RenderItemContent (writer, item, isDynamicItem);
1417                         writer.RenderEndTag (); // A
1418                         
1419                         writer.RenderEndTag (); // TD
1420                         
1421                         // Popup image
1422                         
1423                         if (dynamicChildren) {
1424                                 string popOutImage = GetPopOutImage (item, isDynamicItem);
1425                                 if (popOutImage != null)
1426                                 {
1427                                         writer.RenderBeginTag (HtmlTextWriterTag.Td);
1428                                         writer.AddAttribute ("src", popOutImage);
1429                                         writer.AddAttribute ("border", "0");
1430                                         writer.RenderBeginTag (HtmlTextWriterTag.Img);
1431                                         writer.RenderEndTag (); // IMG
1432                                         writer.RenderEndTag (); // TD
1433                                 }
1434                         }
1435                         
1436                         writer.RenderEndTag (); // TR
1437                         writer.RenderEndTag (); // TABLE
1438                         
1439                         // Bottom separator image
1440                                 
1441                         string separatorImg = item.SeparatorImageUrl;
1442                         if (separatorImg.Length == 0) { 
1443                                 if (isDynamicItem) separatorImg = DynamicBottomSeparatorImageUrl;
1444                                 else separatorImg = StaticBottomSeparatorImageUrl;
1445                         }
1446                         if (separatorImg.Length > 0) {
1447                                 writer.AddAttribute ("src", separatorImg);
1448                                 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1449                                 writer.RenderEndTag (); // IMG
1450                         }
1451                                 
1452                         // Submenu
1453                                 
1454                         if (vertical) {
1455                                 if (displayChildren) {
1456                                         if (dynamicChildren) dynamicMenus.Add (item);
1457                                         else {
1458                                                 writer.AddAttribute ("width", "100%");
1459                                                 RenderMenu (writer, item.ChildItems, true, false, item.Depth + 1);
1460                                         }
1461                                 }
1462                                 
1463                                 writer.RenderEndTag (); // TD
1464                                 writer.RenderEndTag (); // TR
1465                         } else {
1466                                 writer.RenderEndTag (); // TD
1467                                 
1468                                 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1469                                 if (displayChildren) {
1470                                         if (dynamicChildren) dynamicMenus.Add (item);
1471                                         else RenderMenu (writer, item.ChildItems, false, false, item.Depth + 1);
1472                                 }
1473                                 writer.RenderEndTag (); // TD
1474                         }
1475                 }
1476
1477                 void RenderItemContent (HtmlTextWriter writer, MenuItem item, bool isDynamicItem) {
1478                         if (_menuItemControls!=null && _menuItemControls [item] != null) {
1479                                 ((Control) _menuItemControls [item]).Render (writer);
1480                         }
1481                         else if (isDynamicItem && DynamicItemFormatString.Length > 0) {
1482                                 writer.Write (string.Format (DynamicItemFormatString, item.Text));
1483                         }
1484                         else if (!isDynamicItem && StaticItemFormatString.Length > 0) {
1485                                 writer.Write (string.Format (StaticItemFormatString, item.Text));
1486                         }
1487                         else {
1488                                 writer.Write (item.Text);
1489                         }
1490                 }
1491                         
1492                 Unit GetItemSpacing (MenuItem item, bool dynamic)
1493                 {
1494                         Unit itemSpacing;
1495                         
1496                         if (item.Selected) {
1497                                 if (levelSelectedStyles != null && item.Depth < levelSelectedStyles.Count) {
1498                                         itemSpacing = levelSelectedStyles [item.Depth].ItemSpacing;
1499                                         if (itemSpacing != Unit.Empty) return itemSpacing;
1500                                 }
1501                                 
1502                                 if (dynamic) itemSpacing = DynamicSelectedStyle.ItemSpacing;
1503                                 else itemSpacing = StaticSelectedStyle.ItemSpacing;
1504                                 if (itemSpacing != Unit.Empty) return itemSpacing;
1505                         }
1506                         
1507                         if (levelMenuItemStyles != null && item.Depth < levelMenuItemStyles.Count) {
1508                                 itemSpacing = levelMenuItemStyles [item.Depth].ItemSpacing;
1509                                 if (itemSpacing != Unit.Empty) return itemSpacing;
1510                         }
1511                         
1512                         if (dynamic) return DynamicMenuItemStyle.ItemSpacing;
1513                         else return StaticMenuItemStyle.ItemSpacing;
1514                 }
1515                 
1516                 string GetPopOutImage (MenuItem item, bool isDynamicItem)
1517                 {
1518                         if (item.PopOutImageUrl != "")
1519                                 return item.PopOutImageUrl;
1520
1521                         if (isDynamicItem) {
1522                                 if (DynamicPopOutImageUrl != "")
1523                                         return DynamicPopOutImageUrl;
1524                                 if (DynamicEnableDefaultPopOutImage)
1525                                         return AssemblyResourceLoader.GetResourceUrl (typeof(Menu), "arrow_plus.gif");
1526                         } else {
1527                                 if (StaticPopOutImageUrl != "")
1528                                         return StaticPopOutImageUrl;
1529                                 if (StaticEnableDefaultPopOutImage)
1530                                         return AssemblyResourceLoader.GetResourceUrl (typeof(Menu), "arrow_plus.gif");
1531                         }
1532                         return null;
1533                 }
1534                         
1535                 void RenderItemHref (HtmlTextWriter writer, MenuItem item)
1536                 {
1537                         if (!item.BranchEnabled) {
1538                                 writer.AddAttribute ("disabled", "true");
1539                         }
1540                         else if (!item.Selectable) {
1541                                 writer.AddAttribute ("href", "#");
1542                                 writer.AddStyleAttribute ("cursor", "text");
1543                         }
1544                         else if (item.NavigateUrl != "") {
1545                                 writer.AddAttribute ("href", item.NavigateUrl);
1546                                 if (item.Target != "")
1547                                         writer.AddAttribute ("target", item.Target);
1548                                 else if (Target != "")
1549                                         writer.AddAttribute ("target", Target);
1550                         }
1551                         else {
1552                                 writer.AddAttribute ("href", GetClientEvent (item));
1553                         }
1554
1555                 }
1556                 
1557                 string GetItemClientId (MenuItem item, string sufix)
1558                 {
1559                         return ClientID + "_" + item.Path + sufix;
1560                 }
1561                                                         
1562                 string GetClientEvent (MenuItem item)
1563                 {
1564                         return Page.ClientScript.GetPostBackClientHyperlink (this, item.Path);
1565                 }
1566         }
1567 }
1568
1569 #endif