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