ListControl.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. //
  2. // System.Web.UI.WebControls.ListControl.cs
  3. //
  4. // Authors:
  5. // Gaurav Vaish ([email protected])
  6. // Andreas Nahr ([email protected])
  7. //
  8. // (C) Gaurav Vaish (2002)
  9. // (C) 2003 Andreas Nahr
  10. //
  11. //
  12. // Permission is hereby granted, free of charge, to any person obtaining
  13. // a copy of this software and associated documentation files (the
  14. // "Software"), to deal in the Software without restriction, including
  15. // without limitation the rights to use, copy, modify, merge, publish,
  16. // distribute, sublicense, and/or sell copies of the Software, and to
  17. // permit persons to whom the Software is furnished to do so, subject to
  18. // the following conditions:
  19. //
  20. // The above copyright notice and this permission notice shall be
  21. // included in all copies or substantial portions of the Software.
  22. //
  23. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  27. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  28. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  29. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  30. //
  31. using System;
  32. using System.Collections;
  33. using System.ComponentModel;
  34. using System.ComponentModel.Design;
  35. using System.Web;
  36. using System.Web.UI;
  37. using System.Web.Util;
  38. namespace System.Web.UI.WebControls
  39. {
  40. [DefaultEvent("SelectedIndexChanged")]
  41. #if !NET_2_0
  42. [DefaultProperty("DataSource")]
  43. #endif
  44. [Designer ("System.Web.UI.Design.WebControls.ListControlDesigner, " + Consts.AssemblySystem_Design, typeof (IDesigner))]
  45. [DataBindingHandler("System.Web.UI.Design.ListControlDataBindingHandler, " + Consts.AssemblySystem_Design)]
  46. [ParseChildren(true, "Items")]
  47. public abstract class ListControl :
  48. #if NET_2_0
  49. DataBoundControl
  50. #else
  51. WebControl
  52. #endif
  53. {
  54. private static readonly object SelectedIndexChangedEvent = new object();
  55. #if !NET_2_0
  56. private object dataSource;
  57. #endif
  58. private ListItemCollection items;
  59. private int cachedSelectedIndex = -1;
  60. private string cachedSelectedValue;
  61. #if !NET_2_0
  62. public ListControl(): base(HtmlTextWriterTag.Select)
  63. {
  64. }
  65. #else
  66. protected override HtmlTextWriterTag TagKey {
  67. get { return HtmlTextWriterTag.Select; }
  68. }
  69. #endif
  70. [WebCategory ("Action")]
  71. [WebSysDescription ("Raised when the selected index entry has changed.")]
  72. public event EventHandler SelectedIndexChanged
  73. {
  74. add
  75. {
  76. Events.AddHandler(SelectedIndexChangedEvent, value);
  77. }
  78. remove
  79. {
  80. Events.RemoveHandler(SelectedIndexChangedEvent, value);
  81. }
  82. }
  83. [DefaultValue (false), WebCategory ("Behavior")]
  84. [WebSysDescription ("The control automatically posts back after changing the text.")]
  85. public virtual bool AutoPostBack
  86. {
  87. get
  88. {
  89. object o = ViewState["AutoPostBack"];
  90. if(o!=null)
  91. return (bool)o;
  92. return false;
  93. }
  94. set
  95. {
  96. ViewState["AutoPostBack"] = value;
  97. }
  98. }
  99. #if !NET_2_0
  100. [DefaultValue (""), WebCategory ("Data")]
  101. [WebSysDescription ("The name of the table that is used for binding when a DataSource is specified.")]
  102. public virtual string DataMember
  103. {
  104. get
  105. {
  106. object o = ViewState["DataMember"];
  107. if(o!=null)
  108. return (string)o;
  109. return String.Empty;
  110. }
  111. set
  112. {
  113. ViewState["DataMember"] = value;
  114. }
  115. }
  116. [DefaultValue (null), Bindable (true), WebCategory ("Data")]
  117. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  118. [WebSysDescription ("The DataSource that is used for data-binding.")]
  119. public virtual object DataSource
  120. {
  121. get
  122. {
  123. return dataSource;
  124. }
  125. set
  126. {
  127. if(value == null || value is IListSource || value is IEnumerable) {
  128. dataSource = value;
  129. return;
  130. }
  131. throw new ArgumentException(HttpRuntime.FormatResourceString(ID, "Invalid DataSource Type"));
  132. }
  133. }
  134. #endif
  135. [DefaultValue (""), WebCategory ("Data")]
  136. [WebSysDescription ("The field in the datatable that provides the text entry.")]
  137. public virtual string DataTextField
  138. {
  139. get
  140. {
  141. object o = ViewState["DataTextField"];
  142. if(o!=null)
  143. return (string)o;
  144. return String.Empty;
  145. }
  146. set
  147. {
  148. ViewState["DataTextField"] = value;
  149. }
  150. }
  151. [DefaultValue (""), WebCategory ("Data")]
  152. [WebSysDescription ("Specifies a formatting rule for the texts that are returned.")]
  153. public virtual string DataTextFormatString
  154. {
  155. get
  156. {
  157. object o = ViewState["DataTextFormatString"];
  158. if(o!=null)
  159. return (string)o;
  160. return String.Empty;
  161. }
  162. set
  163. {
  164. ViewState["DataTextFormatString"] = value;
  165. }
  166. }
  167. [DefaultValue (""), WebCategory ("Data")]
  168. [WebSysDescription ("The field in the datatable that provides the entry value.")]
  169. public virtual string DataValueField
  170. {
  171. get
  172. {
  173. object o = ViewState["DataValueField"];
  174. if(o!=null)
  175. return (string)o;
  176. return String.Empty;
  177. }
  178. set
  179. {
  180. ViewState["DataValueField"] = value;
  181. }
  182. }
  183. [DefaultValue (null), MergableProperty (false), WebCategory ("Misc")]
  184. [PersistenceMode (PersistenceMode.InnerDefaultProperty)]
  185. [WebSysDescription ("A collection of all items contained in this list.")]
  186. public virtual ListItemCollection Items
  187. {
  188. get
  189. {
  190. if(items==null)
  191. {
  192. items = new ListItemCollection();
  193. if(IsTrackingViewState)
  194. {
  195. items.TrackViewState();
  196. }
  197. }
  198. return items;
  199. }
  200. }
  201. [DefaultValue (0), Bindable (true), WebCategory ("Misc")]
  202. [Browsable (false), DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  203. [WebSysDescription ("The index number of the currently selected ListItem.")]
  204. public virtual int SelectedIndex
  205. {
  206. get {
  207. ListItemCollection items = Items;
  208. int last = items.Count;
  209. for (int i = 0; i < last; i++) {
  210. if (items [i].Selected)
  211. return i;
  212. }
  213. return -1;
  214. }
  215. set {
  216. if (Items.Count == 0)
  217. {
  218. cachedSelectedIndex = value;
  219. return;
  220. }
  221. if ((value < -1) || (value >= Items.Count))
  222. throw new ArgumentOutOfRangeException ();
  223. ClearSelection ();
  224. if (value != -1)
  225. Items [value].Selected = true;
  226. }
  227. }
  228. [DefaultValue (null), WebCategory ("Misc")]
  229. [Browsable (false), DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  230. [WebSysDescription ("The currently selected ListItem.")]
  231. public virtual ListItem SelectedItem
  232. {
  233. get
  234. {
  235. int idx = SelectedIndex;
  236. if (idx < 0)
  237. return null;
  238. return Items [idx];
  239. }
  240. }
  241. #if NET_1_1
  242. [DefaultValue (""), Bindable (true), WebCategory ("Misc")]
  243. [Browsable (false), DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  244. [WebSysDescription ("The value of the currently selected ListItem.")]
  245. public virtual string SelectedValue {
  246. get {
  247. int idx = SelectedIndex;
  248. if (idx == -1)
  249. return "";
  250. return Items [idx].Value;
  251. }
  252. set {
  253. ListItem item = null;
  254. if (value != null) {
  255. if (Items.Count > 0) {
  256. item = Items.FindByValue (value);
  257. if (item == null)
  258. throw new ArgumentOutOfRangeException ("value");
  259. } else {
  260. cachedSelectedValue = value;
  261. return;
  262. }
  263. }
  264. ClearSelection ();
  265. if (item != null)
  266. item.Selected = true;
  267. }
  268. }
  269. #endif
  270. internal virtual ArrayList SelectedIndices
  271. {
  272. get
  273. {
  274. ArrayList si = new ArrayList();
  275. for(int i=0; i < Items.Count; i++)
  276. {
  277. if(Items[i].Selected)
  278. si.Add(i);
  279. }
  280. return si;
  281. }
  282. }
  283. internal void Select(ArrayList indices)
  284. {
  285. ClearSelection();
  286. foreach(object intObj in indices)
  287. {
  288. int index = (int)intObj;
  289. if(index >= 0 && index < Items.Count)
  290. Items[index].Selected = true;
  291. }
  292. }
  293. public virtual void ClearSelection()
  294. {
  295. for(int i=0; i < Items.Count; i++)
  296. {
  297. Items[i].Selected = false;
  298. }
  299. }
  300. protected override void LoadViewState(object savedState)
  301. {
  302. //Order: BaseClass, Items (Collection), Indices
  303. if(savedState != null && savedState is Triplet)
  304. {
  305. Triplet state = (Triplet)savedState;
  306. base.LoadViewState(state.First);
  307. Items.LoadViewState(state.Second);
  308. object indices = state.Third;
  309. if(indices != null)
  310. {
  311. Select((ArrayList)indices);
  312. }
  313. }
  314. }
  315. #if NET_2_0
  316. protected override void PerformDataBinding ()
  317. {
  318. base.PerformDataBinding ();
  319. IEnumerable ds = GetResolvedDataSource ();
  320. #else
  321. protected override void OnDataBinding(EventArgs e)
  322. {
  323. base.OnDataBinding(e);
  324. IEnumerable ds = DataSourceHelper.GetResolvedDataSource (DataSource, DataMember);
  325. #endif
  326. if(ds != null) {
  327. string dtf = DataTextField;
  328. string dvf = DataValueField;
  329. string dtfs = DataTextFormatString;
  330. if (dtfs.Length == 0)
  331. dtfs = "{0}";
  332. Items.Clear();
  333. bool dontUseProperties = (dtf.Length == 0 && dvf.Length == 0);
  334. foreach (object current in ds) {
  335. ListItem li = new ListItem();
  336. if (dontUseProperties){
  337. li.Text = String.Format (dtfs, current);
  338. li.Value = current.ToString ();
  339. Items.Add (li);
  340. continue;
  341. }
  342. object o;
  343. if (dtf.Length > 0) {
  344. o = DataBinder.GetPropertyValue (current, dtf, dtfs);
  345. li.Text = o.ToString ();
  346. }
  347. if (dvf.Length > 0) {
  348. o = DataBinder.GetPropertyValue (current, dvf, null);
  349. li.Value = o.ToString ();
  350. }
  351. Items.Add(li);
  352. }
  353. }
  354. if (cachedSelectedValue != null) {
  355. int index = Items.FindByValueInternal (cachedSelectedValue);
  356. if (index == -1)
  357. throw new ArgumentOutOfRangeException("value");
  358. if (cachedSelectedIndex != -1 && cachedSelectedIndex != index)
  359. throw new ArgumentException(HttpRuntime.FormatResourceString(
  360. "Attributes_mutually_exclusive", "Selected Index", "Selected Value"));
  361. SelectedIndex = index;
  362. cachedSelectedIndex = -1;
  363. cachedSelectedValue = null;
  364. return;
  365. }
  366. if (cachedSelectedIndex != -1) {
  367. SelectedIndex = cachedSelectedIndex;
  368. cachedSelectedIndex = -1;
  369. }
  370. }
  371. protected virtual void OnSelectedIndexChanged(EventArgs e)
  372. {
  373. if(Events!=null)
  374. {
  375. EventHandler eh = (EventHandler)(Events[SelectedIndexChangedEvent]);
  376. if(eh!=null)
  377. eh(this, e);
  378. }
  379. }
  380. protected override void OnPreRender (EventArgs e)
  381. {
  382. base.OnPreRender(e);
  383. }
  384. protected override object SaveViewState()
  385. {
  386. //Order: BaseClass, Items (Collection), Indices
  387. object vs = base.SaveViewState();
  388. object itemSvs = Items.SaveViewState();
  389. object indices = null;
  390. if (SaveSelectedIndicesViewState)
  391. indices = SelectedIndices;
  392. if (vs != null || itemSvs != null || indices != null)
  393. return new Triplet(vs, itemSvs, indices);
  394. return null;
  395. }
  396. protected override void TrackViewState()
  397. {
  398. base.TrackViewState();
  399. Items.TrackViewState();
  400. }
  401. private bool SaveSelectedIndicesViewState {
  402. get {
  403. if (Events[SelectedIndexChangedEvent] == null && Enabled && Visible) {
  404. Type t = GetType();
  405. // If I am a derivative, let it take of storing the selected indices.
  406. if (t == typeof(DropDownList) || t == typeof(ListBox) ||
  407. t == typeof(CheckBoxList) || t == typeof(RadioButtonList))
  408. return false;
  409. }
  410. return true;
  411. }
  412. }
  413. }
  414. }