2004-06-09 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / System.Web / System.Web.UI.WebControls / DataList.cs
1 //
2 // System.Web.UI.WebControls.DataList.cs
3 //
4 // Authors:
5 //   Gaurav Vaish (gvaish@iitk.ac.in)
6 //   Andreas Nahr (ClassDevelopment@A-SoftTech.com)
7 //
8 // (C) Gaurav Vaish (2002)
9 // (C) 2003 Andreas Nahr
10 //
11
12 using System;
13 using System.Collections;
14 using System.ComponentModel;
15 using System.ComponentModel.Design;
16 using System.Web;
17 using System.Web.UI;
18 using System.Web.Util;
19
20 namespace System.Web.UI.WebControls
21 {
22         [Designer("System.Web.UI.Design.WebControls.DataListDesigner, " + Consts.AssemblySystem_Design, typeof (IDesigner))]
23         [Editor ("System.Web.UI.Design.WebControls.DataListComponentEditor, " + Consts.AssemblySystem_Design, typeof (ComponentEditor))]
24         public class DataList: BaseDataList, INamingContainer, IRepeatInfoUser
25         {
26                 public const string CancelCommandName = "Cancel";
27                 public const string DeleteCommandName = "Delete";
28                 public const string EditCommandName   = "Edit";
29                 public const string SelectCommandName = "Select";
30                 public const string UpdateCommandName = "Update";
31
32                 static readonly object CancelCommandEvent = new object ();
33                 static readonly object DeleteCommandEvent = new object ();
34                 static readonly object EditCommandEvent   = new object ();
35                 static readonly object ItemCommandEvent   = new object ();
36                 static readonly object ItemCreatedEvent   = new object ();
37                 static readonly object ItemDataBoundEvent = new object ();
38                 static readonly object UpdateCommandEvent = new object ();
39
40                 TableItemStyle alternatingItemStyle;
41                 TableItemStyle editItemStyle;
42                 TableItemStyle footerStyle;
43                 TableItemStyle headerStyle;
44                 TableItemStyle itemStyle;
45                 TableItemStyle selectedItemStyle;
46                 TableItemStyle separatorStyle;
47
48                 ITemplate alternatingItemTemplate;
49                 ITemplate editItemTemplate;
50                 ITemplate footerTemplate;
51                 ITemplate headerTemplate;
52                 ITemplate itemTemplate;
53                 ITemplate selectedItemTemplate;
54                 ITemplate separatorTemplate;
55
56                 ArrayList itemsArray;
57                 DataListItemCollection items;
58
59                 bool extractTemplateRows;
60
61                 public DataList ()
62                 {
63                 }
64
65                 [DefaultValue (null)]
66                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
67                 [NotifyParentProperty (true)]
68                 [WebCategory ("Style")]
69                 [PersistenceMode (PersistenceMode.InnerProperty)]
70                 [WebSysDescription ("The style applied to alternating items.")]
71                 public virtual TableItemStyle AlternatingItemStyle {
72                         get {
73                                 if (alternatingItemStyle == null) {
74                                         alternatingItemStyle = new TableItemStyle ();
75                                         if (IsTrackingViewState)
76                                                 alternatingItemStyle.TrackViewState ();
77                                 }
78
79                                 return alternatingItemStyle;
80                         }
81                 }
82
83                 [Browsable (false)]
84                 [DefaultValue (null)]
85                 [TemplateContainer (typeof (DataListItem))]
86                 [PersistenceMode (PersistenceMode.InnerProperty)]
87                 [WebSysDescription ("The template used for alternating items.")]
88                 public virtual ITemplate AlternatingItemTemplate {
89                         get { return alternatingItemTemplate; }
90                         set { alternatingItemTemplate = value; }
91                 }
92
93                 [DefaultValue (-1)]
94                 [WebCategory ("Misc")]
95                 [WebSysDescription ("The index of the item shown in edit mode.")]
96                 public virtual int EditItemIndex {
97                         get {
98                                 object o = ViewState ["EditItemIndex"];
99                                 if (o != null)
100                                         return (int) o;
101
102                                 return -1;
103                         }
104
105                         set {
106                                 if (value < -1)
107                                          throw new ArgumentOutOfRangeException("value");
108                                  
109                                 ViewState ["EditItemIndex"] = value; 
110                         }
111                 }
112
113                 [DefaultValue (null)]
114                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
115                 [NotifyParentProperty (true)]
116                 [WebCategory ("Style")]
117                 [PersistenceMode (PersistenceMode.InnerProperty)]
118                 [WebSysDescription ("The style applied to items in edit mode.")]
119                 public virtual TableItemStyle EditItemStyle {
120                         get {
121                                 if (editItemStyle == null) {
122                                         editItemStyle = new TableItemStyle ();
123                                         if (IsTrackingViewState)
124                                                 editItemStyle.TrackViewState ();
125                                 }
126
127                                 return editItemStyle;
128                         }
129                 }
130
131                 [Browsable (false)]
132                 [DefaultValue (null)]
133                 [TemplateContainer (typeof (DataListItem))]
134                 [PersistenceMode (PersistenceMode.InnerProperty)]
135                 [WebSysDescription ("The template used for items in edit mode.")]
136                 public virtual ITemplate EditItemTemplate {
137                         get { return editItemTemplate; }
138                         set { editItemTemplate = value; }
139                 }
140
141
142                 [DefaultValue (false), WebCategory ("Misc")]
143                 [WebSysDescription ("Extract rows in the template.")]
144                 public virtual bool ExtractTemplateRows {
145                         get {
146                                 object o = ViewState ["ExtractTemplateRows"];
147                                 if (o != null)
148                                         return (bool) o;
149
150                                 return false;
151                         }
152
153                         set { ViewState ["ExtractTemplateRows"] = value; }
154                 }
155
156                 [DefaultValue (null)]
157                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
158                 [NotifyParentProperty (true)]
159                 [WebCategory ("Style")]
160                 [PersistenceMode (PersistenceMode.InnerProperty)]
161                 [WebSysDescription ("The style applied to the footer.")]
162                 public virtual TableItemStyle FooterStyle {
163                         get {
164                                 if (footerStyle == null) {
165                                         footerStyle = new TableItemStyle ();
166                                         if (IsTrackingViewState)
167                                                 footerStyle.TrackViewState ();
168                                 }
169
170                                 return footerStyle;
171                         }
172                 }
173
174                 [Browsable (false)]
175                 [DefaultValue (null)]
176                 [TemplateContainer (typeof (DataListItem))]
177                 [PersistenceMode (PersistenceMode.InnerProperty)]
178                 [WebSysDescription ("The template used for the footer.")]
179                 public virtual ITemplate FooterTemplate {
180                         get { return footerTemplate; }
181                         set { footerTemplate = value; }
182                 }
183
184                 [DefaultValue (typeof (GridLines), "None")]
185                 public override GridLines GridLines {
186                         get { return base.GridLines; }
187                         set { base.GridLines = value; }
188                 }
189
190                 [DefaultValue (null)]
191                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
192                 [NotifyParentProperty (true)]
193                 [WebCategory ("Style")]
194                 [PersistenceMode (PersistenceMode.InnerProperty)]
195                 [WebSysDescription ("The style applied to the header.")]
196                 public virtual TableItemStyle HeaderStyle {
197                         get {
198                                 if (headerStyle == null) {
199                                         headerStyle = new TableItemStyle ();
200                                         if (IsTrackingViewState)
201                                                 headerStyle.TrackViewState ();
202                                 }
203
204                                 return headerStyle;
205                         }
206                 }
207
208                 [Browsable (false)]
209                 [DefaultValue (null)]
210                 [TemplateContainer (typeof (DataListItem))]
211                 [PersistenceMode (PersistenceMode.InnerProperty)]
212                 [WebSysDescription ("The template used for the header.")]
213                 public virtual ITemplate HeaderTemplate {
214                         get { return headerTemplate; }
215                         set { headerTemplate = value; }
216                 }
217
218                 [Browsable (false)]
219                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
220                 [WebSysDescription ("A colletion containing all items.")]
221                 public virtual DataListItemCollection Items {
222                         get {
223                                 if (items == null) {
224                                         if (itemsArray == null) {
225                                                 EnsureChildControls ();
226                                                 itemsArray = new ArrayList ();
227                                         }
228                                         items = new DataListItemCollection (itemsArray);
229                                 }
230
231                                 return items;
232                         }
233                 }
234
235                 [DefaultValue (null)]
236                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
237                 [NotifyParentProperty (true)]
238                 [WebCategory ("Style")]
239                 [PersistenceMode (PersistenceMode.InnerProperty)]
240                 [WebSysDescription ("The style applied to items.")]
241                 public virtual TableItemStyle ItemStyle {
242                         get {
243                                 if (itemStyle == null) {
244                                         itemStyle = new TableItemStyle ();
245                                         if (IsTrackingViewState)
246                                                 itemStyle.TrackViewState ();
247                                 }
248
249                                 return itemStyle;
250                         }
251                 }
252
253                 [Browsable (false)]
254                 [DefaultValue (null)]
255                 [TemplateContainer (typeof (DataListItem))]
256                 [PersistenceMode (PersistenceMode.InnerProperty)]
257                 [WebSysDescription ("The template used for items.")]
258                 public virtual ITemplate ItemTemplate {
259                         get { return itemTemplate; }
260                         set { itemTemplate = value; }
261                 }
262
263
264                 [DefaultValue (0), Bindable (true), WebCategory ("Layout")]
265                 [WebSysDescription ("The number of columns that should be used.")]
266                 public virtual int RepeatColumns {
267                         get {
268                                 object o = ViewState ["RepeatColumns"];
269                                 if (o != null)
270                                         return (int) o;
271
272                                 return 0;
273                         }
274                         set {
275                                 if (value < 0)
276                                         throw new ArgumentOutOfRangeException ("value", "RepeatColumns value has to be 0 for 'not set' or > 0.");
277
278                                 ViewState ["RepeatColumns"] = value;
279                         }
280                 }
281
282                 [DefaultValue (typeof (RepeatDirection), "Vertical"), Bindable (true), WebCategory ("Layout")]
283                 [WebSysDescription ("Which direction should be used when filling the columns.")]
284                 public virtual RepeatDirection RepeatDirection {
285                         get {
286                                 object o = ViewState ["RepeatDirection"];
287                                 if (o != null)
288                                         return (RepeatDirection) o;
289
290                                 return RepeatDirection.Vertical;
291                         }
292                         set {
293                                 if (!Enum.IsDefined (typeof (RepeatDirection), value))
294                                         throw new ArgumentOutOfRangeException ("value", "Only valid enumeration members are allowed");
295
296                                 ViewState ["RepeatDirection"] = value;
297                         }
298                 }
299
300                 [DefaultValue (typeof (RepeatLayout), "Table"), Bindable (true), WebCategory ("Layout")]
301                 [WebSysDescription ("The type of layout - mechanism that is used.")]
302                 public virtual RepeatLayout RepeatLayout {
303                         get {
304                                 object o = ViewState ["RepeatLayout"];
305                                 if (o != null)
306                                         return (RepeatLayout) o;
307
308                                 return RepeatLayout.Table;
309                         }
310                         set {
311                                 if (!Enum.IsDefined (typeof (RepeatLayout), value))
312                                         throw new ArgumentOutOfRangeException ("value", "Only valid enumeration members are allowed");
313
314                                 ViewState ["RepeatLayout"] = value;
315                         }
316                 }
317
318                 [DefaultValue (-1), Bindable (true)]
319                 [WebSysDescription ("The currently selected item index number.")]
320                 public virtual int SelectedIndex {
321                         get {
322                                 object o = ViewState ["SelectedIndex"];
323                                 if (o != null)
324                                         return (int) o;
325
326                                 return -1;
327                         }
328                         set {
329                                 //FIXME: Looks like a bug in Microsoft's specs.
330                                 // Exception is missing in document. I haven't tested the case
331                                 // But I think exception should follow
332                                 if (value < -1)
333                                         throw new ArgumentOutOfRangeException("value");
334
335                                 int prevSel = SelectedIndex;
336                                 ViewState ["SelectedIndex"] = value;
337                                 DataListItem prevSelItem;
338                                 ListItemType liType;
339
340                                 if (itemsArray != null) {
341                                         if (prevSel >= 0 && prevSel < itemsArray.Count) {
342                                                 prevSelItem = (DataListItem) itemsArray [prevSel];
343                                                 if (prevSelItem.ItemType != ListItemType.EditItem) {
344                                                         liType = ((prevSel % 2) == 0 ? ListItemType.AlternatingItem :
345                                                                                        ListItemType.Item);
346
347                                                         prevSelItem.SetItemType (liType);
348                                                 }
349                                         }
350
351                                         if (value >= 0 && value < itemsArray.Count) {
352                                                 prevSelItem = (DataListItem) itemsArray [value];
353                                                 if (prevSelItem.ItemType != ListItemType.EditItem) {
354                                                         prevSelItem.SetItemType (ListItemType.SelectedItem);
355                                                 }
356                                         }
357                                 }
358                         }
359                 }
360
361                 [Browsable (false)]
362                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
363                 [WebSysDescription ("The currently selected item.")]
364                 public virtual DataListItem SelectedItem {
365                         get {
366                                 if (SelectedIndex == -1)
367                                         return null;
368
369                                 return Items [SelectedIndex];
370                         }
371                 }
372
373                 [DefaultValue (null)]
374                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
375                 [NotifyParentProperty (true)]
376                 [WebCategory ("Style")]
377                 [PersistenceMode (PersistenceMode.InnerProperty)]
378                 [WebSysDescription ("The style used for the currently selected item.")]
379                 public virtual TableItemStyle SelectedItemStyle {
380                         get {
381                                 if (selectedItemStyle == null) {
382                                         selectedItemStyle = new TableItemStyle ();
383                                         if (IsTrackingViewState)
384                                                 selectedItemStyle.TrackViewState ();
385                                 }
386
387                                 return selectedItemStyle;
388                         }
389                 }
390
391                 [Browsable (false)]
392                 [DefaultValue (null)]
393                 [TemplateContainer (typeof (DataListItem))]
394                 [PersistenceMode (PersistenceMode.InnerProperty)]
395                 [WebSysDescription ("The template used for currently selected items.")]
396                 public virtual ITemplate SelectedItemTemplate {
397                         get { return selectedItemTemplate; }
398                         set { selectedItemTemplate = value; }
399                 }
400
401                 [DefaultValue (null)]
402                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
403                 [NotifyParentProperty (true)]
404                 [WebCategory ("Style")]
405                 [PersistenceMode (PersistenceMode.InnerProperty)]
406                 [WebSysDescription ("The style applied to separators.")]
407                 public virtual TableItemStyle SeparatorStyle {
408                         get {
409                                 if (separatorStyle == null) {
410                                         separatorStyle = new TableItemStyle ();
411                                         if (IsTrackingViewState)
412                                                 separatorStyle.TrackViewState ();
413                                 }
414
415                                 return separatorStyle;
416                         }
417                 }
418
419                 [Browsable (false)]
420                 [DefaultValue (null)]
421                 [TemplateContainer (typeof (DataListItem))]
422                 [PersistenceMode (PersistenceMode.InnerProperty)]
423                 [WebSysDescription ("The template used for separators.")]
424                 public virtual ITemplate SeparatorTemplate {
425                         get { return separatorTemplate; }
426                         set { separatorTemplate = value; }
427                 }
428
429                 [DefaultValue (true), Bindable (true), WebCategory ("Appearance")]
430                 [WebSysDescription ("Display the header for the DataList.")]
431                 public virtual bool ShowHeader {
432                         get {
433                                 object o = ViewState ["ShowHeader"];
434                                 if (o != null)
435                                         return (bool) o;
436
437                                 return true;
438                         }
439                         set { ViewState ["ShowHeader"] = value; }
440                 }
441
442                 [DefaultValue (true), Bindable (true), WebCategory ("Appearance")]
443                 [WebSysDescription ("Display the footer for the DataList.")]
444                 public virtual bool ShowFooter {
445                         get {
446                                 object o = ViewState ["ShowFooter"];
447                                 if (o != null)
448                                         return (bool) o;
449
450                                 return true;
451                         }
452                         set
453                         {
454                                 ViewState["ShowFooter"] = value;
455                         }
456                 }
457
458                 [WebCategory ("Action")]
459                 [WebSysDescription ("Raised when a cancel command is generated.")]
460                 public event DataListCommandEventHandler CancelCommand {
461                         add { Events.AddHandler (CancelCommandEvent, value); }
462                         remove { Events.RemoveHandler (CancelCommandEvent, value); }
463                 }
464
465                 [WebCategory ("Action")]
466                 [WebSysDescription ("Raised when a delete command is generated.")]
467                 public event DataListCommandEventHandler DeleteCommand {
468                         add { Events.AddHandler (DeleteCommandEvent, value); }
469                         remove { Events.RemoveHandler (DeleteCommandEvent, value); }
470                 }
471
472                 [WebCategory ("Action")]
473                 [WebSysDescription ("Raised when an edit command is generated.")]
474                 public event DataListCommandEventHandler EditCommand {
475                         add { Events.AddHandler (EditCommandEvent, value); }
476                         remove { Events.RemoveHandler (EditCommandEvent, value); }
477                 }
478
479                 [WebCategory ("Action")]
480                 [WebSysDescription ("Raised when an item command is generated.")]
481                 public event DataListCommandEventHandler ItemCommand {
482                         add { Events.AddHandler (ItemCommandEvent, value); }
483                         remove { Events.RemoveHandler (ItemCommandEvent, value); }
484                 }
485
486                 [WebCategory ("Behavior")]
487                 [WebSysDescription ("Raised when a new item is created.")]
488                 public event DataListItemEventHandler ItemCreated {
489                         add { Events.AddHandler (ItemCreatedEvent, value); }
490                         remove { Events.RemoveHandler (ItemCreatedEvent, value); }
491                 }
492
493                 [WebCategory ("Behavior")]
494                 [WebSysDescription ("Raised when a item gets data-bound.")]
495                 public event DataListItemEventHandler ItemDataBound {
496                         add { Events.AddHandler (ItemDataBoundEvent, value); }
497                         remove { Events.RemoveHandler (ItemDataBoundEvent, value); }
498                 }
499
500                 [WebCategory ("Action")]
501                 [WebSysDescription ("Raised when an update command is generated.")]
502                 public event DataListCommandEventHandler UpdateCommand {
503                         add { Events.AddHandler (UpdateCommandEvent, value); }
504                         remove { Events.RemoveHandler (UpdateCommandEvent, value); }
505                 }
506
507                 protected override Style CreateControlStyle ()
508                 {
509                         TableStyle retVal = new TableStyle (ViewState);
510                         retVal.CellSpacing = 0;
511                         return retVal;
512                 }
513
514                 protected override void LoadViewState (object savedState)
515                 {
516                         if (savedState == null)
517                                 return;
518
519                         object [] states = (object []) savedState;
520
521                         if (states [0] != null)
522                                 base.LoadViewState (states [0]);
523                         if (states [1] != null)
524                                 alternatingItemStyle.LoadViewState (states [1]);
525                         if (states [2] != null)
526                                 editItemStyle.LoadViewState (states [2]);
527                         if (states [3] != null)
528                                 footerStyle.LoadViewState (states [3]);
529                         if (states [4] != null)
530                                 headerStyle.LoadViewState (states [4]);
531                         if (states [5] != null)
532                                 itemStyle.LoadViewState (states [5]);
533                         if (states [6] != null)
534                                 selectedItemStyle.LoadViewState (states [6]);
535                         if (states [7] != null)
536                                 separatorStyle.LoadViewState (states [7]);
537                 }
538
539                 protected override object SaveViewState()
540                 {
541                         object [] states = new object [8];
542                         states [0] = base.SaveViewState ();
543                         states [1] = (alternatingItemStyle == null ? null : alternatingItemStyle.SaveViewState ());
544                         states [2] = (editItemStyle == null        ? null : editItemStyle.SaveViewState ());
545                         states [3] = (footerStyle == null          ? null : footerStyle.SaveViewState ());
546                         states [4] = (headerStyle == null          ? null : headerStyle.SaveViewState ());
547                         states [5] = (itemStyle == null            ? null : itemStyle.SaveViewState ());
548                         states [6] = (selectedItemStyle == null    ? null : selectedItemStyle.SaveViewState ());
549                         states [7] = (separatorStyle == null       ? null : separatorStyle.SaveViewState ());
550                         return states;
551                 }
552
553                 protected override void TrackViewState ()
554                 {
555                         base.TrackViewState ();
556                         if (alternatingItemStyle != null)
557                                 alternatingItemStyle.TrackViewState ();
558                         if (editItemStyle != null)
559                                 editItemStyle.TrackViewState ();
560                         if (footerStyle != null)
561                                 footerStyle.TrackViewState ();
562                         if (headerStyle != null)
563                                 headerStyle.TrackViewState ();
564                         if (itemStyle != null)
565                                 itemStyle.TrackViewState ();
566                         if (selectedItemStyle != null)
567                                 selectedItemStyle.TrackViewState ();
568                         if (separatorStyle != null)
569                                 separatorStyle.TrackViewState ();
570                 }
571
572                 protected override bool OnBubbleEvent (object source, EventArgs e)
573                 {
574                         if (!(e is DataListCommandEventArgs))
575                                 return false;
576
577                         DataListCommandEventArgs args = (DataListCommandEventArgs) e;
578                         OnItemCommand (args);
579                         string cmdName = args.CommandName.ToLower ();
580
581                         if (cmdName == "cancel") {
582                                 OnCancelCommand (args);
583                         } else if (cmdName == "delete") {
584                                 OnDeleteCommand (args);
585                         } else if (cmdName == "edit") {
586                                 OnEditCommand (args);
587                         } else if (cmdName == "select") {
588                                 SelectedIndex = args.Item.ItemIndex;
589                                 OnSelectedIndexChanged (EventArgs.Empty);
590                         } else if (cmdName == "update") {
591                                 OnUpdateCommand (args);
592                         }
593
594                         return true;
595                 }
596
597                 void InvokeCommandEvent (DataListCommandEventArgs args, object key)
598                 {
599                         DataListCommandEventHandler dlceh = (DataListCommandEventHandler) Events [key];
600                         if (dlceh != null)
601                                 dlceh (this, args);
602                 }
603                 
604                 void InvokeItemEvent (DataListItemEventArgs args, object key)
605                 {
606                         DataListItemEventHandler dlieh = (DataListItemEventHandler) Events [key];
607                         if (dlieh != null)
608                                 dlieh (this, args);
609                 }
610                 
611                 protected virtual void OnCancelCommand (DataListCommandEventArgs e)
612                 {
613                         InvokeCommandEvent (e, CancelCommandEvent);
614                 }
615
616                 protected virtual void OnDeleteCommand (DataListCommandEventArgs e)
617                 {
618                         InvokeCommandEvent (e, DeleteCommandEvent);
619                 }
620
621                 protected virtual void OnEditCommand (DataListCommandEventArgs e)
622                 {
623                         InvokeCommandEvent (e, EditCommandEvent);
624                 }
625
626                 protected virtual void OnItemCommand (DataListCommandEventArgs e)
627                 {
628                         InvokeCommandEvent (e, ItemCommandEvent);
629                 }
630
631                 protected virtual void OnItemCreated (DataListItemEventArgs e)
632                 {
633                         InvokeItemEvent (e, ItemCreatedEvent);
634                 }
635
636                 protected virtual void OnItemDataBound (DataListItemEventArgs e)
637                 {
638                         InvokeItemEvent (e, ItemDataBoundEvent);
639                 }
640
641                 protected virtual void OnUpdateCommand (DataListCommandEventArgs e)
642                 {
643                         InvokeCommandEvent (e, UpdateCommandEvent);
644                 }
645
646                 protected override void RenderContents (HtmlTextWriter writer)
647                 {
648                         if (Controls.Count == 0)
649                                 return;
650
651                         RepeatInfo repeater = new RepeatInfo ();
652                         Table templateTable = null;
653                         if (extractTemplateRows) {
654                                 repeater.RepeatDirection = RepeatDirection.Vertical;
655                                 repeater.RepeatLayout  = RepeatLayout.Flow;
656                                 repeater.RepeatColumns = 1;
657                                 repeater.OuterTableImplied = true;
658                                 
659                                 templateTable = new Table ();
660                                 templateTable.ID = ClientID;
661                                 templateTable.CopyBaseAttributes (this);
662                                 templateTable.ApplyStyle (ControlStyle);
663                                 templateTable.RenderBeginTag (writer);
664                         } else {
665                                 repeater.RepeatDirection = RepeatDirection;
666                                 repeater.RepeatLayout = RepeatLayout;
667                                 repeater.RepeatColumns = RepeatColumns;
668                         }
669
670                         repeater.RenderRepeater (writer, this, ControlStyle, this);
671                         if (templateTable != null) {
672                                 templateTable.RenderEndTag (writer);
673                         }
674                 }
675
676                 private DataListItem GetItem (ListItemType itemType, int repeatIndex)
677                 {
678                         DataListItem retVal = null;
679                         switch (itemType) {
680                         case ListItemType.Header:
681                                 retVal = (DataListItem) Controls [0];
682                                 break;
683                         case ListItemType.Footer:
684                                 retVal = (DataListItem) Controls [Controls.Count - 1];
685                                 break;
686                         case ListItemType.Item:
687                                 goto case ListItemType.EditItem;
688                         case ListItemType.AlternatingItem:
689                                 goto case ListItemType.EditItem;
690                         case ListItemType.SelectedItem:
691                                 goto case ListItemType.EditItem;
692                         case ListItemType.EditItem:
693                                 retVal = (DataListItem) itemsArray [repeatIndex];
694                                 break;
695                         case ListItemType.Separator:
696                                 int index = 2 * repeatIndex + 1;
697                                 if (headerTemplate != null)
698                                         index ++;
699                                 retVal = (DataListItem) Controls [index];
700                                 break;
701                         }
702                         return retVal;
703                 }
704
705                 /// <summary>
706                 /// Undocumented
707                 /// </summary>
708                 protected override void CreateControlHierarchy (bool useDataSource)
709                 {
710                         IEnumerable source = null;
711                         ArrayList dkeys = DataKeysArray;
712
713                         if (itemsArray != null) {
714                                 itemsArray.Clear ();
715                         } else {
716                                 itemsArray = new ArrayList ();
717                         }
718
719                         extractTemplateRows = ExtractTemplateRows;
720                         if (!useDataSource) {
721                                 int count = (int) ViewState ["_!ItemCount"];
722                                 if (count != -1) {
723                                         source = new DataSourceInternal (count);
724                                         itemsArray.Capacity = count;
725                                 }
726                         } else {
727                                 dkeys.Clear ();
728                                 source = GetResolvedDataSource ();
729                                 if (source is ICollection) {
730                                         dkeys.Capacity = ((ICollection) source).Count;
731                                         itemsArray.Capacity = ((ICollection) source).Count;
732                                 }
733                         }
734
735                         int itemCount = 0;
736                         if (source != null) {
737                                 int index = 0;
738                                 int editIndex = EditItemIndex;
739                                 int selIndex = SelectedIndex;
740                                 string dataKey = DataKeyField;
741                                 
742                                 if (headerTemplate != null)
743                                         CreateItem (-1, ListItemType.Header, useDataSource, null);
744
745                                 foreach (object current in source) {
746                                         if (useDataSource) {
747                                                 try {
748                                                         dkeys.Add (DataBinder.GetPropertyValue (current, dataKey));
749                                                 } catch {
750                                                         dkeys.Add (dkeys.Count);
751                                                 }
752                                         }
753
754                                         ListItemType type = ListItemType.Item;
755                                         if (index == editIndex) {
756                                                 type = ListItemType.EditItem;
757                                         } else if (index == selIndex) {
758                                                 type = ListItemType.SelectedItem;
759                                         } else if ((index % 2) != 0) {
760                                                 type = ListItemType.AlternatingItem;
761                                         }
762
763                                         itemsArray.Add (CreateItem (index, type, useDataSource, current));
764                                         if (separatorTemplate != null)
765                                                 CreateItem (index, ListItemType.Separator, useDataSource, null);
766                                         itemCount++;
767                                         index++;
768                                 }
769
770                                 if (footerTemplate != null)
771                                         CreateItem (-1, ListItemType.Footer, useDataSource, null);
772                         }
773
774                         if (useDataSource)
775                                 ViewState ["_!ItemCount"] = (source != null ? itemCount : -1);
776                 }
777
778                 /// <summary>
779                 /// Undocumented
780                 /// </summary>
781                 protected virtual DataListItem CreateItem (int itemIndex, ListItemType itemType)
782                 {
783                         return new DataListItem (itemIndex, itemType);
784                 }
785
786                 private DataListItem CreateItem (int itemIndex, ListItemType itemType, bool dataBind, object dataItem)
787                 {
788                         DataListItem retVal = CreateItem (itemIndex, itemType);
789                         DataListItemEventArgs e = new DataListItemEventArgs (retVal);
790                         InitializeItem (retVal);
791                         if (dataBind)
792                                 retVal.DataItem = dataItem;
793                 
794                         OnItemCreated (e);
795                         Controls.Add (retVal);
796
797                         if (dataBind) {
798                                 retVal.DataBind ();
799                                 OnItemDataBound (e);
800                                 retVal.DataItem = null;
801                         }
802
803                         return retVal;
804                 }
805
806                 /// <summary>
807                 /// Undocumented
808                 /// </summary>
809                 protected override void PrepareControlHierarchy ()
810                 {
811                         if (Controls.Count == 0)
812                                 return;
813
814                         Style defaultStyle = null;
815                         Style rowStyle = null;
816
817                         if (alternatingItemStyle != null) {
818                                 defaultStyle = new TableItemStyle ();
819                                 defaultStyle.CopyFrom (itemStyle);
820                                 defaultStyle.CopyFrom (alternatingItemStyle);
821                         } else {
822                                 defaultStyle = itemStyle;
823                         }
824
825                         foreach (DataListItem current in Controls) {
826                                 rowStyle = null;
827                                 switch (current.ItemType) {
828                                 case ListItemType.Header:
829                                         if (headerStyle != null)
830                                                 rowStyle = headerStyle;
831                                         break;
832                                 case ListItemType.Footer:
833                                         if (footerStyle != null)
834                                                 rowStyle = footerStyle;
835                                         break;
836                                 case ListItemType.Separator:
837                                         rowStyle = separatorStyle;
838                                         break;
839                                 case ListItemType.Item:
840                                         rowStyle = itemStyle;
841                                         break;
842                                 case ListItemType.AlternatingItem:
843                                         rowStyle = defaultStyle;
844                                         break;
845                                 case ListItemType.SelectedItem:
846                                         rowStyle = new TableItemStyle ();
847                                         if ((current.ItemIndex % 2) == 0) {
848                                                 rowStyle.CopyFrom (itemStyle);
849                                         } else {
850                                                 rowStyle.CopyFrom (defaultStyle);
851                                         }
852                                         rowStyle.CopyFrom (selectedItemStyle);
853                                         break;
854                                 case ListItemType.EditItem:
855                                         rowStyle = new TableItemStyle ();
856                                         if ((current.ItemIndex % 2) == 0) {
857                                                 rowStyle.CopyFrom (itemStyle);
858                                         } else {
859                                                 rowStyle.CopyFrom (defaultStyle);
860                                         }
861
862                                         if (current.ItemIndex == SelectedIndex)
863                                                 rowStyle.CopyFrom (selectedItemStyle);
864
865                                         rowStyle.CopyFrom (editItemStyle);
866                                         break;
867                                 }
868
869                                 if (rowStyle == null)
870                                         continue;
871
872                                 if (!extractTemplateRows) {
873                                         current.MergeStyle (rowStyle);
874                                         continue;
875                                 }
876
877                                 foreach (Control currentCtrl in current.Controls) {
878                                         if (!(currentCtrl is Table))
879                                                 continue;
880
881                                         foreach (TableRow cRow in ((Table) currentCtrl).Rows)
882                                                 cRow.MergeStyle (rowStyle);
883                                 }
884                         }
885                 }
886
887                 /// <summary>
888                 /// Undocumented
889                 /// </summary>
890                 protected virtual void InitializeItem (DataListItem item)
891                 {
892                         ListItemType type = item.ItemType;
893                         ITemplate template = itemTemplate;
894
895                         switch (type) {
896                         case ListItemType.Header:
897                                 template = headerTemplate;
898                                 break;
899                         case ListItemType.Footer:
900                                 template = footerTemplate;
901                                 break;
902                         case ListItemType.AlternatingItem:
903                                 if (alternatingItemTemplate != null)
904                                         template = alternatingItemTemplate;
905                                 break;
906                         case ListItemType.SelectedItem:
907                                 if (selectedItemTemplate != null) {
908                                         template = selectedItemTemplate;
909                                         break;
910                                 }
911
912                                 if ((item.ItemIndex % 2) != 0)
913                                         goto case ListItemType.AlternatingItem;
914                                 break;
915                         case ListItemType.EditItem:
916                                 if (editItemTemplate != null) {
917                                         template = editItemTemplate;
918                                         break;
919                                 }
920
921                                 if (item.ItemIndex == SelectedIndex)
922                                         goto case ListItemType.SelectedItem;
923
924                                 if ((item.ItemIndex % 2) != 0)
925                                         goto case ListItemType.AlternatingItem;
926                                 break;
927                         case ListItemType.Separator:
928                                 template = separatorTemplate;
929                                 break;
930                         }
931
932                         if (template != null)
933                                 template.InstantiateIn (item);
934                 }
935
936                 bool IRepeatInfoUser.HasFooter {
937                         get { return (ShowFooter && footerTemplate != null); }
938                 }
939
940                 bool IRepeatInfoUser.HasHeader {
941                         get { return (ShowHeader && headerTemplate != null); }
942                 }
943
944                 bool IRepeatInfoUser.HasSeparators {
945                         get { return (separatorTemplate != null); }
946                 }
947
948                 int IRepeatInfoUser.RepeatedItemCount {
949                         get {
950                                 if (itemsArray != null)
951                                         return itemsArray.Count;
952
953                                 return 0;
954                         }
955                 }
956
957                 void IRepeatInfoUser.RenderItem (ListItemType itemType,
958                                                  int repeatIndex,
959                                                  RepeatInfo repeatInfo,
960                                                  HtmlTextWriter writer)
961                 {
962                         DataListItem item = GetItem (itemType, repeatIndex);
963                         if (item != null)
964                                 item.RenderItem (writer,
965                                                  extractTemplateRows,
966                                                  (repeatInfo.RepeatLayout == RepeatLayout.Table));
967                 }
968
969                 Style IRepeatInfoUser.GetItemStyle (ListItemType itemType, int repeatIndex)
970                 {
971                         DataListItem item = GetItem (itemType, repeatIndex);
972                         if (item == null || !item.ControlStyleCreated)
973                                 return null;
974
975                         return item.ControlStyle;
976                 }
977         }
978 }
979