2010-03-12 Jb Evain <jbevain@novell.com>
[mono.git] / mcs / class / System.Web / System.Web.UI.WebControls / FormView.cs
1 //
2 // System.Web.UI.WebControls.FormView.cs
3 //
4 // Authors:
5 //      Lluis Sanchez Gual (lluis@novell.com)
6 //
7 // (C) 2005 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 #if NET_2_0
30
31 using System;
32 using System.Collections;
33 using System.Collections.Specialized;
34 using System.ComponentModel;
35 using System.Web.UI;
36 using System.Security.Permissions;
37 using System.Text;
38 using System.IO;
39 using System.Reflection;
40
41 namespace System.Web.UI.WebControls
42 {
43         [SupportsEventValidation]
44         [DesignerAttribute ("System.Web.UI.Design.WebControls.FormViewDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
45         [ControlValuePropertyAttribute ("SelectedValue")]
46         [DefaultEventAttribute ("PageIndexChanging")]
47         [AspNetHostingPermissionAttribute (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
48         [AspNetHostingPermissionAttribute (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
49         public class FormView: CompositeDataBoundControl, IDataItemContainer, INamingContainer, IPostBackEventHandler, IPostBackContainer
50         {
51                 object dataItem;
52                 
53                 Table table;
54                 FormViewRow headerRow;
55                 FormViewRow footerRow;
56                 FormViewRow bottomPagerRow;
57                 FormViewRow topPagerRow;
58                 FormViewRow itemRow;
59                 
60                 IOrderedDictionary currentEditRowKeys;
61                 IOrderedDictionary currentEditNewValues;
62                 IOrderedDictionary currentEditOldValues;
63                 
64                 ITemplate pagerTemplate;
65                 ITemplate emptyDataTemplate;
66                 ITemplate headerTemplate;
67                 ITemplate footerTemplate;
68                 ITemplate editItemTemplate;
69                 ITemplate insertItemTemplate;
70                 ITemplate itemTemplate;
71                 
72                 PropertyDescriptor[] cachedKeyProperties;
73                 readonly string[] emptyKeys = new string[0];
74                 readonly string unhandledEventExceptionMessage = "The FormView '{0}' fired event {1} which wasn't handled.";
75                 
76                 // View state
77                 PagerSettings pagerSettings;
78                 
79                 TableItemStyle editRowStyle;
80                 TableItemStyle insertRowStyle;
81                 TableItemStyle emptyDataRowStyle;
82                 TableItemStyle footerStyle;
83                 TableItemStyle headerStyle;
84                 TableItemStyle pagerStyle;
85                 TableItemStyle rowStyle;
86                 
87                 IOrderedDictionary _keyTable;
88                 DataKey key;
89                 DataKey oldEditValues;
90                 
91                 static readonly object PageIndexChangedEvent = new object();
92                 static readonly object PageIndexChangingEvent = new object();
93                 static readonly object ItemCommandEvent = new object();
94                 static readonly object ItemCreatedEvent = new object();
95                 static readonly object ItemDeletedEvent = new object();
96                 static readonly object ItemDeletingEvent = new object();
97                 static readonly object ItemInsertedEvent = new object();
98                 static readonly object ItemInsertingEvent = new object();
99                 static readonly object ModeChangingEvent = new object();
100                 static readonly object ModeChangedEvent = new object();
101                 static readonly object ItemUpdatedEvent = new object();
102                 static readonly object ItemUpdatingEvent = new object();
103                 
104                 // Control state
105                 int pageIndex;
106                 FormViewMode currentMode = FormViewMode.ReadOnly; 
107                 bool hasCurrentMode;
108                 int pageCount;
109                 
110                 public event EventHandler PageIndexChanged {
111                         add { Events.AddHandler (PageIndexChangedEvent, value); }
112                         remove { Events.RemoveHandler (PageIndexChangedEvent, value); }
113                 }
114                 
115                 public event FormViewPageEventHandler PageIndexChanging {
116                         add { Events.AddHandler (PageIndexChangingEvent, value); }
117                         remove { Events.RemoveHandler (PageIndexChangingEvent, value); }
118                 }
119                 
120                 public event FormViewCommandEventHandler ItemCommand {
121                         add { Events.AddHandler (ItemCommandEvent, value); }
122                         remove { Events.RemoveHandler (ItemCommandEvent, value); }
123                 }
124                 
125                 public event EventHandler ItemCreated {
126                         add { Events.AddHandler (ItemCreatedEvent, value); }
127                         remove { Events.RemoveHandler (ItemCreatedEvent, value); }
128                 }
129                 
130                 public event FormViewDeletedEventHandler ItemDeleted {
131                         add { Events.AddHandler (ItemDeletedEvent, value); }
132                         remove { Events.RemoveHandler (ItemDeletedEvent, value); }
133                 }
134                 
135                 public event FormViewDeleteEventHandler ItemDeleting {
136                         add { Events.AddHandler (ItemDeletingEvent, value); }
137                         remove { Events.RemoveHandler (ItemDeletingEvent, value); }
138                 }
139                 
140                 public event FormViewInsertedEventHandler ItemInserted {
141                         add { Events.AddHandler (ItemInsertedEvent, value); }
142                         remove { Events.RemoveHandler (ItemInsertedEvent, value); }
143                 }
144                 
145                 public event FormViewInsertEventHandler ItemInserting {
146                         add { Events.AddHandler (ItemInsertingEvent, value); }
147                         remove { Events.RemoveHandler (ItemInsertingEvent, value); }
148                 }
149                 
150                 public event FormViewModeEventHandler ModeChanging {
151                         add { Events.AddHandler (ModeChangingEvent, value); }
152                         remove { Events.RemoveHandler (ModeChangingEvent, value); }
153                 }
154                 
155                 public event EventHandler ModeChanged {
156                         add { Events.AddHandler (ModeChangedEvent, value); }
157                         remove { Events.RemoveHandler (ModeChangedEvent, value); }
158                 }
159                 
160                 public event FormViewUpdatedEventHandler ItemUpdated {
161                         add { Events.AddHandler (ItemUpdatedEvent, value); }
162                         remove { Events.RemoveHandler (ItemUpdatedEvent, value); }
163                 }
164                 
165                 public event FormViewUpdateEventHandler ItemUpdating {
166                         add { Events.AddHandler (ItemUpdatingEvent, value); }
167                         remove { Events.RemoveHandler (ItemUpdatingEvent, value); }
168                 }
169                 
170                 protected virtual void OnPageIndexChanged (EventArgs e)
171                 {
172                         if (Events != null) {
173                                 EventHandler eh = (EventHandler) Events [PageIndexChangedEvent];
174                                 if (eh != null) eh (this, e);
175                         }
176                 }
177                 
178                 protected virtual void OnPageIndexChanging (FormViewPageEventArgs e)
179                 {
180                         if (Events != null) {
181                                 FormViewPageEventHandler eh = (FormViewPageEventHandler) Events [PageIndexChangingEvent];
182                                 if (eh != null) {
183                                         eh (this, e);
184                                         return;
185                                 }
186                         }
187                         if (!IsBoundUsingDataSourceID)
188                                 throw new HttpException (String.Format (unhandledEventExceptionMessage, ID, "PageIndexChanging"));
189                 }
190                 
191                 protected virtual void OnItemCommand (FormViewCommandEventArgs e)
192                 {
193                         if (Events != null) {
194                                 FormViewCommandEventHandler eh = (FormViewCommandEventHandler) Events [ItemCommandEvent];
195                                 if (eh != null) eh (this, e);
196                         }
197                 }
198                 
199                 protected virtual void OnItemCreated (EventArgs e)
200                 {
201                         if (Events != null) {
202                                 EventHandler eh = (EventHandler) Events [ItemCreatedEvent];
203                                 if (eh != null) eh (this, e);
204                         }
205                 }
206                 
207                 protected virtual void OnItemDeleted (FormViewDeletedEventArgs e)
208                 {
209                         if (Events != null) {
210                                 FormViewDeletedEventHandler eh = (FormViewDeletedEventHandler) Events [ItemDeletedEvent];
211                                 if (eh != null) eh (this, e);
212                         }
213                 }
214                 
215                 protected virtual void OnItemInserted (FormViewInsertedEventArgs e)
216                 {
217                         if (Events != null) {
218                                 FormViewInsertedEventHandler eh = (FormViewInsertedEventHandler) Events [ItemInsertedEvent];
219                                 if (eh != null) eh (this, e);
220                         }
221                 }
222                 
223                 protected virtual void OnItemInserting (FormViewInsertEventArgs e)
224                 {
225                         if (Events != null) {
226                                 FormViewInsertEventHandler eh = (FormViewInsertEventHandler) Events [ItemInsertingEvent];
227                                 if (eh != null) {
228                                         eh (this, e);
229                                         return;
230                                 }
231                         }
232                         if (!IsBoundUsingDataSourceID)
233                                 throw new HttpException (String.Format (unhandledEventExceptionMessage, ID, "ItemInserting"));
234                 }
235                 
236                 protected virtual void OnItemDeleting (FormViewDeleteEventArgs e)
237                 {
238                         if (Events != null) {
239                                 FormViewDeleteEventHandler eh = (FormViewDeleteEventHandler) Events [ItemDeletingEvent];
240                                 if (eh != null) {
241                                         eh (this, e);
242                                         return;
243                                 }
244                         }
245                         if (!IsBoundUsingDataSourceID)
246                                 throw new HttpException (String.Format (unhandledEventExceptionMessage, ID, "ItemDeleting"));
247                 }
248                 
249                 protected virtual void OnModeChanged (EventArgs e)
250                 {
251                         if (Events != null) {
252                                 EventHandler eh = (EventHandler) Events [ModeChangedEvent];
253                                 if (eh != null) eh (this, e);
254                         }
255                 }
256                 
257                 protected virtual void OnModeChanging (FormViewModeEventArgs e)
258                 {
259                         if (Events != null) {
260                                 FormViewModeEventHandler eh = (FormViewModeEventHandler) Events [ModeChangingEvent];
261                                 if (eh != null) {
262                                         eh (this, e);
263                                         return;
264                                 }
265                         }
266                         if (!IsBoundUsingDataSourceID)
267                                 throw new HttpException (String.Format (unhandledEventExceptionMessage, ID, "ModeChanging"));
268                 }
269                 
270                 protected virtual void OnItemUpdated (FormViewUpdatedEventArgs e)
271                 {
272                         if (Events != null) {
273                                 FormViewUpdatedEventHandler eh = (FormViewUpdatedEventHandler) Events [ItemUpdatedEvent];
274                                 if (eh != null) eh (this, e);
275                         }
276                 }
277                 
278                 protected virtual void OnItemUpdating (FormViewUpdateEventArgs e)
279                 {
280                         if (Events != null) {
281                                 FormViewUpdateEventHandler eh = (FormViewUpdateEventHandler) Events [ItemUpdatingEvent];
282                                 if (eh != null) {
283                                         eh (this, e);
284                                         return;
285                                 }
286                         }
287                         if (!IsBoundUsingDataSourceID)
288                                 throw new HttpException (String.Format (unhandledEventExceptionMessage, ID, "ItemUpdating"));
289                 }
290                 
291                 
292                 [WebCategoryAttribute ("Paging")]
293                 [DefaultValueAttribute (false)]
294                 public virtual bool AllowPaging {
295                         get {
296                                 object ob = ViewState ["AllowPaging"];
297                                 if (ob != null) return (bool) ob;
298                                 return false;
299                         }
300                         set {
301                                 ViewState ["AllowPaging"] = value;
302                                 RequireBinding ();
303                         }
304                 }
305                 
306                 [UrlPropertyAttribute]
307                 [WebCategoryAttribute ("Appearance")]
308                 [DefaultValueAttribute ("")]
309                 [EditorAttribute ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
310                 public virtual string BackImageUrl {
311                         get {
312                                 if (ControlStyleCreated)
313                                         return ((TableStyle) ControlStyle).BackImageUrl;
314                                 return String.Empty;
315                         }
316                         set {
317                                 ((TableStyle) ControlStyle).BackImageUrl = value;
318                         }
319                 }
320
321                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
322                 [BrowsableAttribute (false)]
323                 public virtual FormViewRow BottomPagerRow {
324                         get {
325                                 EnsureChildControls ();
326                                 return bottomPagerRow;
327                         }
328                 }
329         
330                 [WebCategoryAttribute ("Accessibility")]
331                 [DefaultValueAttribute ("")]
332                 [LocalizableAttribute (true)]
333                 public virtual string Caption {
334                         get {
335                                 object ob = ViewState ["Caption"];
336                                 if (ob != null) return (string) ob;
337                                 return string.Empty;
338                         }
339                         set {
340                                 ViewState ["Caption"] = value;
341                                 RequireBinding ();
342                         }
343                 }
344                 
345                 [WebCategoryAttribute ("Accessibility")]
346                 [DefaultValueAttribute (TableCaptionAlign.NotSet)]
347                 public virtual TableCaptionAlign CaptionAlign
348                 {
349                         get {
350                                 object o = ViewState ["CaptionAlign"];
351                                 if(o != null) return (TableCaptionAlign) o;
352                                 return TableCaptionAlign.NotSet;
353                         }
354                         set {
355                                 ViewState ["CaptionAlign"] = value;
356                                 RequireBinding ();
357                         }
358                 }
359
360                 [WebCategoryAttribute ("Layout")]
361                 [DefaultValueAttribute (-1)]
362                 public virtual int CellPadding
363                 {
364                         get {
365                                 if (ControlStyleCreated)
366                                         return ((TableStyle) ControlStyle).CellPadding;
367                                 return -1;
368                         }
369                         set {
370                                 ((TableStyle) ControlStyle).CellPadding = value;
371                         }
372                 }
373
374                 [WebCategoryAttribute ("Layout")]
375                 [DefaultValueAttribute (0)]
376                 public virtual int CellSpacing
377                 {
378                         get {
379                                 if (ControlStyleCreated)
380                                         return ((TableStyle) ControlStyle).CellSpacing;
381                                 return 0;
382                         }
383                         set {
384                                 ((TableStyle) ControlStyle).CellSpacing = value;
385                         }
386                 }
387                 
388                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
389                 [BrowsableAttribute (false)]
390                 public FormViewMode CurrentMode {
391                         get {
392                                 return hasCurrentMode ? currentMode : DefaultMode;
393                         }
394                         private set {
395                                 hasCurrentMode = true;
396                                 currentMode = value;
397                         }
398                 }
399
400                 FormViewMode defaultMode;
401
402                 [DefaultValueAttribute (FormViewMode.ReadOnly)]
403                 [WebCategoryAttribute ("Behavior")]
404                 public virtual FormViewMode DefaultMode {
405                         get {
406                                 return defaultMode;
407                         }
408                         set {
409                                 defaultMode = value;
410                                 RequireBinding ();
411                         }
412                 }
413
414                 string[] dataKeyNames;
415                 [DefaultValueAttribute (null)]
416                 [WebCategoryAttribute ("Data")]
417                 [TypeConverter (typeof(StringArrayConverter))]
418                 [EditorAttribute ("System.Web.UI.Design.WebControls.DataFieldEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
419                 public virtual string[] DataKeyNames
420                 {
421                         get {
422                                 if (dataKeyNames == null)
423                                         return emptyKeys;
424                                 return dataKeyNames;
425                         }
426                         set {
427                                 dataKeyNames = value;
428                                 RequireBinding ();
429                         }
430                 }
431                 
432                 IOrderedDictionary KeyTable {
433                         get {
434                                 if (_keyTable == null) {
435                                         _keyTable = new OrderedDictionary (DataKeyNames.Length);
436                                 }
437                                 return _keyTable;
438                         }
439                 }
440
441                 [BrowsableAttribute (false)]
442                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
443                 public virtual DataKey DataKey {
444                         get {
445                                 if (key == null) {
446                                         key= new DataKey (KeyTable);
447                                 }
448                                 return key;
449                         }
450                 }
451
452                 DataKey OldEditValues {
453                         get {
454                                 if (oldEditValues == null) {
455                                         oldEditValues = new DataKey (new OrderedDictionary ());
456                                 }
457                                 return oldEditValues;
458                         }
459                 }
460
461                 [DefaultValue (null)]
462                 [TemplateContainer (typeof(FormView), BindingDirection.TwoWay)]
463                 [PersistenceMode (PersistenceMode.InnerProperty)]
464                 [Browsable (false)]
465                 public virtual ITemplate EditItemTemplate {
466                         get { return editItemTemplate; }
467                         set { editItemTemplate = value; }
468                 }
469
470                 [WebCategoryAttribute ("Styles")]
471                 [PersistenceMode (PersistenceMode.InnerProperty)]
472                 [NotifyParentProperty (true)]
473                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
474                 [DefaultValueAttribute (null)]
475                 public TableItemStyle EditRowStyle {
476                         get {
477                                 if (editRowStyle == null) {
478                                         editRowStyle = new TableItemStyle ();
479                                         if (IsTrackingViewState)
480                                                 editRowStyle.TrackViewState();
481                                 }
482                                 return editRowStyle;
483                         }
484                 }
485                 
486                 [WebCategoryAttribute ("Styles")]
487                 [PersistenceMode (PersistenceMode.InnerProperty)]
488                 [NotifyParentProperty (true)]
489                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
490                 [DefaultValueAttribute (null)]
491                 public TableItemStyle EmptyDataRowStyle {
492                         get {
493                                 if (emptyDataRowStyle == null) {
494                                         emptyDataRowStyle = new TableItemStyle ();
495                                         if (IsTrackingViewState)
496                                                 emptyDataRowStyle.TrackViewState();
497                                 }
498                                 return emptyDataRowStyle;
499                         }
500                 }
501                 
502                 [DefaultValue (null)]
503                 [TemplateContainer (typeof(FormView), BindingDirection.OneWay)]
504                 [PersistenceMode (PersistenceMode.InnerProperty)]
505                 [Browsable (false)]
506                 public virtual ITemplate EmptyDataTemplate {
507                         get { return emptyDataTemplate; }
508                         set { emptyDataTemplate = value; }
509                 }
510                 
511                 [LocalizableAttribute (true)]
512                 [WebCategoryAttribute ("Appearance")]
513                 [DefaultValueAttribute ("")]
514                 public virtual string EmptyDataText {
515                         get {
516                                 object ob = ViewState ["EmptyDataText"];
517                                 if (ob != null) return (string) ob;
518                                 return string.Empty;
519                         }
520                         set {
521                                 ViewState ["EmptyDataText"] = value;
522                                 RequireBinding ();
523                         }
524                 }
525         
526                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
527                 [BrowsableAttribute (false)]
528                 public virtual FormViewRow FooterRow {
529                         get {
530                                 EnsureChildControls ();
531                                 return footerRow;
532                         }
533                 }
534         
535                 [DefaultValue (null)]
536                 [TemplateContainer (typeof(FormView), BindingDirection.OneWay)]
537                 [PersistenceMode (PersistenceMode.InnerProperty)]
538                 [Browsable (false)]
539                 public virtual ITemplate FooterTemplate {
540                         get { return footerTemplate; }
541                         set { footerTemplate = value; }
542                 }
543
544                 [LocalizableAttribute (true)]
545                 [WebCategoryAttribute ("Appearance")]
546                 [DefaultValueAttribute ("")]
547                 public virtual string FooterText {
548                         get {
549                                 object ob = ViewState ["FooterText"];
550                                 if (ob != null) return (string) ob;
551                                 return string.Empty;
552                         }
553                         set {
554                                 ViewState ["FooterText"] = value;
555                                 RequireBinding ();
556                         }
557                 }
558                 
559                 [WebCategoryAttribute ("Styles")]
560                 [PersistenceMode (PersistenceMode.InnerProperty)]
561                 [NotifyParentProperty (true)]
562                 [DefaultValue (null)]
563                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
564                 public TableItemStyle FooterStyle {
565                         get {
566                                 if (footerStyle == null) {
567                                         footerStyle = new TableItemStyle ();
568                                         if (IsTrackingViewState)
569                                                 footerStyle.TrackViewState();
570                                 }
571                                 return footerStyle;
572                         }
573                 }
574                 
575                 [WebCategoryAttribute ("Appearance")]
576                 [DefaultValueAttribute (GridLines.None)]
577                 public virtual GridLines GridLines {
578                         get {
579                                 if (ControlStyleCreated)
580                                         return ((TableStyle) ControlStyle).GridLines;
581                                 return GridLines.None;
582                         }
583                         set {
584                                 ((TableStyle) ControlStyle).GridLines = value;
585                         }
586                 }
587
588                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
589                 [BrowsableAttribute (false)]
590                 public virtual FormViewRow HeaderRow {
591                         get {
592                                 EnsureChildControls ();
593                                 return headerRow;
594                         }
595                 }
596         
597                 [WebCategoryAttribute ("Styles")]
598                 [PersistenceMode (PersistenceMode.InnerProperty)]
599                 [NotifyParentProperty (true)]
600                 [DefaultValue (null)]
601                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
602                 public TableItemStyle HeaderStyle {
603                         get {
604                                 if (headerStyle == null) {
605                                         headerStyle = new TableItemStyle ();
606                                         if (IsTrackingViewState)
607                                                 headerStyle.TrackViewState();
608                                 }
609                                 return headerStyle;
610                         }
611                 }
612                 
613                 [DefaultValue (null)]
614                 [TemplateContainer (typeof(FormView), BindingDirection.OneWay)]
615                 [PersistenceMode (PersistenceMode.InnerProperty)]
616                 [Browsable (false)]
617                 public virtual ITemplate HeaderTemplate {
618                         get { return headerTemplate; }
619                         set { headerTemplate = value; }
620                 }
621
622                 [LocalizableAttribute (true)]
623                 [WebCategoryAttribute ("Appearance")]
624                 [DefaultValueAttribute ("")]
625                 public virtual string HeaderText {
626                         get {
627                                 object ob = ViewState ["HeaderText"];
628                                 if (ob != null) return (string) ob;
629                                 return string.Empty;
630                         }
631                         set {
632                                 ViewState ["HeaderText"] = value;
633                                 RequireBinding ();
634                         }
635                 }
636                 
637                 [Category ("Layout")]
638                 [DefaultValueAttribute (HorizontalAlign.NotSet)]
639                 public virtual HorizontalAlign HorizontalAlign {
640                         get {
641                                 if (ControlStyleCreated)
642                                         return ((TableStyle) ControlStyle).HorizontalAlign;
643                                 return HorizontalAlign.NotSet;
644                         }
645                         set {
646                                 ((TableStyle) ControlStyle).HorizontalAlign = value;
647                         }
648                 }
649
650                 [DefaultValue (null)]
651                 [TemplateContainer (typeof(FormView), BindingDirection.TwoWay)]
652                 [PersistenceMode (PersistenceMode.InnerProperty)]
653                 [Browsable (false)]
654                 public virtual ITemplate InsertItemTemplate {
655                         get { return insertItemTemplate; }
656                         set { insertItemTemplate = value; }
657                 }
658
659                 [WebCategoryAttribute ("Styles")]
660                 [PersistenceMode (PersistenceMode.InnerProperty)]
661                 [NotifyParentProperty (true)]
662                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
663                 [DefaultValueAttribute (null)]
664                 public TableItemStyle InsertRowStyle {
665                         get {
666                                 if (insertRowStyle == null) {
667                                         insertRowStyle = new TableItemStyle ();
668                                         if (IsTrackingViewState)
669                                                 insertRowStyle.TrackViewState();
670                                 }
671                                 return insertRowStyle;
672                         }
673                 }
674
675                 [DefaultValue (null)]
676                 [TemplateContainer (typeof(FormView), BindingDirection.TwoWay)]
677                 [PersistenceMode (PersistenceMode.InnerProperty)]
678                 [Browsable (false)]
679                 public virtual ITemplate ItemTemplate {
680                         get { return itemTemplate; }
681                         set { itemTemplate = value; }
682                 }
683                 
684                 [BrowsableAttribute (false)]
685                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
686                 public virtual int PageCount {
687                         get {
688                                 return pageCount;
689                         }
690                         private set {
691                                 pageCount = value;
692                         }
693                 }
694
695                 [WebCategoryAttribute ("Paging")]
696                 [BindableAttribute (true, BindingDirection.OneWay)]
697                 [DefaultValueAttribute (0)]
698                 public virtual int PageIndex {
699                         get {
700                                 return pageIndex;
701                         }
702                         set {
703                                 if (value < -1)
704                                         throw new ArgumentOutOfRangeException ("PageIndex must be non-negative");
705                                 if (pageIndex == value || value == -1)
706                                         return;
707                                 pageIndex = value;
708                                 RequireBinding ();
709                         }
710                 }
711         
712                 [WebCategoryAttribute ("Paging")]
713                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Content)]
714                 [NotifyParentPropertyAttribute (true)]
715                 [PersistenceModeAttribute (PersistenceMode.InnerProperty)]
716                 public virtual PagerSettings PagerSettings {
717                         get {
718                                 if (pagerSettings == null) {
719                                         pagerSettings = new PagerSettings (this);
720                                         if (IsTrackingViewState)
721                                                 ((IStateManager)pagerSettings).TrackViewState ();
722                                 }
723                                 return pagerSettings;
724                         }
725                 }
726         
727                 [WebCategoryAttribute ("Styles")]
728                 [PersistenceMode (PersistenceMode.InnerProperty)]
729                 [NotifyParentProperty (true)]
730                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
731                 public TableItemStyle PagerStyle {
732                         get {
733                                 if (pagerStyle == null) {
734                                         pagerStyle = new TableItemStyle ();
735                                         if (IsTrackingViewState)
736                                                 pagerStyle.TrackViewState();
737                                 }
738                                 return pagerStyle;
739                         }
740                 }
741                 
742                 
743                 [DefaultValue (null)]
744                 [TemplateContainerAttribute (typeof (FormView))]
745                 [PersistenceMode (PersistenceMode.InnerProperty)]
746                 [Browsable (false)]
747                 public virtual ITemplate PagerTemplate {
748                         get { return pagerTemplate; }
749                         set { pagerTemplate = value; }
750                 }
751                 
752                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
753                 [BrowsableAttribute (false)]
754                 public virtual FormViewRow Row {
755                         get {
756                                 EnsureChildControls ();
757                                 return itemRow;
758                         }
759                 }
760                 
761                 [WebCategoryAttribute ("Styles")]
762                 [PersistenceMode (PersistenceMode.InnerProperty)]
763                 [NotifyParentProperty (true)]
764                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
765                 [DefaultValue (null)]
766                 public TableItemStyle RowStyle {
767                         get {
768                                 if (rowStyle == null) {
769                                         rowStyle = new TableItemStyle ();
770                                         if (IsTrackingViewState)
771                                                 rowStyle.TrackViewState();
772                                 }
773                                 return rowStyle;
774                         }
775                 }
776
777                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
778                 [BrowsableAttribute (false)]
779                 public object SelectedValue {
780                         get { return DataKey.Value; }
781                 }
782                 
783                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
784                 [BrowsableAttribute (false)]
785                 public virtual FormViewRow TopPagerRow {
786                         get {
787                                 EnsureChildControls ();
788                                 return topPagerRow;
789                         }
790                 }
791         
792                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
793                 [BrowsableAttribute (false)]
794                 public virtual object DataItem {
795                         get {
796                                 return dataItem;
797                         }
798                 }
799                 
800                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
801                 [BrowsableAttribute (false)]
802                 public int DataItemCount {
803                         get { return PageCount; }
804                 }               
805         
806                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
807                 [BrowsableAttribute (false)]
808                 public virtual int DataItemIndex {
809                         get { return PageIndex; }
810                 }
811
812                 int IDataItemContainer.DataItemIndex {
813                         get { return DataItemIndex; }
814                 }
815         
816                 int IDataItemContainer.DisplayIndex {
817                         get { return PageIndex; }
818                 }               
819         
820                 public virtual bool IsBindableType (Type type)
821                 {
822                         return type.IsPrimitive || type == typeof (string) || type == typeof (DateTime) || type == typeof (Guid) || type == typeof (Decimal);
823                 }
824                 
825                 protected override DataSourceSelectArguments CreateDataSourceSelectArguments ()
826                 {
827                         DataSourceSelectArguments arg = new DataSourceSelectArguments ();
828                         DataSourceView view = GetData ();
829                         if (AllowPaging && view.CanPage) {
830                                 arg.StartRowIndex = PageIndex;
831                                 if (view.CanRetrieveTotalRowCount) {
832                                         arg.RetrieveTotalRowCount = true;
833                                         arg.MaximumRows = 1;
834                                 }
835                                 else {
836                                         arg.MaximumRows = -1;
837                                 }
838                         }
839                         return arg;
840                 }
841                 
842                 protected virtual FormViewRow CreateRow (int rowIndex, DataControlRowType rowType, DataControlRowState rowState)
843                 {
844                         if (rowType == DataControlRowType.Pager)
845                                 return new FormViewPagerRow (rowIndex, rowType, rowState);
846                         else
847                                 return new FormViewRow (rowIndex, rowType, rowState);
848                 }
849                 
850                 void RequireBinding ()
851                 {
852                         if (Initialized) {
853                                 RequiresDataBinding = true;
854                         }
855                 }
856                 
857                 protected virtual Table CreateTable ()
858                 {
859                         return new ContainedTable (this);
860                 }
861
862                 protected override void EnsureDataBound ()
863                 {
864                         if (CurrentMode == FormViewMode.Insert) {
865                                 if (RequiresDataBinding) {
866                                         OnDataBinding (EventArgs.Empty);
867                                         RequiresDataBinding = false;
868                                         InternalPerformDataBinding (null);
869                                         MarkAsDataBound ();
870                                         OnDataBound (EventArgs.Empty);
871                                 }
872                         }
873                         else
874                                 base.EnsureDataBound ();
875                 }
876         
877                 protected override Style CreateControlStyle ()
878                 {
879                         TableStyle style = new TableStyle (ViewState);
880                         style.CellSpacing = 0;
881                         return style;
882                 }
883                 
884                 protected override int CreateChildControls (IEnumerable data, bool dataBinding)
885                 {
886                         PagedDataSource dataSource = new PagedDataSource ();
887                         dataSource.DataSource = CurrentMode != FormViewMode.Insert ? data : null;
888                         dataSource.AllowPaging = AllowPaging;
889                         dataSource.PageSize = 1;
890                         dataSource.CurrentPageIndex = PageIndex;
891
892                         if (dataBinding && CurrentMode != FormViewMode.Insert) {
893                                 DataSourceView view = GetData ();
894                                 if (view != null && view.CanPage) {
895                                         dataSource.AllowServerPaging = true;
896                                         if (SelectArguments.RetrieveTotalRowCount)
897                                                 dataSource.VirtualCount = SelectArguments.TotalRowCount;
898                                 }
899                         }
900
901                         bool showPager = AllowPaging && (dataSource.PageCount > 1);
902                         
903                         Controls.Clear ();
904                         table = CreateTable ();
905                         Controls.Add (table);
906                         headerRow = null;
907                         footerRow = null;
908                         topPagerRow = null;
909                         bottomPagerRow = null;
910
911                         // Gets the current data item
912
913                         if (AllowPaging) {
914                                 PageCount = dataSource.DataSourceCount;
915                                 if (PageIndex >= PageCount && PageCount > 0) {
916                                         pageIndex = dataSource.CurrentPageIndex = PageCount - 1;
917                                 }
918                                 if (dataSource.DataSource != null) {
919                                         IEnumerator e = dataSource.GetEnumerator ();
920                                         if (e.MoveNext ())
921                                                 dataItem = e.Current;
922                                 }
923                         }
924                         else {
925                                 int page = 0;
926                                 object lastItem = null;
927                                 if (dataSource.DataSource != null) {
928                                         IEnumerator e = dataSource.GetEnumerator ();
929                                         for (; e.MoveNext (); page++) {
930                                                 lastItem = e.Current;
931                                                 if (page == PageIndex)
932                                                         dataItem = e.Current;
933                                         }
934                                 }
935                                 PageCount = page;
936                                 if (PageIndex >= PageCount && PageCount > 0) {
937                                         pageIndex = PageCount - 1;
938                                         dataItem = lastItem;
939                                 }
940                         }
941
942                         // Main table creation
943                         bool emptyRow = PageCount == 0 && CurrentMode != FormViewMode.Insert;
944
945                         if (!emptyRow) {
946                                 headerRow = CreateRow (-1, DataControlRowType.Header, DataControlRowState.Normal);
947                                 InitializeRow (headerRow);
948                                 table.Rows.Add (headerRow);
949                         }
950                         
951                         if (showPager && PagerSettings.Position == PagerPosition.Top || PagerSettings.Position == PagerPosition.TopAndBottom) {
952                                 topPagerRow = CreateRow (-1, DataControlRowType.Pager, DataControlRowState.Normal);
953                                 InitializePager (topPagerRow, dataSource);
954                                 table.Rows.Add (topPagerRow);
955                         }
956
957                         if (PageCount > 0) {
958                                 DataControlRowState rstate = GetRowState ();
959                                 itemRow = CreateRow (0, DataControlRowType.DataRow, rstate);
960                                 InitializeRow (itemRow);
961                                 table.Rows.Add (itemRow);
962                         } else {
963                                 switch (CurrentMode) {
964                                 case FormViewMode.Edit:
965                                         itemRow = CreateRow (-1, DataControlRowType.EmptyDataRow, DataControlRowState.Edit);
966                                         break;
967                                 case FormViewMode.Insert:
968                                         itemRow = CreateRow (-1, DataControlRowType.DataRow, DataControlRowState.Insert);
969                                         break;
970                                 default:
971                                         itemRow = CreateRow (-1, DataControlRowType.EmptyDataRow, DataControlRowState.Normal);
972                                         break;
973                                 }
974                                 InitializeRow (itemRow);
975                                 table.Rows.Add (itemRow);
976                         }
977
978                         if (!emptyRow) {
979                                 footerRow = CreateRow (-1, DataControlRowType.Footer, DataControlRowState.Normal);
980                                 InitializeRow (footerRow);
981                                 table.Rows.Add (footerRow);
982                         }
983                         
984                         if (showPager && PagerSettings.Position == PagerPosition.Bottom || PagerSettings.Position == PagerPosition.TopAndBottom) {
985                                 bottomPagerRow = CreateRow (0, DataControlRowType.Pager, DataControlRowState.Normal);
986                                 InitializePager (bottomPagerRow, dataSource);
987                                 table.Rows.Add (bottomPagerRow);
988                         }
989
990                         OnItemCreated (EventArgs.Empty);
991                         
992                         if (dataBinding)
993                                 DataBind (false);
994
995                         return PageCount;
996                 }
997                 
998                 DataControlRowState GetRowState ()
999                 {
1000                         DataControlRowState rstate = DataControlRowState.Normal;
1001                         if (CurrentMode == FormViewMode.Edit) rstate |= DataControlRowState.Edit;
1002                         else if (CurrentMode == FormViewMode.Insert) rstate |= DataControlRowState.Insert;
1003                         return rstate;
1004                 }
1005                 
1006                 protected virtual void InitializePager (FormViewRow row, PagedDataSource dataSource)
1007                 {
1008                         TableCell cell = new TableCell ();
1009                         cell.ColumnSpan = 2;
1010
1011                         if (pagerTemplate != null)
1012                                 pagerTemplate.InstantiateIn (cell);
1013                         else
1014                                 cell.Controls.Add (PagerSettings.CreatePagerControl (dataSource.CurrentPageIndex, dataSource.PageCount));
1015                         
1016                         row.Cells.Add (cell);
1017                 }
1018                 
1019                 protected virtual void InitializeRow (FormViewRow row)
1020                 {
1021                         TableCell cell = new TableCell ();
1022                         
1023                         if (row.RowType == DataControlRowType.DataRow)
1024                         {
1025                                 if ((row.RowState & DataControlRowState.Edit) != 0) {
1026                                         if (editItemTemplate != null)
1027                                                 editItemTemplate.InstantiateIn (cell);
1028                                         else
1029                                                 row.Visible = false;
1030                                 } else if ((row.RowState & DataControlRowState.Insert) != 0) {
1031                                         if (insertItemTemplate != null)
1032                                                 insertItemTemplate.InstantiateIn (cell);
1033                                         else
1034                                                 row.Visible = false;
1035                                 }
1036                                 else if (itemTemplate != null)
1037                                         itemTemplate.InstantiateIn (cell);
1038                                 else
1039                                         row.Visible = false;
1040                         }
1041                         else if (row.RowType == DataControlRowType.EmptyDataRow)
1042                         {
1043                                 if (emptyDataTemplate != null)
1044                                         emptyDataTemplate.InstantiateIn (cell);
1045                                 else if (!String.IsNullOrEmpty (EmptyDataText))
1046                                         cell.Text = EmptyDataText;
1047                                 else
1048                                         row.Visible = false;
1049                         }
1050                         else if (row.RowType == DataControlRowType.Footer)
1051                         {
1052                                 if (footerTemplate != null)
1053                                         footerTemplate.InstantiateIn (cell);
1054                                 else if (!String.IsNullOrEmpty (FooterText))
1055                                         cell.Text = FooterText;
1056                                 else
1057                                         row.Visible = false;
1058                         }
1059                         else if (row.RowType == DataControlRowType.Header)
1060                         {
1061                                 if (headerTemplate != null)
1062                                         headerTemplate.InstantiateIn (cell);
1063                                 else if (!String.IsNullOrEmpty (HeaderText))
1064                                         cell.Text = HeaderText;
1065                                 else
1066                                         row.Visible = false;
1067                         }
1068                         cell.ColumnSpan = 2;
1069                         row.Cells.Add (cell);
1070                 }
1071                 
1072                 void FillRowDataKey (object dataItem)
1073                 {
1074                         KeyTable.Clear ();
1075
1076                         if (cachedKeyProperties == null) {
1077                                 PropertyDescriptorCollection props = TypeDescriptor.GetProperties (dataItem);
1078                                 cachedKeyProperties = new PropertyDescriptor [DataKeyNames.Length];
1079                                 for (int n=0; n<DataKeyNames.Length; n++) { 
1080                                         PropertyDescriptor p = props.Find (DataKeyNames [n], true);
1081                                         if (p == null)
1082                                                 throw new InvalidOperationException ("Property '" + DataKeyNames[n] + "' not found in object of type " + dataItem.GetType());
1083                                         cachedKeyProperties [n] = p;
1084                                 }
1085                         }
1086                         foreach (PropertyDescriptor p in cachedKeyProperties)
1087                                 KeyTable [p.Name] = p.GetValue (dataItem);
1088                 }
1089                 
1090                 IOrderedDictionary GetRowValues (bool includePrimaryKey)
1091                 {
1092                         OrderedDictionary dic = new OrderedDictionary ();
1093                         ExtractRowValues (dic, includePrimaryKey);
1094                         return dic;
1095                 }
1096                 
1097                 protected virtual void ExtractRowValues (IOrderedDictionary fieldValues, bool includeKeys)
1098                 {
1099                         if (Row == null)
1100                                 return;
1101
1102                         DataControlRowState rowState = Row.RowState;
1103                         IBindableTemplate bt;
1104                         
1105                         if ((rowState & DataControlRowState.Insert) != 0)
1106                                 bt = insertItemTemplate as IBindableTemplate; 
1107                         else if ((rowState & DataControlRowState.Edit) != 0)
1108                                 bt = editItemTemplate as IBindableTemplate;
1109                         else
1110                                 return;
1111                         
1112                         if (bt != null) {
1113                                 IOrderedDictionary values = bt.ExtractValues (Row.Cells [0]);
1114                                 if (values != null)
1115                                 foreach (DictionaryEntry e in values) {
1116                                         if (includeKeys || Array.IndexOf (DataKeyNames, e.Key) == -1)
1117                                                 fieldValues [e.Key] = e.Value;
1118                                 }
1119                         }
1120                 }
1121                 
1122                 protected override HtmlTextWriterTag TagKey {
1123                         get {
1124                                 return HtmlTextWriterTag.Table;
1125                         }
1126                 }
1127                 
1128                 public sealed override void DataBind ()
1129                 {
1130                         cachedKeyProperties = null;
1131                         base.DataBind ();
1132                         
1133                         if (pageCount > 0) {
1134                                 if (CurrentMode == FormViewMode.Edit)
1135                                         oldEditValues = new DataKey (GetRowValues (true));
1136                                 FillRowDataKey (dataItem);
1137                                 key = new DataKey (KeyTable);
1138                         }
1139                 }
1140                 
1141                 protected internal override void PerformDataBinding (IEnumerable data)
1142                 {
1143                         base.PerformDataBinding (data);
1144                 }
1145
1146                 protected internal virtual void PrepareControlHierarchy ()
1147                 {
1148                         if (table == null)
1149                                 return;
1150
1151                         table.Caption = Caption;
1152                         table.CaptionAlign = CaptionAlign;
1153
1154                         foreach (FormViewRow row in table.Rows) {
1155                                 switch (row.RowType) {
1156                                 case DataControlRowType.Header:
1157                                         if (headerStyle != null && !headerStyle.IsEmpty)
1158                                                 row.ControlStyle.CopyFrom (headerStyle);
1159                                         break;
1160                                 case DataControlRowType.Footer:
1161                                         if (footerStyle != null && !footerStyle.IsEmpty)
1162                                                 row.ControlStyle.CopyFrom (footerStyle);
1163                                         break;
1164                                 case DataControlRowType.Pager:
1165                                         if (pagerStyle != null && !pagerStyle.IsEmpty)
1166                                                 row.ControlStyle.CopyFrom (pagerStyle);
1167                                         break;
1168                                 case DataControlRowType.EmptyDataRow:
1169                                         if (emptyDataRowStyle != null && !emptyDataRowStyle.IsEmpty)
1170                                                 row.ControlStyle.CopyFrom (emptyDataRowStyle);
1171                                         break;
1172                                 case DataControlRowType.DataRow:
1173                                         if (rowStyle != null && !rowStyle.IsEmpty)
1174                                                 row.ControlStyle.CopyFrom (rowStyle);
1175                                         if ((row.RowState & (DataControlRowState.Edit | DataControlRowState.Insert)) != 0 && editRowStyle != null && !editRowStyle.IsEmpty)
1176                                                 row.ControlStyle.CopyFrom (editRowStyle);
1177                                         if ((row.RowState & DataControlRowState.Insert) != 0 && insertRowStyle != null && !insertRowStyle.IsEmpty)
1178                                                 row.ControlStyle.CopyFrom (insertRowStyle);
1179                                         break;
1180                                 default:
1181                                         break;
1182                                 }
1183                         }
1184                 }
1185                 
1186                 protected internal override void OnInit (EventArgs e)
1187                 {
1188                         Page.RegisterRequiresControlState (this);
1189                         base.OnInit (e);
1190                 }
1191                 
1192                 protected override bool OnBubbleEvent (object source, EventArgs e)
1193                 {
1194                         FormViewCommandEventArgs args = e as FormViewCommandEventArgs;
1195                         if (args != null) {
1196                                 bool causesValidation = false;
1197                                 IButtonControl button = args.CommandSource as IButtonControl;
1198                                 if (button != null && button.CausesValidation) {
1199                                         Page.Validate (button.ValidationGroup);
1200                                         causesValidation = true;
1201                                 }
1202                                 ProcessCommand (args, causesValidation);
1203                                 return true;
1204                         }
1205                         return base.OnBubbleEvent (source, e);
1206                 }
1207
1208                 void ProcessCommand (FormViewCommandEventArgs args, bool causesValidation)
1209                 {
1210                         OnItemCommand (args);
1211                         ProcessEvent (args.CommandName, args.CommandArgument as string, causesValidation);
1212                 }
1213                 
1214                 void IPostBackEventHandler.RaisePostBackEvent (string eventArgument)
1215                 {
1216                         RaisePostBackEvent (eventArgument);
1217                 }
1218
1219                 protected virtual void RaisePostBackEvent (string eventArgument)
1220                 {
1221                         int i = eventArgument.IndexOf ('$');
1222                         CommandEventArgs arg;
1223                         if (i != -1)
1224                                 arg = new CommandEventArgs (eventArgument.Substring (0, i), eventArgument.Substring (i + 1));
1225                         else
1226                                 arg = new CommandEventArgs (eventArgument, null);
1227                         ProcessCommand (new FormViewCommandEventArgs (this, arg), false);
1228                 }
1229
1230                 void ProcessEvent (string eventName, string param, bool causesValidation)
1231                 {
1232                         switch (eventName)
1233                         {
1234                         case DataControlCommands.PageCommandName:
1235                                 int newIndex = -1;
1236                                 switch (param) {
1237                                 case DataControlCommands.FirstPageCommandArgument:
1238                                         newIndex = 0;
1239                                         break;
1240                                 case DataControlCommands.LastPageCommandArgument:
1241                                         newIndex = PageCount - 1;
1242                                         break;
1243                                 case DataControlCommands.NextPageCommandArgument:
1244                                         newIndex = PageIndex + 1;
1245                                         break;
1246                                 case DataControlCommands.PreviousPageCommandArgument:
1247                                         newIndex = PageIndex - 1;
1248                                         break;
1249                                 default:
1250                                         int paramIndex = 0;
1251                                         int.TryParse (param, out paramIndex);
1252                                         newIndex = paramIndex - 1;
1253                                         break;
1254                                 }
1255                                 ShowPage (newIndex);
1256                                 break;
1257                                         
1258                         case DataControlCommands.FirstPageCommandArgument:
1259                                 ShowPage (0);
1260                                 break;
1261
1262                         case DataControlCommands.LastPageCommandArgument:
1263                                 ShowPage (PageCount - 1);
1264                                 break;
1265                                         
1266                         case DataControlCommands.NextPageCommandArgument:
1267                                 if (PageIndex < PageCount - 1)
1268                                         ShowPage (PageIndex + 1);
1269                                 break;
1270
1271                         case DataControlCommands.PreviousPageCommandArgument:
1272                                 if (PageIndex > 0)
1273                                         ShowPage (PageIndex - 1);
1274                                 break;
1275                                         
1276                         case DataControlCommands.EditCommandName:
1277                                 ProcessChangeMode (FormViewMode.Edit, false);
1278                                 break;
1279                                         
1280                         case DataControlCommands.NewCommandName:
1281                                 ProcessChangeMode (FormViewMode.Insert, false);
1282                                 break;
1283                                         
1284                         case DataControlCommands.UpdateCommandName:
1285                                 UpdateItem (param, causesValidation);
1286                                 break;
1287                                         
1288                         case DataControlCommands.CancelCommandName:
1289                                 CancelEdit ();
1290                                 break;
1291                                         
1292                         case DataControlCommands.DeleteCommandName:
1293                                 DeleteItem ();
1294                                 break;
1295                                         
1296                         case DataControlCommands.InsertCommandName:
1297                                 InsertItem (causesValidation);
1298                                 break;
1299                         }
1300                 }
1301                 
1302                 void ShowPage (int index)
1303                 {
1304                         FormViewPageEventArgs args = new FormViewPageEventArgs (index);
1305                         OnPageIndexChanging (args);
1306
1307                         if (args.Cancel || !IsBoundUsingDataSourceID)
1308                                 return;
1309
1310                         int newIndex = args.NewPageIndex;
1311                         if (newIndex < 0 || newIndex >= PageCount)
1312                                 return;
1313                         EndRowEdit (false, false);
1314                         PageIndex = newIndex;
1315                         OnPageIndexChanged (EventArgs.Empty);
1316                 }
1317                 
1318                 public void ChangeMode (FormViewMode newMode)
1319                 {
1320                         if (CurrentMode == newMode)
1321                                 return;
1322                         CurrentMode = newMode;
1323                         RequireBinding ();
1324                 }
1325
1326                 void ProcessChangeMode (FormViewMode newMode, bool cancelingEdit)
1327                 {
1328                         FormViewModeEventArgs args = new FormViewModeEventArgs (newMode, cancelingEdit);
1329                         OnModeChanging (args);
1330
1331                         if (args.Cancel || !IsBoundUsingDataSourceID)
1332                                 return;
1333
1334                         ChangeMode (args.NewMode);
1335
1336                         OnModeChanged (EventArgs.Empty);
1337                 }
1338                 
1339                 void CancelEdit ()
1340                 {
1341                         EndRowEdit (true, true);
1342                 }
1343
1344                 public virtual void UpdateItem (bool causesValidation)
1345                 {
1346                         UpdateItem (null, causesValidation);
1347                 }
1348                 
1349                 void UpdateItem (string param, bool causesValidation)
1350                 {
1351                         if (causesValidation && Page != null && !Page.IsValid)
1352                                 return;
1353                         
1354                         if (currentMode != FormViewMode.Edit) throw new HttpException ("Must be in Edit mode");
1355
1356                         currentEditOldValues = OldEditValues.Values;
1357                         currentEditRowKeys = DataKey.Values;
1358                         currentEditNewValues = GetRowValues (false);
1359                         
1360                         FormViewUpdateEventArgs args = new FormViewUpdateEventArgs (param, currentEditRowKeys, currentEditOldValues, currentEditNewValues);
1361                         OnItemUpdating (args);
1362
1363                         if (args.Cancel || !IsBoundUsingDataSourceID)
1364                                 return;
1365                         
1366                         DataSourceView view = GetData ();
1367                         if (view == null)
1368                                 throw new HttpException ("The DataSourceView associated to data bound control was null");
1369                         view.Update (currentEditRowKeys, currentEditNewValues, currentEditOldValues, new DataSourceViewOperationCallback (UpdateCallback));
1370                 }
1371
1372                 bool UpdateCallback (int recordsAffected, Exception exception)
1373                 {
1374                         FormViewUpdatedEventArgs dargs = new FormViewUpdatedEventArgs (recordsAffected, exception, currentEditRowKeys, currentEditOldValues, currentEditNewValues);
1375                         OnItemUpdated (dargs);
1376
1377                         if (!dargs.KeepInEditMode)                              
1378                                 EndRowEdit (true, false);
1379
1380                         return dargs.ExceptionHandled;
1381                 }
1382
1383                 public virtual void InsertItem (bool causesValidation)
1384                 {
1385                         InsertItem (null, causesValidation);
1386                 }
1387                 
1388                 void InsertItem (string param, bool causesValidation)
1389                 {
1390                         if (causesValidation && Page != null && !Page.IsValid)
1391                                 return;
1392                         
1393                         if (currentMode != FormViewMode.Insert) throw new HttpException ("Must be in Insert mode");
1394                         
1395                         currentEditNewValues = GetRowValues (true);
1396                         FormViewInsertEventArgs args = new FormViewInsertEventArgs (param, currentEditNewValues);
1397                         OnItemInserting (args);
1398
1399                         if (args.Cancel || !IsBoundUsingDataSourceID)
1400                                 return;
1401
1402                         DataSourceView view = GetData ();
1403                         if (view == null)
1404                                 throw new HttpException ("The DataSourceView associated to data bound control was null");
1405                         view.Insert (currentEditNewValues, new DataSourceViewOperationCallback (InsertCallback));
1406                 }
1407                 
1408                 bool InsertCallback (int recordsAffected, Exception exception)
1409                 {
1410                         FormViewInsertedEventArgs dargs = new FormViewInsertedEventArgs (recordsAffected, exception, currentEditNewValues);
1411                         OnItemInserted (dargs);
1412
1413                         if (!dargs.KeepInInsertMode)                            
1414                                 EndRowEdit (true, false);
1415
1416                         return dargs.ExceptionHandled;
1417                 }
1418
1419                 public virtual void DeleteItem ()
1420                 {
1421                         currentEditRowKeys = DataKey.Values;
1422                         currentEditNewValues = GetRowValues (true);
1423                         
1424                         FormViewDeleteEventArgs args = new FormViewDeleteEventArgs (PageIndex, currentEditRowKeys, currentEditNewValues);
1425                         OnItemDeleting (args);
1426
1427                         if (args.Cancel || !IsBoundUsingDataSourceID)
1428                                 return;
1429
1430                         if (PageIndex > 0 && PageIndex == PageCount - 1)
1431                                 PageIndex--;
1432                                 
1433                         RequireBinding ();
1434                                 
1435                         DataSourceView view = GetData ();
1436                         if (view != null)
1437                                 view.Delete (currentEditRowKeys, currentEditNewValues, new DataSourceViewOperationCallback (DeleteCallback));
1438                         else {
1439                                 FormViewDeletedEventArgs dargs = new FormViewDeletedEventArgs (0, null, currentEditRowKeys, currentEditNewValues);
1440                                 OnItemDeleted (dargs);
1441                         }
1442                 }       
1443
1444                 bool DeleteCallback (int recordsAffected, Exception exception)
1445                 {
1446                         FormViewDeletedEventArgs dargs = new FormViewDeletedEventArgs (recordsAffected, exception, currentEditRowKeys, currentEditNewValues);
1447                         OnItemDeleted (dargs);
1448                         return dargs.ExceptionHandled;
1449                 }
1450                 
1451                 void EndRowEdit (bool switchToDefaultMode, bool cancelingEdit) 
1452                 {
1453                         if (switchToDefaultMode)
1454                                 ProcessChangeMode (DefaultMode, cancelingEdit);
1455                         oldEditValues = new DataKey (new OrderedDictionary ());
1456                         currentEditRowKeys = null;
1457                         currentEditOldValues = null;
1458                         currentEditNewValues = null;
1459                         RequireBinding ();
1460                 }
1461
1462                 protected internal override void LoadControlState (object ob)
1463                 {
1464                         if (ob == null) return;
1465                         object[] state = (object[]) ob;
1466                         base.LoadControlState (state[0]);
1467                         pageIndex = (int) state[1];
1468                         pageCount = (int) state[2];
1469                         CurrentMode = (FormViewMode) state[3];
1470                         defaultMode = (FormViewMode) state[4];
1471                         dataKeyNames = (string[]) state[5];
1472                         if (state [6] != null)
1473                                 ((IStateManager) DataKey).LoadViewState (state [6]);
1474                         if (state [7] != null)
1475                                 ((IStateManager) OldEditValues).LoadViewState (state [7]);
1476                 }
1477                 
1478                 protected internal override object SaveControlState ()
1479                 {
1480                         object bstate = base.SaveControlState ();
1481                         return new object [] {
1482                                 bstate, 
1483                                 pageIndex, 
1484                                 pageCount, 
1485                                 CurrentMode, 
1486                                 defaultMode, 
1487                                 dataKeyNames,
1488                                 (key == null ? null : ((IStateManager)key).SaveViewState()),
1489                                 (oldEditValues == null ? null : ((IStateManager) oldEditValues).SaveViewState ())
1490                         };
1491                 }
1492                 
1493                 protected override void TrackViewState()
1494                 {
1495                         base.TrackViewState();
1496                         if (pagerSettings != null) ((IStateManager)pagerSettings).TrackViewState();
1497                         if (footerStyle != null) ((IStateManager)footerStyle).TrackViewState();
1498                         if (headerStyle != null) ((IStateManager)headerStyle).TrackViewState();
1499                         if (pagerStyle != null) ((IStateManager)pagerStyle).TrackViewState();
1500                         if (rowStyle != null) ((IStateManager)rowStyle).TrackViewState();
1501                         if (editRowStyle != null) ((IStateManager)editRowStyle).TrackViewState();
1502                         if (insertRowStyle != null) ((IStateManager)insertRowStyle).TrackViewState();
1503                         if (emptyDataRowStyle != null) ((IStateManager)emptyDataRowStyle).TrackViewState();
1504                 }
1505
1506                 protected override object SaveViewState()
1507                 {
1508                         object[] states = new object [10];
1509                         states[0] = base.SaveViewState();
1510                         states[1] = (pagerSettings == null ? null : ((IStateManager)pagerSettings).SaveViewState());
1511                         states[2] = (footerStyle == null ? null : ((IStateManager)footerStyle).SaveViewState());
1512                         states[3] = (headerStyle == null ? null : ((IStateManager)headerStyle).SaveViewState());
1513                         states[4] = (pagerStyle == null ? null : ((IStateManager)pagerStyle).SaveViewState());
1514                         states[5] = (rowStyle == null ? null : ((IStateManager)rowStyle).SaveViewState());
1515                         states[6] = (insertRowStyle == null ? null : ((IStateManager)insertRowStyle).SaveViewState());
1516                         states[7] = (editRowStyle == null ? null : ((IStateManager)editRowStyle).SaveViewState());
1517                         states[8] = (emptyDataRowStyle == null ? null : ((IStateManager)emptyDataRowStyle).SaveViewState());
1518                         
1519                         for (int i = states.Length - 1; i >= 0; i--) {
1520                                 if (states [i] != null)
1521                                         return states;
1522                         }
1523
1524                         return null;
1525                 }
1526
1527                 protected override void LoadViewState (object savedState)
1528                 {
1529                         if (savedState == null) {
1530                                 base.LoadViewState (null);
1531                                 return;
1532                         }
1533
1534                         object [] states = (object []) savedState;
1535                         
1536                         base.LoadViewState (states[0]);
1537                         
1538                         if (states[1] != null) ((IStateManager)PagerSettings).LoadViewState (states[1]);
1539                         if (states[2] != null) ((IStateManager)FooterStyle).LoadViewState (states[2]);
1540                         if (states[3] != null) ((IStateManager)HeaderStyle).LoadViewState (states[3]);
1541                         if (states[4] != null) ((IStateManager)PagerStyle).LoadViewState (states[4]);
1542                         if (states[5] != null) ((IStateManager)RowStyle).LoadViewState (states[5]);
1543                         if (states[6] != null) ((IStateManager)InsertRowStyle).LoadViewState (states[6]);
1544                         if (states[7] != null) ((IStateManager)EditRowStyle).LoadViewState (states[7]);
1545                         if (states[8] != null) ((IStateManager)EmptyDataRowStyle).LoadViewState (states[8]);
1546                 }
1547                 
1548                 protected internal override void Render (HtmlTextWriter writer)
1549                 {
1550                         PrepareControlHierarchy ();
1551                         
1552                         if (table == null)
1553                                 return;
1554
1555                         table.Render (writer);
1556                 }
1557
1558                 PostBackOptions IPostBackContainer.GetPostBackOptions (IButtonControl control)
1559                 {
1560                         if (control == null)
1561                                 throw new ArgumentNullException ("control");
1562
1563                         if (control.CausesValidation)
1564                                 throw new InvalidOperationException ("A button that causes validation in FormView '" + ID + "' is attempting to use the container GridView as the post back target.  The button should either turn off validation or use itself as the post back container.");
1565
1566                         PostBackOptions options = new PostBackOptions (this);
1567                         options.Argument = control.CommandName + "$" + control.CommandArgument;
1568                         options.RequiresJavaScriptProtocol = true;
1569
1570                         return options;
1571                 }
1572
1573         }
1574 }
1575
1576 #endif