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