Repeater.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. //
  2. // System.Web.UI.WebControls.Repeater.cs
  3. //
  4. // Authors:
  5. // Gaurav Vaish ([email protected])
  6. // Gonzalo Paniagua Javier ([email protected])
  7. // Andreas Nahr ([email protected])
  8. //
  9. // (c) 2002 Ximian, Inc. (http://www.ximian.com)
  10. // (C) Gaurav Vaish (2002)
  11. // (C) 2003 Andreas Nahr
  12. //
  13. //
  14. // Permission is hereby granted, free of charge, to any person obtaining
  15. // a copy of this software and associated documentation files (the
  16. // "Software"), to deal in the Software without restriction, including
  17. // without limitation the rights to use, copy, modify, merge, publish,
  18. // distribute, sublicense, and/or sell copies of the Software, and to
  19. // permit persons to whom the Software is furnished to do so, subject to
  20. // the following conditions:
  21. //
  22. // The above copyright notice and this permission notice shall be
  23. // included in all copies or substantial portions of the Software.
  24. //
  25. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  26. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  27. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  28. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  29. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  30. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  31. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  32. //
  33. using System;
  34. using System.Collections;
  35. using System.Web;
  36. using System.Web.UI;
  37. using System.Web.Util;
  38. using System.ComponentModel;
  39. using System.ComponentModel.Design;
  40. namespace System.Web.UI.WebControls
  41. {
  42. [DefaultEvent("ItemCommand")]
  43. [DefaultProperty("DataSource")]
  44. [Designer ("System.Web.UI.Design.WebControls.RepeaterDesigner, " + Consts.AssemblySystem_Design, typeof (IDesigner))]
  45. [ParseChildren(true)]
  46. [PersistChildren(false)]
  47. public class Repeater : Control, INamingContainer
  48. {
  49. private static readonly object ItemCommandEvent = new object();
  50. private static readonly object ItemCreatedEvent = new object();
  51. private static readonly object ItemDataBoundEvent = new object();
  52. private static readonly string ITEMCOUNT = "Repeater_Item_Count";
  53. private ITemplate alternatingItemTemplate;
  54. private ITemplate footerTemplate;
  55. private ITemplate headerTemplate;
  56. private ITemplate itemTemplate;
  57. private ITemplate separatorTemplate;
  58. private object dataSource;
  59. private RepeaterItemCollection items;
  60. private ArrayList itemsArrayList;
  61. public Repeater(): base()
  62. {
  63. }
  64. [WebCategory ("Action")]
  65. [WebSysDescription ("Raised when a command is executed in the DataList.")]
  66. public event RepeaterCommandEventHandler ItemCommand
  67. {
  68. add
  69. {
  70. Events.AddHandler(ItemCommandEvent, value);
  71. }
  72. remove
  73. {
  74. Events.RemoveHandler(ItemCommandEvent, value);
  75. }
  76. }
  77. [WebCategory ("Behavior")]
  78. [WebSysDescription ("Raised when an item gets created.")]
  79. public event RepeaterItemEventHandler ItemCreated
  80. {
  81. add
  82. {
  83. Events.AddHandler(ItemCreatedEvent, value);
  84. }
  85. remove
  86. {
  87. Events.RemoveHandler(ItemCreatedEvent, value);
  88. }
  89. }
  90. [WebCategory ("Behavior")]
  91. [WebSysDescription ("Raised when an item gets data-bound.")]
  92. public event RepeaterItemEventHandler ItemDataBound
  93. {
  94. add
  95. {
  96. Events.AddHandler(ItemDataBoundEvent, value);
  97. }
  98. remove
  99. {
  100. Events.RemoveHandler(ItemDataBoundEvent, value);
  101. }
  102. }
  103. [DefaultValue (null), Browsable (false), PersistenceMode (PersistenceMode.InnerProperty)]
  104. [TemplateContainer (typeof (RepeaterItem))]
  105. [WebSysDescription ("The template that is used to create an alternating item.")]
  106. public virtual ITemplate AlternatingItemTemplate
  107. {
  108. get
  109. {
  110. return alternatingItemTemplate;
  111. }
  112. set
  113. {
  114. alternatingItemTemplate = value;
  115. }
  116. }
  117. public override ControlCollection Controls
  118. {
  119. get
  120. {
  121. EnsureChildControls();
  122. return base.Controls;
  123. }
  124. }
  125. [DefaultValue (""), WebCategory ("Data")]
  126. [WebSysDescription ("The name of the table that is used for binding when a DataSource is specified.")]
  127. public virtual string DataMember
  128. {
  129. get
  130. {
  131. object o = ViewState["DataMember"];
  132. if(o != null)
  133. {
  134. return (string)o;
  135. }
  136. return String.Empty;
  137. }
  138. set
  139. {
  140. ViewState["DataMember"] = value;
  141. }
  142. }
  143. [DefaultValue (null), Bindable (true), WebCategory ("Data")]
  144. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  145. [WebSysDescription ("The DataSource that is used for data-binding.")]
  146. public virtual object DataSource
  147. {
  148. get
  149. {
  150. return dataSource;
  151. }
  152. set
  153. {
  154. if ((value!=null) && !(value is IListSource) && !(value is IEnumerable))
  155. throw new ArgumentException ("An invalid data source is being used for " +
  156. ID + ". A valid data source must implement either " +
  157. "IListSource or IEnumerable.");
  158. dataSource = value;
  159. }
  160. }
  161. [DefaultValue (null), Browsable (false), PersistenceMode (PersistenceMode.InnerProperty)]
  162. [TemplateContainer (typeof (RepeaterItem))]
  163. [WebSysDescription ("The template that is used to create a footer.")]
  164. public virtual ITemplate FooterTemplate
  165. {
  166. get
  167. {
  168. return footerTemplate;
  169. }
  170. set
  171. {
  172. footerTemplate = value;
  173. }
  174. }
  175. [DefaultValue (null), Browsable (false), PersistenceMode (PersistenceMode.InnerProperty)]
  176. [TemplateContainer (typeof (RepeaterItem))]
  177. [WebSysDescription ("The template that is used to create a header.")]
  178. public virtual ITemplate HeaderTemplate
  179. {
  180. get
  181. {
  182. return headerTemplate;
  183. }
  184. set
  185. {
  186. headerTemplate = value;
  187. }
  188. }
  189. [Browsable (false)]
  190. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  191. [WebSysDescription ("A collection containing all items.")]
  192. public virtual RepeaterItemCollection Items
  193. {
  194. get
  195. {
  196. if(items == null)
  197. {
  198. if(itemsArrayList == null)
  199. {
  200. EnsureChildControls();
  201. }
  202. items = new RepeaterItemCollection(itemsArrayList);
  203. }
  204. return items;
  205. }
  206. }
  207. [DefaultValue (null), Browsable (false), PersistenceMode (PersistenceMode.InnerProperty)]
  208. [TemplateContainer (typeof (RepeaterItem))]
  209. [WebSysDescription ("The template that is used to create an item.")]
  210. public virtual ITemplate ItemTemplate
  211. {
  212. get
  213. {
  214. return itemTemplate;
  215. }
  216. set
  217. {
  218. itemTemplate = value;
  219. }
  220. }
  221. [DefaultValue (null), Browsable (false), PersistenceMode (PersistenceMode.InnerProperty)]
  222. [TemplateContainer (typeof (RepeaterItem))]
  223. [WebSysDescription ("The template that is used to create a seperator.")]
  224. public virtual ITemplate SeparatorTemplate
  225. {
  226. get
  227. {
  228. return separatorTemplate;
  229. }
  230. set
  231. {
  232. separatorTemplate = value;
  233. }
  234. }
  235. public override void DataBind ()
  236. {
  237. #if NET_2_0
  238. RequiresDataBinding = false;
  239. #endif
  240. OnDataBinding (EventArgs.Empty);
  241. }
  242. protected override void CreateChildControls()
  243. {
  244. Controls.Clear ();
  245. if (ViewState[ITEMCOUNT] != null) {
  246. CreateControlHierarchy (false);
  247. } else {
  248. itemsArrayList = new ArrayList ();
  249. ClearChildViewState ();
  250. }
  251. }
  252. private RepeaterItem CreateItem (int itemIndex,
  253. ListItemType itemType,
  254. bool dataBind,
  255. object dataItem)
  256. {
  257. RepeaterItem repeaterItem = new RepeaterItem (itemIndex, itemType);
  258. RepeaterItemEventArgs repeaterEventArgs = new RepeaterItemEventArgs (repeaterItem);
  259. InstantiateItem (repeaterItem);
  260. if (dataBind)
  261. repeaterItem.DataItem = dataItem;
  262. OnItemCreated (repeaterEventArgs);
  263. Controls.Add (repeaterItem);
  264. if (dataBind) {
  265. repeaterItem.DataBind ();
  266. OnItemDataBound (repeaterEventArgs);
  267. repeaterItem.DataItem = null;
  268. }
  269. return repeaterItem;
  270. }
  271. private void InstantiateItem (RepeaterItem item)
  272. {
  273. ITemplate template;
  274. switch (item.ItemType) {
  275. case ListItemType.Header:
  276. template = this.headerTemplate;
  277. break;
  278. case ListItemType.Footer:
  279. template = this.footerTemplate;
  280. break;
  281. case ListItemType.Item:
  282. template = this.itemTemplate;
  283. break;
  284. case ListItemType.AlternatingItem:
  285. template = (alternatingItemTemplate != null ? this.alternatingItemTemplate : itemTemplate);
  286. break;
  287. case ListItemType.Separator:
  288. template = this.separatorTemplate;
  289. break;
  290. default:
  291. throw new HttpException ("Unknown ListItemType: " + item.ItemType);
  292. }
  293. if (template != null)
  294. template.InstantiateIn (item);
  295. }
  296. protected virtual void CreateControlHierarchy (bool useDataSource)
  297. {
  298. if (itemsArrayList != null) {
  299. itemsArrayList.Clear ();
  300. } else {
  301. itemsArrayList = new ArrayList ();
  302. }
  303. IEnumerable ds = null;
  304. if (useDataSource) {
  305. ds = GetResolvedDataSource ();
  306. } else {
  307. int itemCount = (int) ViewState [ITEMCOUNT];
  308. if (itemCount != -1)
  309. ds = new DataSourceInternal (itemCount);
  310. }
  311. int index = 0;
  312. if (ds != null) {
  313. if (headerTemplate != null)
  314. CreateItem (-1, ListItemType.Header, useDataSource, null);
  315. bool even = true;
  316. foreach (object item in ds){
  317. if (separatorTemplate != null && index > 0)
  318. CreateItem (index - 1, ListItemType.Separator,
  319. useDataSource, null);
  320. RepeaterItem repeaterItem;
  321. ListItemType lType;
  322. if (!even)
  323. lType = ListItemType.AlternatingItem;
  324. else
  325. lType = ListItemType.Item;
  326. repeaterItem = CreateItem (index, lType, useDataSource, item);
  327. itemsArrayList.Add (repeaterItem);
  328. index++;
  329. even = !even;
  330. }
  331. if (footerTemplate != null)
  332. CreateItem (-1, ListItemType.Footer, useDataSource, null);
  333. }
  334. if (useDataSource)
  335. ViewState [ITEMCOUNT] = (ds == null) ? -1 : index;
  336. }
  337. protected override bool OnBubbleEvent(object sender, EventArgs e)
  338. {
  339. bool retVal = false;
  340. if(e is RepeaterCommandEventArgs)
  341. {
  342. OnItemCommand((RepeaterCommandEventArgs)e);
  343. retVal = true;
  344. }
  345. return retVal;
  346. }
  347. protected override void OnDataBinding(EventArgs e)
  348. {
  349. base.OnDataBinding(e);
  350. Controls.Clear();
  351. ClearChildViewState();
  352. CreateControlHierarchy(true);
  353. ChildControlsCreated = true;
  354. }
  355. protected virtual void OnItemCommand(RepeaterCommandEventArgs e)
  356. {
  357. if(Events != null)
  358. {
  359. RepeaterCommandEventHandler rceh = (RepeaterCommandEventHandler)
  360. Events [ItemCommandEvent];
  361. if(rceh != null)
  362. {
  363. rceh(this, e);
  364. }
  365. }
  366. }
  367. protected virtual void OnItemCreated(RepeaterItemEventArgs e)
  368. {
  369. if(Events != null)
  370. {
  371. RepeaterItemEventHandler rceh = (RepeaterItemEventHandler)
  372. Events [ItemCreatedEvent];
  373. if(rceh != null)
  374. {
  375. rceh(this, e);
  376. }
  377. }
  378. }
  379. protected virtual void OnItemDataBound(RepeaterItemEventArgs e)
  380. {
  381. if(Events != null)
  382. {
  383. RepeaterItemEventHandler rceh = (RepeaterItemEventHandler)
  384. Events [ItemDataBoundEvent];
  385. if(rceh != null)
  386. {
  387. rceh(this, e);
  388. }
  389. }
  390. }
  391. protected virtual RepeaterItem CreateItem (int itemIndex, ListItemType itemType)
  392. {
  393. return new RepeaterItem (itemIndex, itemType);
  394. }
  395. protected virtual void InitializeItem (RepeaterItem item)
  396. {
  397. InstantiateItem (item);
  398. }
  399. #if NET_2_0
  400. // should be `internal protected' (why, oh WHY did they do that !?!)
  401. protected override void OnInit (EventArgs e)
  402. {
  403. base.OnInit(e);
  404. inited = true;
  405. if (!Page.IsPostBack)
  406. RequiresDataBinding = true;
  407. }
  408. // should be `internal protected' (why, oh WHY did they do that !?!)
  409. protected override void OnLoad (EventArgs e)
  410. {
  411. IDataSource ds = GetDataSourceObject () as IDataSource;
  412. if (ds != null && DataSourceID != "")
  413. ds.DataSourceChanged += new EventHandler (OnDataSourceChanged);
  414. base.OnLoad(e);
  415. }
  416. // should be `internal protected' (why, oh WHY did they do that !?!)
  417. protected override void OnPreRender (EventArgs e)
  418. {
  419. EnsureDataBound ();
  420. base.OnPreRender (e);
  421. }
  422. protected void EnsureDataBound ()
  423. {
  424. if (RequiresDataBinding && DataSourceID != "")
  425. DataBind ();
  426. }
  427. protected virtual object GetDataSourceObject ()
  428. {
  429. if (DataSourceID != "")
  430. return (IDataSource) NamingContainer.FindControl (DataSourceID);
  431. return DataSource;
  432. }
  433. protected virtual IEnumerable GetResolvedDataSource ()
  434. {
  435. if (DataSource != null && DataSourceID != "")
  436. throw new HttpException ();
  437. IDataSource ds = this.GetDataSourceObject () as IDataSource;
  438. if (ds != null && DataSourceID != "")
  439. return ds.GetView (DataMember).Select ();
  440. else if (DataSource != null)
  441. return DataSourceHelper.GetResolvedDataSource (DataSource, DataMember);
  442. else
  443. return null;
  444. }
  445. protected void OnDataSourceChanged (object sender, EventArgs e)
  446. {
  447. RequiresDataBinding = true;
  448. }
  449. public virtual string DataSourceID {
  450. get {
  451. object o = ViewState ["DataSourceID"];
  452. if (o != null)
  453. return (string)o;
  454. return String.Empty;
  455. }
  456. set {
  457. if (inited)
  458. RequiresDataBinding = true;
  459. ViewState ["DataSourceID"] = value;
  460. }
  461. }
  462. bool requiresDataBinding;
  463. protected bool RequiresDataBinding {
  464. get { return requiresDataBinding; }
  465. set { requiresDataBinding = value; }
  466. }
  467. protected bool inited;
  468. #else
  469. IEnumerable GetResolvedDataSource ()
  470. {
  471. if (DataSource != null)
  472. return DataSourceHelper.GetResolvedDataSource (DataSource, DataMember);
  473. else
  474. return null;
  475. }
  476. #endif
  477. }
  478. }