2 // System.Web.UI.WebControls.MenuItem.cs
5 // Lluis Sanchez Gual (lluis@novell.com)
7 // (C) 2004 Novell, Inc (http://www.novell.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
34 using System
.Collections
;
36 using System
.ComponentModel
;
39 namespace System
.Web
.UI
.WebControls
41 [ParseChildrenAttribute (true, "ChildItems")]
42 public sealed class MenuItem
: IStateManager
, ICloneable
44 StateBag ViewState
= new StateBag ();
45 MenuItemCollection items
;
54 IHierarchyData hierarchyData
;
57 MenuItemBinding binding
;
58 PropertyDescriptorCollection boundProperties
;
64 public MenuItem (string text
)
69 public MenuItem (string text
, string value)
75 public MenuItem (string text
, string value, string imageUrl
)
82 public MenuItem (string text
, string value, string imageUrl
, string navigateUrl
)
87 NavigateUrl
= navigateUrl
;
90 public MenuItem (string text
, string value, string imageUrl
, string navigateUrl
, string target
)
95 NavigateUrl
= navigateUrl
;
99 [DesignerSerializationVisibility (DesignerSerializationVisibility
.Hidden
)]
103 if (depth
!= -1) return depth
;
104 if (Parent
== null) depth
= 0;
105 else depth
= Parent
.Depth
+ 1;
110 void ResetPathData ()
122 items
.SetMenu (menu
);
127 [DesignerSerializationVisibility (DesignerSerializationVisibility
.Hidden
)]
128 [DefaultValue (false)]
130 public bool DataBound
{
131 get { return ViewState ["DataBound"] == null ? false : (bool) ViewState ["DataBound"]; }
132 private set { ViewState ["DataBound"] = value; }
135 [DefaultValue (null)]
137 public object DataItem
{
139 if (!DataBound
) throw new InvalidOperationException ("MenuItem is not data bound.");
144 [DesignerSerializationVisibility (DesignerSerializationVisibility
.Hidden
)]
147 public string DataPath
{
149 return ViewState
["DataPath"] == null ? String
.Empty
: (String
) ViewState
["DataPath"];
152 ViewState
["DataPath"] = value;
156 [MergableProperty (false)]
158 [PersistenceMode (PersistenceMode
.InnerDefaultProperty
)]
159 public MenuItemCollection ChildItems
{
162 items
= new MenuItemCollection (this);
164 if (((IStateManager
)this).IsTrackingViewState
)
165 ((IStateManager
)items
).TrackViewState();
173 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts
.AssemblySystem_Design
, typeof (System
.Drawing
.Design
.UITypeEditor
))]
174 public string ImageUrl
{
176 return ViewState
["ImageUrl"] == null ? String
.Empty
: (String
) ViewState
["ImageUrl"];
179 ViewState
["ImageUrl"] = value;
185 [Editor ("System.Web.UI.Design.UrlEditor, " + Consts
.AssemblySystem_Design
, typeof (System
.Drawing
.Design
.UITypeEditor
))]
186 public string NavigateUrl
{
188 return ViewState
["NavigateUrl"] == null ? String
.Empty
: (String
) ViewState
["NavigateUrl"];
191 ViewState
["NavigateUrl"] = value;
197 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts
.AssemblySystem_Design
, typeof (System
.Drawing
.Design
.UITypeEditor
))]
198 public string PopOutImageUrl
{
200 return ViewState
["PopOutImageUrl"] == null ? String
.Empty
: (String
) ViewState
["PopOutImageUrl"];
203 ViewState
["PopOutImageUrl"] = value;
208 public string Target
{
210 return ViewState
["Target"] == null ? String
.Empty
: (String
) ViewState
["Target"];
213 ViewState
["Target"] = value;
221 object o
= ViewState
["Text"];
223 o
= ViewState
["Value"];
229 ViewState
["Text"] = value;
235 public string ToolTip
{
237 return ViewState
["ToolTip"] == null ? String
.Empty
: (String
) ViewState
["ToolTip"];
240 ViewState
["ToolTip"] = value;
246 public string Value
{
248 object o
= ViewState
["Value"];
250 o
= ViewState
["Text"];
256 ViewState
["Value"] = value;
262 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts
.AssemblySystem_Design
, typeof (System
.Drawing
.Design
.UITypeEditor
))]
263 public string SeparatorImageUrl
{
265 return ViewState
["SeparatorImageUrl"] == null ? String
.Empty
: (String
) ViewState
["SeparatorImageUrl"];
268 ViewState
["SeparatorImageUrl"] = value;
272 [BrowsableAttribute (true)]
273 [DefaultValueAttribute (true)]
274 public bool Selectable
{
276 return ViewState
["Selectable"] == null ? true : (bool) ViewState
["Selectable"];
279 ViewState
["Selectable"] = value;
283 [BrowsableAttribute (true)]
284 [DefaultValueAttribute (true)]
285 public bool Enabled
{
287 return ViewState
["Enabled"] == null ? true : (bool) ViewState
["Enabled"];
290 ViewState
["Enabled"] = value;
294 internal bool BranchEnabled
{
295 get { return Enabled && (parent == null || parent.BranchEnabled); }
298 [DefaultValue (false)]
300 public bool Selected
{
303 return menu
.SelectedItem
== this;
309 if (!value && menu
.SelectedItem
== this)
310 menu
.SetSelectedItem (null);
312 menu
.SetSelectedItem (this);
317 [DesignerSerializationVisibility (DesignerSerializationVisibility
.Hidden
)]
319 public MenuItem Parent
{
320 get { return parent; }
323 [DesignerSerializationVisibility (DesignerSerializationVisibility
.Hidden
)]
325 public string ValuePath
{
327 if (menu
== null) return Value
;
329 StringBuilder sb
= new StringBuilder (Value
);
330 MenuItem item
= parent
;
331 while (item
!= null) {
332 sb
.Insert (0, menu
.PathSeparator
);
333 sb
.Insert (0, item
.Value
);
336 return sb
.ToString ();
341 get { return index; }
342 set { index = value; ResetPathData (); }
345 internal void SetParent (MenuItem item
) {
350 internal string Path
{
352 if (path
!= null) return path
;
353 StringBuilder sb
= new StringBuilder (index
.ToString());
354 MenuItem item
= parent
;
355 while (item
!= null) {
357 sb
.Insert (0, item
.Index
.ToString ());
360 path
= sb
.ToString ();
365 internal bool HasChildData
{
366 get { return items != null; }
369 void IStateManager
.LoadViewState (object savedState
)
371 if (savedState
== null)
374 object[] states
= (object[]) savedState
;
375 ViewState
.LoadViewState (states
[0]);
377 if (states
[1] != null)
378 ((IStateManager
)ChildItems
).LoadViewState (states
[1]);
381 object IStateManager
.SaveViewState ()
383 object[] states
= new object[2];
384 states
[0] = ViewState
.SaveViewState();
385 states
[1] = (items
== null ? null : ((IStateManager
)items
).SaveViewState());
387 for (int i
= 0; i
< states
.Length
; i
++) {
388 if (states
[i
] != null)
394 void IStateManager
.TrackViewState ()
398 ViewState
.TrackViewState();
401 ((IStateManager
)items
).TrackViewState ();
404 bool IStateManager
.IsTrackingViewState
406 get { return marked; }
409 internal void SetDirty ()
411 ViewState
.SetDirty (true);
416 object ICloneable
.Clone ()
418 MenuItem nod
= new MenuItem ();
419 foreach (DictionaryEntry e
in ViewState
)
420 nod
.ViewState
[(string)e
.Key
] = e
.Value
;
422 foreach (ICloneable c
in ChildItems
)
423 nod
.ChildItems
.Add ((MenuItem
)c
.Clone ());
428 internal void Bind (IHierarchyData hierarchyData
)
430 this.hierarchyData
= hierarchyData
;
432 DataPath
= hierarchyData
.Path
;
433 dataItem
= hierarchyData
.Item
;
435 MenuItemBinding bin
= GetBinding ();
438 // Bind Enabled property
440 if (bin
.EnabledField
!= "")
441 try { Enabled = Convert.ToBoolean (GetBoundPropertyValue (bin.EnabledField)); }
442 catch { Enabled = bin.Enabled; }
444 Enabled
= bin
.Enabled
;
446 // Bind ImageUrl property
448 if (bin
.ImageUrlField
.Length
> 0) {
449 ImageUrl
= Convert
.ToString (GetBoundPropertyValue (bin
.ImageUrlField
));
450 if (ImageUrl
.Length
== 0)
451 ImageUrl
= bin
.ImageUrl
;
453 else if (bin
.ImageUrl
.Length
> 0)
454 ImageUrl
= bin
.ImageUrl
;
456 // Bind NavigateUrl property
458 if (bin
.NavigateUrlField
.Length
> 0) {
459 NavigateUrl
= Convert
.ToString (GetBoundPropertyValue (bin
.NavigateUrlField
));
460 if (NavigateUrl
.Length
== 0)
461 NavigateUrl
= bin
.NavigateUrl
;
463 else if (bin
.NavigateUrl
.Length
> 0)
464 NavigateUrl
= bin
.NavigateUrl
;
466 // Bind PopOutImageUrl property
468 if (bin
.PopOutImageUrlField
.Length
> 0) {
469 PopOutImageUrl
= Convert
.ToString (GetBoundPropertyValue (bin
.PopOutImageUrlField
));
470 if (PopOutImageUrl
.Length
== 0)
471 PopOutImageUrl
= bin
.PopOutImageUrl
;
473 else if (bin
.PopOutImageUrl
.Length
> 0)
474 PopOutImageUrl
= bin
.PopOutImageUrl
;
476 // Bind Selectable property
478 if (bin
.SelectableField
!= "")
479 try { Selectable = Convert.ToBoolean (GetBoundPropertyValue (bin.SelectableField)); }
480 catch { Selectable = bin.Selectable; }
482 Selectable
= bin
.Selectable
;
484 // Bind SeparatorImageUrl property
486 if (bin
.SeparatorImageUrlField
.Length
> 0) {
487 SeparatorImageUrl
= Convert
.ToString (GetBoundPropertyValue (bin
.SeparatorImageUrlField
));
488 if (SeparatorImageUrl
.Length
== 0)
489 SeparatorImageUrl
= bin
.SeparatorImageUrl
;
491 else if (bin
.SeparatorImageUrl
.Length
> 0)
492 SeparatorImageUrl
= bin
.SeparatorImageUrl
;
494 // Bind Target property
496 if (bin
.TargetField
.Length
> 0) {
497 Target
= Convert
.ToString (GetBoundPropertyValue (bin
.TargetField
));
498 if (Target
.Length
== 0)
501 else if (bin
.Target
.Length
> 0)
504 // Bind ToolTip property
506 if (bin
.ToolTipField
.Length
> 0) {
507 ToolTip
= Convert
.ToString (GetBoundPropertyValue (bin
.ToolTipField
));
508 if (ToolTip
.Length
== 0)
509 ToolTip
= bin
.ToolTip
;
511 else if (bin
.ToolTip
.Length
> 0)
512 ToolTip
= bin
.ToolTip
;
514 // Bind Value property
516 if (bin
.ValueField
.Length
> 0) {
517 value = Convert
.ToString (GetBoundPropertyValue (bin
.ValueField
));
519 if (String
.IsNullOrEmpty (value)) {
520 if (bin
.Value
.Length
> 0)
522 else if (bin
.Text
.Length
> 0)
525 value = String
.Empty
;
529 // Bind Text property
531 if (bin
.TextField
.Length
> 0) {
532 text
= Convert
.ToString (GetBoundPropertyValue (bin
.TextField
));
533 if (bin
.FormatString
.Length
> 0)
534 text
= string.Format (bin
.FormatString
, text
);
536 if (String
.IsNullOrEmpty (text
)) {
537 if (bin
.Text
.Length
> 0)
539 else if (bin
.Value
.Length
> 0)
548 Text
= Value
= GetDefaultBoundText ();
551 INavigateUIData navigateUIData
= hierarchyData
as INavigateUIData
;
552 if (navigateUIData
!= null) {
553 ToolTip
= navigateUIData
.Description
;
554 Text
= navigateUIData
.ToString ();
555 NavigateUrl
= navigateUIData
.NavigateUrl
;
559 internal void SetDataItem (object item
)
564 internal void SetDataPath (string path
)
569 internal void SetDataBound (bool bound
)
574 string GetDefaultBoundText ()
576 if (hierarchyData
!= null) return hierarchyData
.ToString ();
577 else if (dataItem
!= null) return dataItem
.ToString ();
578 else return string.Empty
;
581 string GetDataItemType ()
583 if (hierarchyData
!= null) return hierarchyData
.Type
;
584 else if (dataItem
!= null) return dataItem
.GetType().ToString ();
585 else return string.Empty
;
588 MenuItemBinding
GetBinding ()
590 if (menu
== null) return null;
591 if (gotBinding
) return binding
;
592 binding
= menu
.FindBindingForItem (GetDataItemType (), Depth
);
597 object GetBoundPropertyValue (string name
)
599 if (boundProperties
== null) {
600 if (hierarchyData
!= null)
601 boundProperties
= TypeDescriptor
.GetProperties (hierarchyData
);
603 boundProperties
= TypeDescriptor
.GetProperties (dataItem
);
606 PropertyDescriptor prop
= boundProperties
.Find (name
, true);
608 throw new InvalidOperationException ("Property '" + name
+ "' not found in data bound item");
610 if (hierarchyData
!= null)
611 return prop
.GetValue (hierarchyData
);
613 return prop
.GetValue (dataItem
);