2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[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         public class Menu : HierarchicalDataBoundControl, IPostBackEventHandler, INamingContainer
47         {
48                 MenuItemStyle dynamicMenuItemStyle;
49                 SubMenuStyle dynamicMenuStyle;
50                 MenuItemStyle dynamicSelectedStyle;
51                 MenuItemStyle staticMenuItemStyle;
52                 SubMenuStyle staticMenuStyle;
53                 MenuItemStyle staticSelectedStyle;
54                 Style staticHoverStyle;
55                 Style dynamicHoverStyle;
56
57                 MenuItemStyleCollection levelMenuItemStyles;
58                 MenuItemStyleCollection levelSelectedStyles;
59                 ITemplate staticItemTemplate;
60                 ITemplate dynamicItemTemplate;
61                 
62                 MenuItemCollection items;
63                 MenuItemBindingCollection dataBindings;
64                 MenuItem selectedItem;
65                 Hashtable bindings;
66                 ArrayList dynamicMenus;
67                 
68                 private static readonly object MenuItemClickEvent = new object();
69                 
70                 public event MenuEventHandler MenuItemClick {
71                         add { Events.AddHandler (MenuItemClickEvent, value); }
72                         remove { Events.RemoveHandler (MenuItemClickEvent, value); }
73                 }
74                 
75                 protected virtual void OnMenuItemClick (MenuEventArgs e)
76                 {
77                         if (Events != null) {
78                                 MenuEventHandler eh = (MenuEventHandler) Events [MenuItemClickEvent];
79                                 if (eh != null) eh (this, e);
80                         }
81                 }
82
83                 [PersistenceMode (PersistenceMode.InnerProperty)]
84                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
85                 [Editor ("System.Web.UI.Design.MenuItemBindingsEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
86                 public virtual MenuItemBindingCollection DataBindings {
87                         get {
88                                 if (dataBindings == null) {
89                                         dataBindings = new MenuItemBindingCollection ();
90                                         if (IsTrackingViewState)
91                                                 ((IStateManager)dataBindings).TrackViewState();
92                                 }
93                                 return dataBindings;
94                         }
95                 }
96
97                 [DefaultValue (500)]
98                 [ThemeableAttribute (false)]
99                 public virtual int DisappearAfter {
100                         get {
101                                 object o = ViewState ["DisappearAfter"];
102                                 if (o != null) return (int)o;
103                                 return 500;
104                         }
105                         set {
106                                 ViewState["DisappearAfter"] = value;
107                         }
108                 }
109
110                 [ThemeableAttribute (false)]
111                 [DefaultValue ("")]
112                 [UrlProperty]
113                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
114                 public virtual string DynamicBottomSeparatorImageUrl {
115                         get {
116                                 object o = ViewState ["dbsiu"];
117                                 if (o != null) return (string)o;
118                                 return "";
119                         }
120                         set {
121                                 ViewState["dbsiu"] = value;
122                         }
123                 }
124
125                 [DefaultValue ("")]
126                 [UrlProperty]
127                 [WebCategory ("Appearance")]
128                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
129                 public virtual string DynamicTopSeparatorImageUrl {
130                         get {
131                                 object o = ViewState ["dtsiu"];
132                                 if (o != null) return (string)o;
133                                 return "";
134                         }
135                         set {
136                                 ViewState["dtsiu"] = value;
137                         }
138                 }
139
140                 [DefaultValue ("")]
141                 [UrlProperty]
142                 [WebCategory ("Appearance")]
143                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
144                 public virtual string StaticBottomSeparatorImageUrl {
145                         get {
146                                 object o = ViewState ["sbsiu"];
147                                 if (o != null) return (string)o;
148                                 return "";
149                         }
150                         set {
151                                 ViewState["sbsiu"] = value;
152                         }
153                 }
154
155                 [DefaultValue ("")]
156                 [UrlProperty]
157                 [WebCategory ("Appearance")]
158                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
159                 public virtual string StaticTopSeparatorImageUrl {
160                         get {
161                                 object o = ViewState ["stsiu"];
162                                 if (o != null) return (string)o;
163                                 return "";
164                         }
165                         set {
166                                 ViewState["stsiu"] = value;
167                         }
168                 }
169
170                 [DefaultValue (Orientation.Vertical)]
171                 public virtual Orientation Orientation {
172                         get {
173                                 object o = ViewState ["Orientation"];
174                                 if (o != null) return (Orientation) o;
175                                 return Orientation.Vertical;
176                         }
177                         set {
178                                 ViewState["Orientation"] = value;
179                         }
180                 }
181
182                 [DefaultValue (1)]
183                 [ThemeableAttribute (false)]
184                 public virtual int StaticDisplayLevels {
185                         get {
186                                 object o = ViewState ["StaticDisplayLevels"];
187                                 if (o != null) return (int)o;
188                                 return 1;
189                         }
190                         set {
191                                 if (value < 1) throw new ArgumentOutOfRangeException ();
192                                 ViewState["StaticDisplayLevels"] = value;
193                         }
194                 }
195
196                 [DefaultValue ("16px")]
197                 [ThemeableAttribute (false)]
198                 public Unit StaticSubMenuIndent {
199                         get {
200                                 object o = ViewState ["StaticSubMenuIndent"];
201                                 if (o != null) return (Unit)o;
202                                 return new Unit (16);
203                         }
204                         set {
205                                 ViewState["StaticSubMenuIndent"] = value;
206                         }
207                 }
208
209                 [ThemeableAttribute (false)]
210                 [DefaultValue (3)]
211                 public virtual int MaximumDynamicDisplayLevels {
212                         get {
213                                 object o = ViewState ["MaximumDynamicDisplayLevels"];
214                                 if (o != null) return (int)o;
215                                 return 3;
216                         }
217                         set {
218                                 if (value < 0) throw new ArgumentOutOfRangeException ();
219                                 ViewState["MaximumDynamicDisplayLevels"] = value;
220                         }
221                 }
222
223                 [DefaultValue (0)]
224                 public virtual int DynamicVerticalOffset {
225                         get {
226                                 object o = ViewState ["DynamicVerticalOffset"];
227                                 if (o != null) return (int)o;
228                                 return 0;
229                         }
230                         set {
231                                 ViewState["DynamicVerticalOffset"] = value;
232                         }
233                 }
234
235                 [DefaultValue (0)]
236                 public virtual int DynamicHorizontalOffset {
237                         get {
238                                 object o = ViewState ["DynamicHorizontalOffset"];
239                                 if (o != null) return (int)o;
240                                 return 0;
241                         }
242                         set {
243                                 ViewState["DynamicHorizontalOffset"] = value;
244                         }
245                 }
246
247                 [DefaultValue (true)]
248                 public virtual bool DynamicEnableDefaultPopOutImage {
249                         get {
250                                 object o = ViewState ["dedpoi"];
251                                 if (o != null) return (bool)o;
252                                 return true;
253                         }
254                         set {
255                                 ViewState["dedpoi"] = value;
256                         }
257                 }
258
259                 [DefaultValue (true)]
260                 public virtual bool StaticEnableDefaultPopOutImage {
261                         get {
262                                 object o = ViewState ["sedpoi"];
263                                 if (o != null) return (bool)o;
264                                 return true;
265                         }
266                         set {
267                                 ViewState["sedpoi"] = value;
268                         }
269                 }
270
271                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
272                 [PersistenceMode (PersistenceMode.InnerProperty)]
273                 [Editor ("System.Web.UI.Design.MenuItemCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
274                 public virtual MenuItemCollection Items {
275                         get {
276                                 if (items == null) {
277                                         items = new MenuItemCollection (this);
278                                         if (IsTrackingViewState)
279                                                 ((IStateManager)items).TrackViewState();
280                                 }
281                                 return items;
282                         }
283                 }
284
285                 [DefaultValue ('/')]
286                 public virtual char PathSeparator {
287                         get {
288                                 object o = ViewState ["PathSeparator"];
289                                 if(o != null) return (char)o;
290                                 return '/';
291                         }
292                         set {
293                                 ViewState ["PathSeparator"] = value;
294                         }
295                 }
296
297                 [DefaultValue (false)]
298                 public virtual bool ItemWrap {
299                         get {
300                                 object o = ViewState ["ItemWrap"];
301                                 if(o != null) return (bool)o;
302                                 return false;
303                         }
304                         set {
305                                 ViewState ["ItemWrap"] = value;
306                         }
307                 }
308
309                 [PersistenceMode (PersistenceMode.InnerProperty)]
310                 [NotifyParentProperty (true)]
311                 [DefaultValue (null)]
312                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
313                 public virtual MenuItemStyle DynamicMenuItemStyle {
314                         get {
315                                 if (dynamicMenuItemStyle == null) {
316                                         dynamicMenuItemStyle = new MenuItemStyle ();
317                                         if (IsTrackingViewState)
318                                                 dynamicMenuItemStyle.TrackViewState();
319                                 }
320                                 return dynamicMenuItemStyle;
321                         }
322                 }
323                 
324                 [PersistenceMode (PersistenceMode.InnerProperty)]
325                 [NotifyParentProperty (true)]
326                 [DefaultValue (null)]
327                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
328                 public virtual MenuItemStyle DynamicSelectedStyle {
329                         get {
330                                 if (dynamicSelectedStyle == null) {
331                                         dynamicSelectedStyle = new MenuItemStyle ();
332                                         if (IsTrackingViewState)
333                                                 dynamicSelectedStyle.TrackViewState();
334                                 }
335                                 return dynamicSelectedStyle;
336                         }
337                 }
338                 
339                 [PersistenceMode (PersistenceMode.InnerProperty)]
340                 [NotifyParentProperty (true)]
341                 [DefaultValue (null)]
342                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
343                 public virtual SubMenuStyle DynamicMenuStyle {
344                         get {
345                                 if (dynamicMenuStyle == null) {
346                                         dynamicMenuStyle = new SubMenuStyle ();
347                                         if (IsTrackingViewState)
348                                                 dynamicMenuStyle.TrackViewState();
349                                 }
350                                 return dynamicMenuStyle;
351                         }
352                 }
353                 
354                 [PersistenceMode (PersistenceMode.InnerProperty)]
355                 [NotifyParentProperty (true)]
356                 [DefaultValue (null)]
357                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
358                 public virtual MenuItemStyle StaticMenuItemStyle {
359                         get {
360                                 if (staticMenuItemStyle == null) {
361                                         staticMenuItemStyle = new MenuItemStyle ();
362                                         if (IsTrackingViewState)
363                                                 staticMenuItemStyle.TrackViewState();
364                                 }
365                                 return staticMenuItemStyle;
366                         }
367                 }
368                 
369                 [PersistenceMode (PersistenceMode.InnerProperty)]
370                 [NotifyParentProperty (true)]
371                 [DefaultValue (null)]
372                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
373                 public virtual MenuItemStyle StaticSelectedStyle {
374                         get {
375                                 if (staticSelectedStyle == null) {
376                                         staticSelectedStyle = new MenuItemStyle ();
377                                         if (IsTrackingViewState)
378                                                 staticSelectedStyle.TrackViewState();
379                                 }
380                                 return staticSelectedStyle;
381                         }
382                 }
383                 
384                 [PersistenceMode (PersistenceMode.InnerProperty)]
385                 [NotifyParentProperty (true)]
386                 [DefaultValue (null)]
387                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
388                 public virtual SubMenuStyle StaticMenuStyle {
389                         get {
390                                 if (staticMenuStyle == null) {
391                                         staticMenuStyle = new SubMenuStyle ();
392                                         if (IsTrackingViewState)
393                                                 staticMenuStyle.TrackViewState();
394                                 }
395                                 return staticMenuStyle;
396                         }
397                 }
398
399                 [PersistenceMode (PersistenceMode.InnerProperty)]
400                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
401                 public virtual MenuItemStyleCollection LevelMenuItemStyles {
402                         get {
403                                 if (levelMenuItemStyles == null) {
404                                         levelMenuItemStyles = new MenuItemStyleCollection ();
405                                         if (IsTrackingViewState)
406                                                 ((IStateManager)levelMenuItemStyles).TrackViewState();
407                                 }
408                                 return levelMenuItemStyles;
409                         }
410                 }
411
412                 [PersistenceMode (PersistenceMode.InnerProperty)]
413                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
414                 public virtual MenuItemStyleCollection LevelSelectedStyles {
415                         get {
416                                 if (levelSelectedStyles == null) {
417                                         levelSelectedStyles = new MenuItemStyleCollection ();
418                                         if (IsTrackingViewState)
419                                                 ((IStateManager)levelSelectedStyles).TrackViewState();
420                                 }
421                                 return levelSelectedStyles;
422                         }
423                 }
424
425                 [PersistenceMode (PersistenceMode.InnerProperty)]
426                 [NotifyParentProperty (true)]
427                 [DefaultValue (null)]
428                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
429                 public virtual Style DynamicHoverStyle {
430                         get {
431                                 if (dynamicHoverStyle == null) {
432                                         dynamicHoverStyle = new Style ();
433                                         if (IsTrackingViewState)
434                                                 dynamicHoverStyle.TrackViewState();
435                                 }
436                                 return dynamicHoverStyle;
437                         }
438                 }
439                 
440                 [PersistenceMode (PersistenceMode.InnerProperty)]
441                 [NotifyParentProperty (true)]
442                 [DefaultValue (null)]
443                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
444                 public virtual Style StaticHoverStyle {
445                         get {
446                                 if (staticHoverStyle == null) {
447                                         staticHoverStyle = new Style ();
448                                         if (IsTrackingViewState)
449                                                 staticHoverStyle.TrackViewState();
450                                 }
451                                 return staticHoverStyle;
452                         }
453                 }
454                 
455                 [DefaultValue ("")]
456                 [UrlProperty]
457                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
458                 public virtual string ScrollDownImageUrl {
459                         get {
460                                 object o = ViewState ["sdiu"];
461                                 if (o != null) return (string)o;
462                                 return "";
463                         }
464                         set {
465                                 ViewState["sdiu"] = value;
466                         }
467                 }
468
469                 [DefaultValue ("")]
470                 [UrlProperty]
471                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
472                 public virtual string ScrollUpImageUrl {
473                         get {
474                                 object o = ViewState ["suiu"];
475                                 if (o != null) return (string)o;
476                                 return "";
477                         }
478                         set {
479                                 ViewState["suiu"] = value;
480                         }
481                 }
482
483                 [Localizable (true)]
484                 public virtual string ScrollDownText {
485                         get {
486                                 object o = ViewState ["ScrollDownText"];
487                                 if (o != null) return (string) o;
488                                 return "";
489                         }
490                         set {
491                                 ViewState["ScrollDownText"] = value;
492                         }
493                 }
494
495                 [Localizable (true)]
496                 public virtual string ScrollUpText {
497                         get {
498                                 object o = ViewState ["ScrollUpText"];
499                                 if (o != null) return (string) o;
500                                 return "";
501                         }
502                         set {
503                                 ViewState["ScrollUpText"] = value;
504                         }
505                 }
506
507                 [DefaultValue ("")]
508                 [UrlProperty]
509                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
510                 public virtual string DynamicPopOutImageUrl {
511                         get {
512                                 object o = ViewState ["dpoiu"];
513                                 if (o != null) return (string)o;
514                                 return "";
515                         }
516                         set {
517                                 ViewState["dpoiu"] = value;
518                         }
519                 }
520
521                 [DefaultValue ("")]
522                 [UrlProperty]
523                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
524                 public virtual string StaticPopOutImageUrl {
525                         get {
526                                 object o = ViewState ["spoiu"];
527                                 if (o != null) return (string)o;
528                                 return "";
529                         }
530                         set {
531                                 ViewState["spoiu"] = value;
532                         }
533                 }
534
535                 [DefaultValue ("")]
536                 public virtual string Target {
537                         get {
538                                 object o = ViewState ["Target"];
539                                 if (o != null) return (string) o;
540                                 return "";
541                         }
542                         set {
543                                 ViewState["Target"] = value;
544                         }
545                 }
546
547                 [DefaultValue (null)]
548                 [TemplateContainer (typeof(MenuItemTemplateContainer), BindingDirection.OneWay)]
549                 [PersistenceMode (PersistenceMode.InnerProperty)]
550                 public ITemplate StaticItemTemplate {
551                         get { return staticItemTemplate; }
552                         set { staticItemTemplate = value; }
553                 }
554                 
555                 [DefaultValue (null)]
556                 [TemplateContainer (typeof(MenuItemTemplateContainer), BindingDirection.OneWay)]
557                 [PersistenceMode (PersistenceMode.InnerProperty)]
558                 public ITemplate DynamicItemTemplate {
559                         get { return dynamicItemTemplate; }
560                         set { dynamicItemTemplate = value; }
561                 }
562                 
563                 [Browsable (false)]
564                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
565                 public MenuItem SelectedItem {
566                         get { return selectedItem; }
567                 }
568
569                 [Browsable (false)]
570                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
571                 public string SelectedValue {
572                         get { return selectedItem != null ? selectedItem.Value : null; }
573                 }
574
575                 internal void SetSelectedItem (MenuItem item)
576                 {
577                         if (selectedItem == item) return;
578                         if (selectedItem != null)
579                                 selectedItem.SelectedFlag = false;
580                         selectedItem = item;
581                         selectedItem.SelectedFlag = true;
582                 }
583                 
584                 public MenuItem FindItem (string valuePath)
585                 {
586                         if (valuePath == null) throw new ArgumentNullException ("valuePath");
587                         string[] path = valuePath.Split (PathSeparator);
588                         int n = 0;
589                         MenuItemCollection col = Items;
590                         bool foundBranch = true;
591                         while (col.Count > 0 && foundBranch) {
592                                 foundBranch = false;
593                                 foreach (MenuItem item in col) {
594                                         if (item.Value == path [n]) {
595                                                 if (++n == path.Length) return item;
596                                                 col = item.ChildItems;
597                                                 foundBranch = true;
598                                                 break;
599                                         }
600                                 }
601                         }
602                         return null;
603                 }
604                 
605                 string GetBindingKey (string dataMember, int depth)
606                 {
607                         return dataMember + " " + depth;
608                 }
609                 
610                 internal MenuItemBinding FindBindingForItem (string type, int depth)
611                 {
612                         if (bindings == null) return null;
613
614                         MenuItemBinding bin = (MenuItemBinding) bindings [GetBindingKey (type, depth)];
615                         if (bin != null) return bin;
616                         
617                         bin = (MenuItemBinding) bindings [GetBindingKey (type, -1)];
618                         if (bin != null) return bin;
619                         
620                         bin = (MenuItemBinding) bindings [GetBindingKey ("", depth)];
621                         if (bin != null) return bin;
622                         
623                         bin = (MenuItemBinding) bindings [GetBindingKey ("", -1)];
624                         return bin;
625                 }
626                 
627                 protected internal override void PerformDataBinding ()
628                 {
629                         base.PerformDataBinding ();
630                         HierarchicalDataSourceView data = GetData ("");
631                         IHierarchicalEnumerable e = data.Select ();
632                         foreach (object obj in e) {
633                                 IHierarchyData hdata = e.GetHierarchyData (obj);
634                                 MenuItem item = new MenuItem ();
635                                 item.Bind (hdata);
636                                 Items.Add (item);
637                         }
638                 }
639                 
640                 void IPostBackEventHandler.RaisePostBackEvent (string eventArgument)
641                 {
642                         MenuItem item = FindItemByPos (eventArgument);
643                         if (item == null) return;
644                         item.Selected = true;
645                         OnMenuItemClick (new MenuEventArgs (item));
646                 }
647                 
648                 MenuItem FindItemByPos (string path)
649                 {
650                         string[] indexes = path.Split ('_');
651                         MenuItem item = null;
652                         
653                         foreach (string index in indexes) {
654                                 int i = int.Parse (index);
655                                 if (item == null) {
656                                         if (i >= Items.Count) return null;
657                                         item = Items [i];
658                                 } else {
659                                         if (i >= item.ChildItems.Count) return null;
660                                         item = item.ChildItems [i];
661                                 }
662                         }
663                         return item;
664                 }
665                 
666                 protected override HtmlTextWriterTag TagKey {
667                         get { return HtmlTextWriterTag.Table; }
668                 }
669                 
670                 protected override void TrackViewState()
671                 {
672                         EnsureDataBound ();
673                         
674                         base.TrackViewState();
675                         if (dataBindings != null) {
676                                 ((IStateManager)dataBindings).TrackViewState ();
677                         }
678                         if (items != null) {
679                                 ((IStateManager)items).TrackViewState();
680                         }
681                         if (dynamicMenuItemStyle != null)
682                                 dynamicMenuItemStyle.TrackViewState ();
683                         if (dynamicMenuStyle != null)
684                                 dynamicMenuStyle.TrackViewState ();
685                         if (levelMenuItemStyles != null)
686                                 ((IStateManager)levelMenuItemStyles).TrackViewState();
687                         if (levelSelectedStyles != null)
688                                 ((IStateManager)levelSelectedStyles).TrackViewState();
689                         if (dynamicSelectedStyle != null)
690                                 dynamicSelectedStyle.TrackViewState();
691                         if (staticMenuItemStyle != null)
692                                 staticMenuItemStyle.TrackViewState ();
693                         if (staticMenuStyle != null)
694                                 staticMenuStyle.TrackViewState ();
695                         if (staticSelectedStyle != null)
696                                 staticSelectedStyle.TrackViewState();
697                         if (staticHoverStyle != null)
698                                 staticHoverStyle.TrackViewState();
699                         if (dynamicHoverStyle != null)
700                                 dynamicHoverStyle.TrackViewState();
701                 }
702
703                 protected override object SaveViewState()
704                 {
705                         object[] states = new object [13];
706                         states[0] = base.SaveViewState ();
707                         states[1] = dataBindings == null ? null : ((IStateManager)dataBindings).SaveViewState();
708                         states[2] = items == null ? null : ((IStateManager)items).SaveViewState();
709                         states[3] = dynamicMenuItemStyle == null ? null : dynamicMenuItemStyle.SaveViewState();
710                         states[4] = dynamicMenuStyle == null ? null : dynamicMenuStyle.SaveViewState();
711                         states[5] = levelMenuItemStyles == null ? null : ((IStateManager)levelMenuItemStyles).SaveViewState();
712                         states[6] = levelSelectedStyles == null ? null : ((IStateManager)levelSelectedStyles).SaveViewState();
713                         states[7] = dynamicSelectedStyle == null ? null : dynamicSelectedStyle.SaveViewState();
714                         states[8] = (staticMenuItemStyle == null ? null : staticMenuItemStyle.SaveViewState());
715                         states[9] = staticMenuStyle == null ? null : staticMenuStyle.SaveViewState();
716                         states[10] = staticSelectedStyle == null ? null : staticSelectedStyle.SaveViewState();
717                         states[11] = staticHoverStyle == null ? null : staticHoverStyle.SaveViewState();
718                         states[12] = dynamicHoverStyle == null ? null : dynamicHoverStyle.SaveViewState();
719
720                         for (int i = states.Length - 1; i >= 0; i--) {
721                                 if (states [i] != null)
722                                         return states;
723                         }
724
725                         return null;
726                 }
727
728                 protected override void LoadViewState (object savedState)
729                 {
730                         if (savedState == null)
731                                 return;
732
733                         object [] states = (object []) savedState;
734                         base.LoadViewState (states[0]);
735                         
736                         if (states[1] != null)
737                                 ((IStateManager)dataBindings).LoadViewState(states[1]);
738                         if (states[2] != null)
739                                 ((IStateManager)Items).LoadViewState(states[2]);
740                         if (states[3] != null)
741                                 dynamicMenuItemStyle.LoadViewState (states[3]);
742                         if (states[4] != null)
743                                 dynamicMenuStyle.LoadViewState (states[4]);
744                         if (states[5] != null)
745                                 ((IStateManager)levelMenuItemStyles).LoadViewState(states[5]);
746                         if (states[6] != null)
747                                 ((IStateManager)levelSelectedStyles).LoadViewState(states[6]);
748                         if (states[7] != null)
749                                 dynamicSelectedStyle.LoadViewState (states[7]);
750                         if (states[8] != null)
751                                 staticMenuItemStyle.LoadViewState (states[8]);
752                         if (states[9] != null)
753                                 staticMenuStyle.LoadViewState (states[9]);
754                         if (states[10] != null)
755                                 staticSelectedStyle.LoadViewState (states[10]);
756                         if (states[11] != null)
757                                 staticHoverStyle.LoadViewState (states[11]);
758                         if (states[12] != null)
759                                 dynamicHoverStyle.LoadViewState (states[12]);
760                 }
761                 
762                 protected override void OnPreRender (EventArgs e)
763                 {
764                         base.OnPreRender (e);
765                         
766                         if (!Page.ClientScript.IsClientScriptIncludeRegistered (typeof(Menu), "Menu.js")) {
767                                 string url = Page.GetWebResourceUrl (typeof(Menu), "Menu.js");
768                                 Page.ClientScript.RegisterClientScriptInclude (typeof(Menu), "Menu.js", url);
769                         }
770                         
771                         string cmenu = ClientID + "_data";
772                         string script = string.Format ("var {0} = new Object ();\n", cmenu);
773                         script += string.Format ("{0}.disappearAfter = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (DisappearAfter));
774                         script += string.Format ("{0}.vertical = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (Orientation == Orientation.Vertical));
775                         if (DynamicHorizontalOffset != 0)
776                                 script += string.Format ("{0}.dho = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (DynamicHorizontalOffset));
777                         if (DynamicVerticalOffset != 0)
778                                 script += string.Format ("{0}.dvo = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (DynamicVerticalOffset));
779                                 
780                         // The order in which styles are defined matters when more than one class
781                         // is assigned to an element
782                         
783                         if (dynamicMenuStyle != null)
784                                 RegisterItemStyle (dynamicMenuStyle);
785                         if (staticMenuStyle != null)
786                                 RegisterItemStyle (staticMenuStyle);
787                 
788                         if (staticMenuItemStyle != null)
789                                 RegisterItemStyle (staticMenuItemStyle);
790                         if (staticSelectedStyle != null)
791                                 RegisterItemStyle (staticSelectedStyle);
792
793                         if (dynamicMenuItemStyle != null)
794                                 RegisterItemStyle (dynamicMenuItemStyle);
795                         if (dynamicSelectedStyle != null)
796                                 RegisterItemStyle (dynamicSelectedStyle);
797
798                         if (levelMenuItemStyles != null)
799                                 foreach (Style style in levelMenuItemStyles)
800                                         RegisterItemStyle (style);
801
802                         if (levelSelectedStyles != null)
803                                 foreach (Style style in levelSelectedStyles)
804                                         RegisterItemStyle (style);
805                         
806                         if (dynamicHoverStyle != null)
807                                 RegisterItemStyle (dynamicHoverStyle);
808                         if (staticHoverStyle != null)
809                                 RegisterItemStyle (staticHoverStyle);
810
811                         if (staticHoverStyle != null)
812                                 script += string.Format ("{0}.staticHover = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (staticHoverStyle.RegisteredCssClass));
813                         if (dynamicHoverStyle != null)
814                                 script += string.Format ("{0}.dynamicHover = {1};\n", cmenu, ClientScriptManager.GetScriptLiteral (dynamicHoverStyle.RegisteredCssClass));
815                         
816                         Page.ClientScript.RegisterStartupScript (typeof(Menu), ClientID, script, true);
817
818                         if (dataBindings != null && dataBindings.Count > 0) {
819                                 bindings = new Hashtable ();
820                                 foreach (TreeNodeBinding bin in dataBindings) {
821                                         string key = GetBindingKey (bin.DataMember, bin.Depth);
822                                         bindings [key] = bin;
823                                 }
824                         }
825                         else
826                                 bindings = null;
827                 }
828                 
829                 void RegisterItemStyle (Style baseStyle)
830                 {
831                         Page.Header.StyleSheet.RegisterStyle (baseStyle, this);
832                         Style ts = new Style ();
833                         ts.CopyTextStylesFrom (baseStyle);
834                         Page.Header.StyleSheet.CreateStyleRule (ts, "." + baseStyle.RegisteredCssClass + " A", this);
835                 }
836                 
837                 public override void RenderBeginTag (HtmlTextWriter writer)
838                 {
839                         RenderMenuBeginTagAttributes (writer, false);
840                         base.RenderBeginTag (writer);
841                 }
842                 
843                 public override void RenderEndTag (HtmlTextWriter writer)
844                 {
845                         base.RenderEndTag (writer);
846                         
847                         // Render dynamic menus outside the main control tag
848                         for (int n=0; n<dynamicMenus.Count; n++) {
849                                 MenuItem item = (MenuItem) dynamicMenus [n];
850                                 RenderDynamicMenu (writer, item);
851                         }
852                         dynamicMenus = null;
853                 }
854                 
855                 protected override void RenderContents (HtmlTextWriter writer)
856                 {
857                         dynamicMenus = new ArrayList ();
858                         RenderMenuBody (writer, Items, Orientation == Orientation.Vertical, false);
859                 }
860                 
861                 void RenderDynamicMenu (HtmlTextWriter writer, MenuItem item)
862                 {
863                         if (dynamicMenuStyle != null)
864                                 writer.AddAttribute ("class", dynamicMenuStyle.RegisteredCssClass);
865                         
866                         writer.AddStyleAttribute ("visibility", "hidden");
867                         writer.AddStyleAttribute ("position", "absolute");
868                         writer.AddStyleAttribute ("left", "0px");
869                         writer.AddStyleAttribute ("top", "0px");
870                         writer.AddAttribute ("id", GetItemClientId (item, "s"));
871                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
872
873                         // Up button
874                         writer.AddAttribute ("id", GetItemClientId (item, "cu"));
875                         writer.AddStyleAttribute ("display", "block");
876                         writer.AddStyleAttribute ("text-align", "center");
877                         writer.AddAttribute ("onmouseover", string.Format ("javascript:Menu_OverScrollBtn ('{0}','{1}','{2}')", ClientID, item.Path, "u"));
878                         writer.AddAttribute ("onmouseout", string.Format ("javascript:Menu_OutScrollBtn ('{0}','{1}','{2}')", ClientID, item.Path, "u"));
879                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
880                         
881                         string src = ScrollUpImageUrl != "" ? ScrollUpImageUrl : Page.GetWebResourceUrl (typeof(Menu), "arrow_up.gif");
882                         writer.AddAttribute ("src", src);
883                         writer.AddAttribute ("alt", ScrollUpText);
884                         writer.RenderBeginTag (HtmlTextWriterTag.Img);
885                         writer.RenderEndTag (); // IMG
886                         
887                         writer.RenderEndTag (); // DIV scroll button
888                 
889                         writer.AddAttribute ("id", GetItemClientId (item, "cb"));       // Scroll container
890                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
891                         writer.AddAttribute ("id", GetItemClientId (item, "cc"));       // Content
892                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
893                         
894                         RenderMenu (writer, item.ChildItems, true, true);
895                         
896                         writer.RenderEndTag (); // DIV Content
897                         writer.RenderEndTag (); // DIV Scroll container
898
899                         // Down button
900                         writer.AddAttribute ("id", GetItemClientId (item, "cd"));
901                         writer.AddStyleAttribute ("display", "block");
902                         writer.AddStyleAttribute ("text-align", "center");
903                         writer.AddAttribute ("onmouseover", string.Format ("javascript:Menu_OverScrollBtn ('{0}','{1}','{2}')", ClientID, item.Path, "d"));
904                         writer.AddAttribute ("onmouseout", string.Format ("javascript:Menu_OutScrollBtn ('{0}','{1}','{2}')", ClientID, item.Path, "d"));
905                         writer.RenderBeginTag (HtmlTextWriterTag.Div);
906                         
907                         src = ScrollDownImageUrl != "" ? ScrollDownImageUrl : Page.GetWebResourceUrl (typeof(Menu), "arrow_down.gif");
908                         writer.AddAttribute ("src", src);
909                         writer.AddAttribute ("alt", ScrollDownText);
910                         writer.RenderBeginTag (HtmlTextWriterTag.Img);
911                         writer.RenderEndTag (); // IMG
912                         
913                         writer.RenderEndTag (); // DIV scroll button
914                         
915                         writer.RenderEndTag (); // DIV menu
916                 }
917                 
918                 void RenderMenuBeginTagAttributes (HtmlTextWriter writer, bool dynamic)
919                 {
920                         writer.AddAttribute ("cellpadding", "0");
921                         writer.AddAttribute ("cellspacing", "0");
922
923                         if (!dynamic && staticMenuStyle != null)
924                                 writer.AddAttribute ("class", staticMenuStyle.RegisteredCssClass);
925                 }
926                 
927                 void RenderMenu (HtmlTextWriter writer, MenuItemCollection items, bool vertical, bool dynamic)
928                 {
929                         RenderMenuBeginTag (writer, dynamic);
930                         RenderMenuBody (writer, items, vertical, dynamic);
931                         RenderMenuEndTag (writer);
932                 }
933                 
934                 void RenderMenuBeginTag (HtmlTextWriter writer, bool dynamic)
935                 {
936                         RenderMenuBeginTagAttributes (writer, dynamic);
937                         writer.RenderBeginTag (HtmlTextWriterTag.Table);
938                 }
939                 
940                 void RenderMenuEndTag (HtmlTextWriter writer)
941                 {
942                         writer.RenderEndTag ();
943                 }
944                 
945                 void RenderMenuBody (HtmlTextWriter writer, MenuItemCollection items, bool vertical, bool dynamic)
946                 {
947                         if (!vertical) writer.RenderBeginTag (HtmlTextWriterTag.Tr);
948                         
949                         for (int n=0; n<items.Count; n++) {
950                                 MenuItem item = items [n];
951                                 if (n > 0) {
952                                         int itemSpacing = GetItemSpacing (item, dynamic);
953                                         if (itemSpacing != 0) {
954                                                 if (vertical) {
955                                                         writer.AddAttribute ("height", itemSpacing + "px");
956                                                         writer.RenderBeginTag (HtmlTextWriterTag.Tr);
957                                                         writer.RenderEndTag ();
958                                                 } else {
959                                                         writer.AddAttribute ("width", itemSpacing + "px");
960                                                         writer.RenderBeginTag (HtmlTextWriterTag.Td);
961                                                         writer.RenderEndTag ();
962                                                 }
963                                         }
964                                 }
965                                 RenderMenuItem (writer, item);
966                         }
967                         
968                         if (!vertical) writer.RenderEndTag ();  // TR
969                 }
970                 
971                 void RenderMenuItem (HtmlTextWriter writer, MenuItem item)
972                 {
973                         bool displayChildren = (item.Depth + 1 < StaticDisplayLevels + MaximumDynamicDisplayLevels);
974                         bool dynamicChildren = displayChildren && (item.Depth + 1 >= StaticDisplayLevels) && item.ChildItems.Count > 0;
975                         bool isDynamicItem = item.Depth + 1 > StaticDisplayLevels;
976                         bool vertical = (Orientation == Orientation.Vertical) || isDynamicItem;
977
978                         if (vertical)
979                                 writer.RenderBeginTag (HtmlTextWriterTag.Tr);
980                         
981                         Style itemStyle = null;
982                         if (levelMenuItemStyles != null && item.Depth < levelMenuItemStyles.Count)
983                                 itemStyle = levelMenuItemStyles [item.Depth];
984                         else if (isDynamicItem) {
985                                 if (dynamicMenuItemStyle != null)
986                                         itemStyle = dynamicMenuItemStyle;
987                         } else {
988                                 if (staticMenuItemStyle != null)
989                                         itemStyle = staticMenuItemStyle;
990                         }
991                         
992                         Style selectedStyle = null;
993                         if (item == SelectedItem) {
994                                 if (levelSelectedStyles != null && item.Depth < levelSelectedStyles.Count)
995                                         selectedStyle = levelSelectedStyles [item.Depth];
996                                 else if (isDynamicItem) {
997                                         if (dynamicSelectedStyle != null)
998                                                 selectedStyle = dynamicSelectedStyle;
999                                 } else {
1000                                         if (staticSelectedStyle != null)
1001                                                 selectedStyle = staticSelectedStyle;
1002                                 }
1003                         }
1004                         
1005                         string cls = "";
1006                         if (itemStyle != null) cls += itemStyle.RegisteredCssClass + " ";
1007                         if (selectedStyle != null) cls += selectedStyle.RegisteredCssClass + " ";
1008                         if (cls != "")
1009                                 writer.AddAttribute ("class", cls);
1010                         
1011                         string parentId = isDynamicItem ? "'" + item.Parent.Path + "'" : "null";
1012                         if (dynamicChildren) {
1013                                 writer.AddAttribute ("onmouseover", string.Format ("javascript:Menu_OverItem ('{0}','{1}',{2})", ClientID, item.Path, parentId));
1014                                 writer.AddAttribute ("onmouseout", string.Format ("javascript:Menu_OutItem ('{0}','{1}')", ClientID, item.Path));
1015                         } else if (isDynamicItem) {
1016                                 writer.AddAttribute ("onmouseover", string.Format ("javascript:Menu_OverDynamicLeafItem ('{0}','{1}',{2})", ClientID, item.Path, parentId));
1017                                 writer.AddAttribute ("onmouseout", string.Format ("javascript:Menu_OutItem ('{0}','{1}',{2})", ClientID, item.Path, parentId));
1018                         } else {
1019                                 writer.AddAttribute ("onmouseover", string.Format ("javascript:Menu_OverStaticLeafItem ('{0}','{1}')", ClientID, item.Path));
1020                                 writer.AddAttribute ("onmouseout", string.Format ("javascript:Menu_OutItem ('{0}','{1}')", ClientID, item.Path));
1021                         }
1022                         
1023                         writer.AddAttribute ("id", GetItemClientId (item, "i"));
1024                         
1025                         writer.RenderBeginTag (HtmlTextWriterTag.Td);
1026
1027                         // Top separator image
1028
1029                         if (isDynamicItem && DynamicTopSeparatorImageUrl != "") {
1030                                 writer.AddAttribute ("src", DynamicTopSeparatorImageUrl);
1031                                 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1032                                 writer.RenderEndTag (); // IMG
1033                         } else  if (!isDynamicItem && StaticTopSeparatorImageUrl != "") {
1034                                 writer.AddAttribute ("src", StaticTopSeparatorImageUrl);
1035                                 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1036                                 writer.RenderEndTag (); // IMG
1037                         }
1038                         
1039                         // Menu item box
1040                         
1041                         writer.AddAttribute ("cellpadding", "0");
1042                         writer.AddAttribute ("cellspacing", "0");
1043                         writer.AddAttribute ("width", "100%");
1044                         writer.RenderBeginTag (HtmlTextWriterTag.Table);
1045                         writer.RenderBeginTag (HtmlTextWriterTag.Tr);
1046                         
1047                         if (item.Depth > 0 && !isDynamicItem) {
1048                                 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1049                                 writer.AddStyleAttribute ("width", StaticSubMenuIndent.ToString ());
1050                                 writer.RenderBeginTag (HtmlTextWriterTag.Div);
1051                                 writer.RenderEndTag (); // DIV
1052                                 writer.RenderEndTag (); // TD
1053                         }
1054                         
1055                         if (item.ImageUrl != "") {
1056                                 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1057                                 RenderItemHref (writer, item);
1058                                 writer.RenderBeginTag (HtmlTextWriterTag.A);
1059                                 writer.AddAttribute ("src", item.ImageUrl);
1060                                 writer.AddAttribute ("border", "0");
1061                                 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1062                                 writer.RenderEndTag (); // IMG
1063                                 writer.RenderEndTag (); // A
1064                                 writer.RenderEndTag (); // TD
1065                         }
1066                         
1067                         // Menu item text
1068                         
1069                         writer.AddAttribute ("width", "100%");
1070                         if (!ItemWrap)
1071                                 writer.AddAttribute ("nowrap", "nowrap");
1072                         writer.RenderBeginTag (HtmlTextWriterTag.Td);
1073                         
1074                         RenderItemHref (writer, item);
1075                         writer.AddStyleAttribute ("text-decoration", "none");
1076                         writer.RenderBeginTag (HtmlTextWriterTag.A);
1077                         RenderItemContent (writer, item, isDynamicItem);
1078                         writer.RenderEndTag (); // A
1079                         
1080                         writer.RenderEndTag (); // TD
1081                         
1082                         // Popup image
1083                         
1084                         if (dynamicChildren) {
1085                                 string popOutImage = GetPopOutImage (item, isDynamicItem);
1086                                 if (popOutImage != null)
1087                                 {
1088                                         writer.RenderBeginTag (HtmlTextWriterTag.Td);
1089                                         writer.AddAttribute ("src", popOutImage);
1090                                         writer.AddAttribute ("border", "0");
1091                                         writer.RenderBeginTag (HtmlTextWriterTag.Img);
1092                                         writer.RenderEndTag (); // IMG
1093                                         writer.RenderEndTag (); // TD
1094                                 }
1095                         }
1096                         
1097                         writer.RenderEndTag (); // TR
1098                         writer.RenderEndTag (); // TABLE
1099                         
1100                         // Bottom separator image
1101                                 
1102                         string separatorImg = item.SeparatorImageUrl;
1103                         if (separatorImg.Length == 0) { 
1104                                 if (isDynamicItem) separatorImg = DynamicBottomSeparatorImageUrl;
1105                                 else separatorImg = StaticBottomSeparatorImageUrl;
1106                         }
1107                         if (separatorImg.Length > 0) {
1108                                 writer.AddAttribute ("src", separatorImg);
1109                                 writer.RenderBeginTag (HtmlTextWriterTag.Img);
1110                                 writer.RenderEndTag (); // IMG
1111                         }
1112                                 
1113                         // Submenu
1114                                 
1115                         if (vertical) {
1116                                 if (displayChildren) {
1117                                         if (dynamicChildren) dynamicMenus.Add (item);
1118                                         else {
1119                                                 writer.AddAttribute ("width", "100%");
1120                                                 RenderMenu (writer, item.ChildItems, true, false);
1121                                         }
1122                                 }
1123                                 
1124                                 writer.RenderEndTag (); // TD
1125                                 writer.RenderEndTag (); // TR
1126                         } else {
1127                                 writer.RenderEndTag (); // TD
1128                                 
1129                                 writer.RenderBeginTag (HtmlTextWriterTag.Td);
1130                                 if (displayChildren) {
1131                                         if (dynamicChildren) dynamicMenus.Add (item);
1132                                         else RenderMenu (writer, item.ChildItems, false, false);
1133                                 }
1134                                 writer.RenderEndTag (); // TD
1135                         }
1136                 }
1137                 
1138                 void RenderItemContent (HtmlTextWriter writer, MenuItem item, bool isDynamicItem)
1139                 {
1140                         if (isDynamicItem && dynamicItemTemplate != null) {
1141                                 MenuItemTemplateContainer cter = new MenuItemTemplateContainer (item.Index, item);
1142                                 dynamicItemTemplate.InstantiateIn (cter);
1143                                 cter.Render (writer);
1144                         } else if (!isDynamicItem && staticItemTemplate != null) {
1145                                 MenuItemTemplateContainer cter = new MenuItemTemplateContainer (item.Index, item);
1146                                 staticItemTemplate.InstantiateIn (cter);
1147                                 cter.Render (writer);
1148                         } else {
1149                                 writer.Write (item.Text);
1150                         }
1151                 }
1152                         
1153                 int GetItemSpacing (MenuItem item, bool dynamic)
1154                 {
1155                         int itemSpacing;
1156                         
1157                         if (item.Selected) {
1158                                 if (levelSelectedStyles != null && item.Depth < levelSelectedStyles.Count) {
1159                                         itemSpacing = levelSelectedStyles [item.Depth].ItemSpacing;
1160                                         if (itemSpacing != 0) return itemSpacing;
1161                                 }
1162                                 
1163                                 if (dynamic) itemSpacing = DynamicSelectedStyle.ItemSpacing;
1164                                 else itemSpacing = StaticSelectedStyle.ItemSpacing;
1165                                 if (itemSpacing != 0) return itemSpacing;
1166                         }
1167                         
1168                         if (levelMenuItemStyles != null && item.Depth < levelMenuItemStyles.Count) {
1169                                 itemSpacing = levelMenuItemStyles [item.Depth].ItemSpacing;
1170                                 if (itemSpacing != 0) return itemSpacing;
1171                         }
1172                         
1173                         if (dynamic) return DynamicMenuItemStyle.ItemSpacing;
1174                         else return StaticMenuItemStyle.ItemSpacing;
1175                 }
1176                 
1177                 
1178                 string GetItemSeparatorImage (MenuItem item, bool isDynamicItem)
1179                 {
1180                         if (item.SeparatorImageUrl != "") return item.SeparatorImageUrl;
1181                         if (isDynamicItem && DynamicTopSeparatorImageUrl != "")
1182                                 return DynamicTopSeparatorImageUrl;
1183                         else  if (!isDynamicItem && StaticTopSeparatorImageUrl != "")
1184                                 return StaticTopSeparatorImageUrl;
1185                         return null;
1186                 }
1187                         
1188                 string GetPopOutImage (MenuItem item, bool isDynamicItem)
1189                 {
1190                         if (item.PopOutImageUrl != "")
1191                                 return item.PopOutImageUrl;
1192
1193                         if (isDynamicItem) {
1194                                 if (DynamicPopOutImageUrl != "")
1195                                         return DynamicPopOutImageUrl;
1196                                 if (DynamicEnableDefaultPopOutImage)
1197                                         return AssemblyResourceLoader.GetResourceUrl (typeof(Menu), "arrow_plus.gif");
1198                         } else {
1199                                 if (StaticPopOutImageUrl != "")
1200                                         return StaticPopOutImageUrl;
1201                                 if (StaticEnableDefaultPopOutImage)
1202                                         return AssemblyResourceLoader.GetResourceUrl (typeof(Menu), "arrow_plus.gif");
1203                         }
1204                         return null;
1205                 }
1206                         
1207                 void RenderItemHref (HtmlTextWriter writer, MenuItem item)
1208                 {
1209                         if (item.NavigateUrl != "") {
1210                                 writer.AddAttribute ("href", item.NavigateUrl);
1211                                 if (item.Target != "")
1212                                         writer.AddAttribute ("target", item.Target);
1213                                 else if (Target != "")
1214                                         writer.AddAttribute ("target", Target);
1215                         }
1216                         else {
1217                                 writer.AddAttribute ("href", GetClientEvent (item));
1218                         }
1219                 }
1220                 
1221                 string GetItemClientId (MenuItem item, string sufix)
1222                 {
1223                         return ClientID + "_" + item.Path + sufix;
1224                 }
1225                                                         
1226                 string GetClientEvent (MenuItem item)
1227                 {
1228                         return Page.GetPostBackClientHyperlink (this, item.Path);
1229                 }
1230         }
1231 }
1232
1233 #endif