MenuItem.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. //
  2. // System.Web.UI.WebControls.MenuItem.cs
  3. //
  4. // Authors:
  5. // Lluis Sanchez Gual ([email protected])
  6. //
  7. // (C) 2004 Novell, Inc (http://www.novell.com)
  8. //
  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:
  16. //
  17. // The above copyright notice and this permission notice shall be
  18. // included in all copies or substantial portions of the Software.
  19. //
  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.
  27. //
  28. // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
  29. //
  30. #if NET_2_0
  31. using System;
  32. using System.Collections;
  33. using System.Text;
  34. using System.ComponentModel;
  35. using System.Web.UI;
  36. namespace System.Web.UI.WebControls
  37. {
  38. [ParseChildrenAttribute (true, "ChildItems")]
  39. public sealed class MenuItem: IStateManager, ICloneable
  40. {
  41. StateBag ViewState = new StateBag ();
  42. MenuItemCollection items;
  43. bool marked;
  44. Menu menu;
  45. MenuItem parent;
  46. int index;
  47. string path;
  48. int depth = -1;
  49. bool dataBound;
  50. string dataPath;
  51. object dataItem;
  52. IHierarchyData hierarchyData;
  53. bool gotBinding;
  54. MenuItemBinding binding;
  55. PropertyDescriptorCollection boundProperties;
  56. public MenuItem ()
  57. {
  58. }
  59. public MenuItem (string text)
  60. {
  61. Text = text;
  62. }
  63. public MenuItem (string text, string value)
  64. {
  65. Text = text;
  66. Value = value;
  67. }
  68. public MenuItem (string text, string value, string imageUrl)
  69. {
  70. Text = text;
  71. Value = value;
  72. ImageUrl = imageUrl;
  73. }
  74. public MenuItem (string text, string value, string imageUrl, string navigateUrl)
  75. {
  76. Text = text;
  77. Value = value;
  78. ImageUrl = imageUrl;
  79. NavigateUrl = navigateUrl;
  80. }
  81. public MenuItem (string text, string value, string imageUrl, string navigateUrl, string target)
  82. {
  83. Text = text;
  84. Value = value;
  85. ImageUrl = imageUrl;
  86. NavigateUrl = navigateUrl;
  87. Target = target;
  88. }
  89. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  90. [Browsable (false)]
  91. public int Depth {
  92. get {
  93. if (depth != -1) return depth;
  94. if (Parent == null) depth = 0;
  95. else depth = Parent.Depth + 1;
  96. return depth;
  97. }
  98. }
  99. void ResetPathData ()
  100. {
  101. path = null;
  102. depth = -1;
  103. gotBinding = false;
  104. }
  105. internal Menu Menu {
  106. get { return menu; }
  107. set {
  108. menu = value;
  109. if (items != null)
  110. items.SetMenu (menu);
  111. ResetPathData ();
  112. }
  113. }
  114. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  115. [DefaultValue (false)]
  116. [Browsable (false)]
  117. public bool DataBound {
  118. get { return dataBound; }
  119. }
  120. [DefaultValue (null)]
  121. [Browsable (false)]
  122. public object DataItem {
  123. get {
  124. if (!dataBound) throw new InvalidOperationException ("MenuItem is not data bound.");
  125. return dataItem;
  126. }
  127. }
  128. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  129. [DefaultValue ("")]
  130. [Browsable (false)]
  131. public string DataPath {
  132. get {
  133. if (!dataBound) throw new InvalidOperationException ("MenuItem is not data bound.");
  134. return dataPath;
  135. }
  136. }
  137. [MergableProperty (false)]
  138. [Browsable (false)]
  139. [PersistenceMode (PersistenceMode.InnerDefaultProperty)]
  140. public MenuItemCollection ChildItems {
  141. get {
  142. if (items == null) {
  143. if (DataBound)
  144. FillBoundChildren ();
  145. else
  146. items = new MenuItemCollection (this);
  147. if (((IStateManager)this).IsTrackingViewState)
  148. ((IStateManager)items).TrackViewState();
  149. }
  150. return items;
  151. }
  152. }
  153. [DefaultValue ("")]
  154. [UrlProperty]
  155. [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
  156. public string ImageUrl {
  157. get {
  158. object o = ViewState ["ImageUrl"];
  159. if (o != null) return (string)o;
  160. if (DataBound) {
  161. MenuItemBinding bin = GetBinding ();
  162. if (bin != null) {
  163. if (bin.ImageUrlField != "")
  164. return (string) GetBoundPropertyValue (bin.ImageUrlField);
  165. return bin.ImageUrl;
  166. }
  167. }
  168. return "";
  169. }
  170. set {
  171. ViewState ["ImageUrl"] = value;
  172. }
  173. }
  174. [DefaultValue ("")]
  175. [UrlProperty]
  176. [Editor ("System.Web.UI.Design.UrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
  177. public string NavigateUrl {
  178. get {
  179. object o = ViewState ["NavigateUrl"];
  180. if (o != null) return (string)o;
  181. if (DataBound) {
  182. MenuItemBinding bin = GetBinding ();
  183. if (bin != null) {
  184. if (bin.NavigateUrlField != "")
  185. return (string) GetBoundPropertyValue (bin.NavigateUrlField);
  186. return bin.NavigateUrl;
  187. }
  188. }
  189. return "";
  190. }
  191. set {
  192. ViewState ["NavigateUrl"] = value;
  193. }
  194. }
  195. [DefaultValue ("")]
  196. [UrlProperty]
  197. [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
  198. public string PopOutImageUrl {
  199. get {
  200. object o = ViewState ["PopOutImageUrl"];
  201. if (o != null) return (string)o;
  202. if (DataBound) {
  203. MenuItemBinding bin = GetBinding ();
  204. if (bin != null) {
  205. if (bin.PopOutImageUrlField != "")
  206. return (string) GetBoundPropertyValue (bin.PopOutImageUrlField);
  207. return bin.PopOutImageUrl;
  208. }
  209. }
  210. return "";
  211. }
  212. set {
  213. ViewState ["PopOutImageUrl"] = value;
  214. }
  215. }
  216. [DefaultValue ("")]
  217. public string Target {
  218. get {
  219. object o = ViewState ["Target"];
  220. if(o != null) return (string)o;
  221. if (DataBound) {
  222. MenuItemBinding bin = GetBinding ();
  223. if (bin != null) {
  224. if (bin.TargetField != "")
  225. return (string) GetBoundPropertyValue (bin.TargetField);
  226. return bin.Target;
  227. }
  228. }
  229. return "";
  230. }
  231. set {
  232. ViewState ["Target"] = value;
  233. }
  234. }
  235. [Localizable (true)]
  236. [DefaultValue ("")]
  237. public string Text {
  238. get {
  239. object o = ViewState ["Text"];
  240. if (o != null) return (string)o;
  241. if (DataBound) {
  242. MenuItemBinding bin = GetBinding ();
  243. if (bin != null) {
  244. string text;
  245. if (bin.TextField != "")
  246. text = (string) GetBoundPropertyValue (bin.TextField);
  247. else if (bin.Text != "")
  248. text = bin.Text;
  249. else
  250. text = GetDefaultBoundText ();
  251. if (bin.FormatString.Length != 0)
  252. text = string.Format (bin.FormatString, text);
  253. return text;
  254. }
  255. return GetDefaultBoundText ();
  256. }
  257. return "";
  258. }
  259. set {
  260. ViewState ["Text"] = value;
  261. }
  262. }
  263. [Localizable (true)]
  264. [DefaultValue ("")]
  265. public string ToolTip {
  266. get {
  267. object o = ViewState ["ToolTip"];
  268. if(o != null) return (string)o;
  269. if (DataBound) {
  270. MenuItemBinding bin = GetBinding ();
  271. if (bin != null) {
  272. if (bin.ToolTipField != "")
  273. return (string) GetBoundPropertyValue (bin.ToolTipField);
  274. return bin.ToolTip;
  275. }
  276. }
  277. return "";
  278. }
  279. set {
  280. ViewState ["ToolTip"] = value;
  281. }
  282. }
  283. [Localizable (true)]
  284. [DefaultValue ("")]
  285. public string Value {
  286. get {
  287. object o = ViewState ["Value"];
  288. if(o != null) return (string)o;
  289. if (DataBound) {
  290. MenuItemBinding bin = GetBinding ();
  291. if (bin != null) {
  292. if (bin.ValueField != "")
  293. return (string) GetBoundPropertyValue (bin.ValueField);
  294. if (bin.Value != "")
  295. return bin.Value;
  296. }
  297. return GetDefaultBoundText ();
  298. }
  299. return "";
  300. }
  301. set {
  302. ViewState ["Value"] = value;
  303. }
  304. }
  305. [DefaultValue ("")]
  306. [UrlProperty]
  307. [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
  308. public string SeparatorImageUrl {
  309. get {
  310. object o = ViewState ["SeparatorImageUrl"];
  311. if (o != null) return (string)o;
  312. if (DataBound) {
  313. MenuItemBinding bin = GetBinding ();
  314. if (bin != null) {
  315. if (bin.SeparatorImageUrlField != "")
  316. return (string) GetBoundPropertyValue (bin.SeparatorImageUrlField);
  317. return bin.SeparatorImageUrl;
  318. }
  319. }
  320. return "";
  321. }
  322. set {
  323. ViewState ["SeparatorImageUrl"] = value;
  324. }
  325. }
  326. [BrowsableAttribute (true)]
  327. [DefaultValueAttribute (true)]
  328. public bool Selectable {
  329. get {
  330. object o = ViewState ["Selectable"];
  331. if (o != null) return (bool)o;
  332. if (DataBound) {
  333. MenuItemBinding bin = GetBinding ();
  334. if (bin != null) {
  335. if (bin.SelectableField != "")
  336. return (bool) GetBoundPropertyValue (bin.SelectableField);
  337. return bin.Selectable;
  338. }
  339. }
  340. return true;
  341. }
  342. set {
  343. ViewState ["Selectable"] = value;
  344. }
  345. }
  346. [BrowsableAttribute (true)]
  347. [DefaultValueAttribute (true)]
  348. public bool Enabled {
  349. get {
  350. object o = ViewState ["Enabled"];
  351. if (o != null) return (bool)o;
  352. if (DataBound) {
  353. MenuItemBinding bin = GetBinding ();
  354. if (bin != null) {
  355. if (bin.EnabledField != "")
  356. return (bool) GetBoundPropertyValue (bin.EnabledField);
  357. return bin.Enabled;
  358. }
  359. }
  360. return true;
  361. }
  362. set {
  363. ViewState ["Enabled"] = value;
  364. }
  365. }
  366. internal bool BranchEnabled {
  367. get { return Enabled && (parent == null || parent.BranchEnabled); }
  368. }
  369. [DefaultValue (false)]
  370. [Browsable (true)]
  371. public bool Selected {
  372. get {
  373. if (menu != null)
  374. return menu.SelectedItem == this;
  375. else
  376. return false;
  377. }
  378. set {
  379. if (menu != null) {
  380. if (!value && menu.SelectedItem == this)
  381. menu.SetSelectedItem (null);
  382. else if (value)
  383. menu.SetSelectedItem (this);
  384. }
  385. }
  386. }
  387. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  388. [Browsable (false)]
  389. public MenuItem Parent {
  390. get { return parent; }
  391. }
  392. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  393. [Browsable (false)]
  394. public string ValuePath {
  395. get {
  396. if (menu == null) return Value;
  397. StringBuilder sb = new StringBuilder (Value);
  398. MenuItem item = parent;
  399. while (item != null) {
  400. sb.Insert (0, menu.PathSeparator);
  401. sb.Insert (0, item.Value);
  402. item = item.Parent;
  403. }
  404. return sb.ToString ();
  405. }
  406. }
  407. internal int Index {
  408. get { return index; }
  409. set { index = value; ResetPathData (); }
  410. }
  411. internal void SetParent (MenuItem item) {
  412. parent = item;
  413. ResetPathData ();
  414. }
  415. internal string Path {
  416. get {
  417. if (path != null) return path;
  418. StringBuilder sb = new StringBuilder (index.ToString());
  419. MenuItem item = parent;
  420. while (item != null) {
  421. sb.Insert (0, '_');
  422. sb.Insert (0, item.Index.ToString ());
  423. item = item.Parent;
  424. }
  425. path = sb.ToString ();
  426. return path;
  427. }
  428. }
  429. internal bool HasChildData {
  430. get { return items != null; }
  431. }
  432. void IStateManager.LoadViewState (object savedState)
  433. {
  434. if (savedState == null)
  435. return;
  436. object[] states = (object[]) savedState;
  437. ViewState.LoadViewState (states [0]);
  438. if (states [1] != null)
  439. ((IStateManager)ChildItems).LoadViewState (states [1]);
  440. }
  441. object IStateManager.SaveViewState ()
  442. {
  443. object[] states = new object[2];
  444. states[0] = ViewState.SaveViewState();
  445. states[1] = (items == null ? null : ((IStateManager)items).SaveViewState());
  446. for (int i = 0; i < states.Length; i++) {
  447. if (states [i] != null)
  448. return states;
  449. }
  450. return null;
  451. }
  452. void IStateManager.TrackViewState ()
  453. {
  454. if (marked) return;
  455. marked = true;
  456. ViewState.TrackViewState();
  457. if (items != null)
  458. ((IStateManager)items).TrackViewState ();
  459. }
  460. bool IStateManager.IsTrackingViewState
  461. {
  462. get { return marked; }
  463. }
  464. internal void SetDirty ()
  465. {
  466. ViewState.SetDirty (true);
  467. }
  468. object ICloneable.Clone ()
  469. {
  470. MenuItem nod = new MenuItem ();
  471. foreach (DictionaryEntry e in ViewState)
  472. nod.ViewState [(string)e.Key] = e.Value;
  473. foreach (ICloneable c in ChildItems)
  474. nod.ChildItems.Add ((MenuItem)c.Clone ());
  475. return nod;
  476. }
  477. internal void Bind (IHierarchyData hierarchyData)
  478. {
  479. this.hierarchyData = hierarchyData;
  480. dataBound = true;
  481. dataPath = hierarchyData.Path;
  482. dataItem = hierarchyData.Item;
  483. INavigateUIData navigateUIData = hierarchyData as INavigateUIData;
  484. if (navigateUIData != null)
  485. NavigateUrl = navigateUIData.NavigateUrl;
  486. }
  487. internal void SetDataItem (object item)
  488. {
  489. dataItem = item;
  490. }
  491. internal void SetDataPath (string path)
  492. {
  493. dataPath = path;
  494. }
  495. internal void SetDataBound (bool bound)
  496. {
  497. dataBound = bound;
  498. }
  499. string GetDefaultBoundText ()
  500. {
  501. if (hierarchyData != null) return hierarchyData.ToString ();
  502. else if (dataItem != null) return dataItem.ToString ();
  503. else return string.Empty;
  504. }
  505. string GetDataItemType ()
  506. {
  507. if (hierarchyData != null) return hierarchyData.Type;
  508. else if (dataItem != null) return dataItem.GetType().ToString ();
  509. else return string.Empty;
  510. }
  511. MenuItemBinding GetBinding ()
  512. {
  513. if (menu == null) return null;
  514. if (gotBinding) return binding;
  515. binding = menu.FindBindingForItem (GetDataItemType (), Depth);
  516. gotBinding = true;
  517. return binding;
  518. }
  519. object GetBoundPropertyValue (string name)
  520. {
  521. if (boundProperties == null) {
  522. if (hierarchyData != null)
  523. boundProperties = TypeDescriptor.GetProperties (hierarchyData);
  524. else
  525. boundProperties = TypeDescriptor.GetProperties (dataItem);
  526. }
  527. PropertyDescriptor prop = boundProperties.Find (name, true);
  528. if (prop == null)
  529. throw new InvalidOperationException ("Property '" + name + "' not found in data bound item");
  530. if (hierarchyData != null)
  531. return prop.GetValue (hierarchyData);
  532. else
  533. return prop.GetValue (dataItem);
  534. }
  535. void FillBoundChildren ()
  536. {
  537. items = new MenuItemCollection (this);
  538. if (hierarchyData == null || !hierarchyData.HasChildren) return;
  539. IHierarchicalEnumerable e = hierarchyData.GetChildren ();
  540. foreach (object obj in e) {
  541. IHierarchyData hdata = e.GetHierarchyData (obj);
  542. MenuItem item = new MenuItem ();
  543. item.Bind (hdata);
  544. items.Add (item);
  545. }
  546. }
  547. }
  548. }
  549. #endif