New tests.
[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                         PagerSettings pagerSettings = PagerSettings;
902                         bool showPager = AllowPaging && pagerSettings.Visible && (dataSource.PageCount > 1);
903                         
904                         Controls.Clear ();
905                         table = CreateTable ();
906                         Controls.Add (table);
907                         headerRow = null;
908                         footerRow = null;
909                         topPagerRow = null;
910                         bottomPagerRow = null;
911
912                         // Gets the current data item
913
914                         if (AllowPaging) {
915                                 PageCount = dataSource.DataSourceCount;
916                                 if (PageIndex >= PageCount && PageCount > 0) {
917                                         pageIndex = dataSource.CurrentPageIndex = PageCount - 1;
918                                 }
919                                 if (dataSource.DataSource != null) {
920                                         IEnumerator e = dataSource.GetEnumerator ();
921                                         if (e.MoveNext ())
922                                                 dataItem = e.Current;
923                                 }
924                         }
925                         else {
926                                 int page = 0;
927                                 object lastItem = null;
928                                 if (dataSource.DataSource != null) {
929                                         IEnumerator e = dataSource.GetEnumerator ();
930                                         for (; e.MoveNext (); page++) {
931                                                 lastItem = e.Current;
932                                                 if (page == PageIndex)
933                                                         dataItem = e.Current;
934                                         }
935                                 }
936                                 PageCount = page;
937                                 if (PageIndex >= PageCount && PageCount > 0) {
938                                         pageIndex = PageCount - 1;
939                                         dataItem = lastItem;
940                                 }
941                         }
942
943                         // Main table creation
944                         bool emptyRow = PageCount == 0 && CurrentMode != FormViewMode.Insert;
945
946                         if (!emptyRow) {
947                                 headerRow = CreateRow (-1, DataControlRowType.Header, DataControlRowState.Normal);
948                                 InitializeRow (headerRow);
949                                 table.Rows.Add (headerRow);
950                         }
951
952                         if (showPager && pagerSettings.Position == PagerPosition.Top || pagerSettings.Position == PagerPosition.TopAndBottom) {
953                                 topPagerRow = CreateRow (-1, DataControlRowType.Pager, DataControlRowState.Normal);
954                                 InitializePager (topPagerRow, dataSource);
955                                 table.Rows.Add (topPagerRow);
956                         }
957
958                         if (PageCount > 0) {
959                                 DataControlRowState rstate = GetRowState ();
960                                 itemRow = CreateRow (0, DataControlRowType.DataRow, rstate);
961                                 InitializeRow (itemRow);
962                                 table.Rows.Add (itemRow);
963                         } else {
964                                 switch (CurrentMode) {
965                                 case FormViewMode.Edit:
966                                         itemRow = CreateRow (-1, DataControlRowType.EmptyDataRow, DataControlRowState.Edit);
967                                         break;
968                                 case FormViewMode.Insert:
969                                         itemRow = CreateRow (-1, DataControlRowType.DataRow, DataControlRowState.Insert);
970                                         break;
971                                 default:
972                                         itemRow = CreateRow (-1, DataControlRowType.EmptyDataRow, DataControlRowState.Normal);
973                                         break;
974                                 }
975                                 InitializeRow (itemRow);
976                                 table.Rows.Add (itemRow);
977                         }
978
979                         if (!emptyRow) {
980                                 footerRow = CreateRow (-1, DataControlRowType.Footer, DataControlRowState.Normal);
981                                 InitializeRow (footerRow);
982                                 table.Rows.Add (footerRow);
983                         }
984                         
985                         if (showPager && pagerSettings.Position == PagerPosition.Bottom || pagerSettings.Position == PagerPosition.TopAndBottom) {
986                                 bottomPagerRow = CreateRow (0, DataControlRowType.Pager, DataControlRowState.Normal);
987                                 InitializePager (bottomPagerRow, dataSource);
988                                 table.Rows.Add (bottomPagerRow);
989                         }
990
991                         OnItemCreated (EventArgs.Empty);
992                         
993                         if (dataBinding)
994                                 DataBind (false);
995
996                         return PageCount;
997                 }
998                 
999                 DataControlRowState GetRowState ()
1000                 {
1001                         DataControlRowState rstate = DataControlRowState.Normal;
1002                         if (CurrentMode == FormViewMode.Edit) rstate |= DataControlRowState.Edit;
1003                         else if (CurrentMode == FormViewMode.Insert) rstate |= DataControlRowState.Insert;
1004                         return rstate;
1005                 }
1006                 
1007                 protected virtual void InitializePager (FormViewRow row, PagedDataSource dataSource)
1008                 {
1009                         TableCell cell = new TableCell ();
1010                         cell.ColumnSpan = 2;
1011
1012                         if (pagerTemplate != null)
1013                                 pagerTemplate.InstantiateIn (cell);
1014                         else
1015                                 cell.Controls.Add (PagerSettings.CreatePagerControl (dataSource.CurrentPageIndex, dataSource.PageCount));
1016                         
1017                         row.Cells.Add (cell);
1018                 }
1019                 
1020                 protected virtual void InitializeRow (FormViewRow row)
1021                 {
1022                         TableCell cell = new TableCell ();
1023                         
1024                         if (row.RowType == DataControlRowType.DataRow)
1025                         {
1026                                 if ((row.RowState & DataControlRowState.Edit) != 0) {
1027                                         if (editItemTemplate != null)
1028                                                 editItemTemplate.InstantiateIn (cell);
1029                                         else
1030                                                 row.Visible = false;
1031                                 } else if ((row.RowState & DataControlRowState.Insert) != 0) {
1032                                         if (insertItemTemplate != null)
1033                                                 insertItemTemplate.InstantiateIn (cell);
1034                                         else
1035                                                 row.Visible = false;
1036                                 }
1037                                 else if (itemTemplate != null)
1038                                         itemTemplate.InstantiateIn (cell);
1039                                 else
1040                                         row.Visible = false;
1041                         }
1042                         else if (row.RowType == DataControlRowType.EmptyDataRow)
1043                         {
1044                                 if (emptyDataTemplate != null)
1045                                         emptyDataTemplate.InstantiateIn (cell);
1046                                 else if (!String.IsNullOrEmpty (EmptyDataText))
1047                                         cell.Text = EmptyDataText;
1048                                 else
1049                                         row.Visible = false;
1050                         }
1051                         else if (row.RowType == DataControlRowType.Footer)
1052                         {
1053                                 if (footerTemplate != null)
1054                                         footerTemplate.InstantiateIn (cell);
1055                                 else if (!String.IsNullOrEmpty (FooterText))
1056                                         cell.Text = FooterText;
1057                                 else
1058                                         row.Visible = false;
1059                         }
1060                         else if (row.RowType == DataControlRowType.Header)
1061                         {
1062                                 if (headerTemplate != null)
1063                                         headerTemplate.InstantiateIn (cell);
1064                                 else if (!String.IsNullOrEmpty (HeaderText))
1065                                         cell.Text = HeaderText;
1066                                 else
1067                                         row.Visible = false;
1068                         }
1069                         cell.ColumnSpan = 2;
1070                         row.Cells.Add (cell);
1071                 }
1072                 
1073                 void FillRowDataKey (object dataItem)
1074                 {
1075                         KeyTable.Clear ();
1076
1077                         if (cachedKeyProperties == null) {
1078                                 PropertyDescriptorCollection props = TypeDescriptor.GetProperties (dataItem);
1079                                 cachedKeyProperties = new PropertyDescriptor [DataKeyNames.Length];
1080                                 for (int n=0; n<DataKeyNames.Length; n++) { 
1081                                         PropertyDescriptor p = props.Find (DataKeyNames [n], true);
1082                                         if (p == null)
1083                                                 throw new InvalidOperationException ("Property '" + DataKeyNames[n] + "' not found in object of type " + dataItem.GetType());
1084                                         cachedKeyProperties [n] = p;
1085                                 }
1086                         }
1087                         foreach (PropertyDescriptor p in cachedKeyProperties)
1088                                 KeyTable [p.Name] = p.GetValue (dataItem);
1089                 }
1090                 
1091                 IOrderedDictionary GetRowValues (bool includePrimaryKey)
1092                 {
1093                         OrderedDictionary dic = new OrderedDictionary ();
1094                         ExtractRowValues (dic, includePrimaryKey);
1095                         return dic;
1096                 }
1097                 
1098                 protected virtual void ExtractRowValues (IOrderedDictionary fieldValues, bool includeKeys)
1099                 {
1100                         if (Row == null)
1101                                 return;
1102
1103                         DataControlRowState rowState = Row.RowState;
1104                         IBindableTemplate bt;
1105                         
1106                         if ((rowState & DataControlRowState.Insert) != 0)
1107                                 bt = insertItemTemplate as IBindableTemplate; 
1108                         else if ((rowState & DataControlRowState.Edit) != 0)
1109                                 bt = editItemTemplate as IBindableTemplate;
1110                         else
1111                                 return;
1112                         
1113                         if (bt != null) {
1114                                 IOrderedDictionary values = bt.ExtractValues (Row.Cells [0]);
1115                                 if (values != null)
1116                                 foreach (DictionaryEntry e in values) {
1117                                         if (includeKeys || Array.IndexOf (DataKeyNames, e.Key) == -1)
1118                                                 fieldValues [e.Key] = e.Value;
1119                                 }
1120                         }
1121                 }
1122                 
1123                 protected override HtmlTextWriterTag TagKey {
1124                         get {
1125                                 return HtmlTextWriterTag.Table;
1126                         }
1127                 }
1128                 
1129                 public sealed override void DataBind ()
1130                 {
1131                         cachedKeyProperties = null;
1132                         base.DataBind ();
1133                         
1134                         if (pageCount > 0) {
1135                                 if (CurrentMode == FormViewMode.Edit)
1136                                         oldEditValues = new DataKey (GetRowValues (true));
1137                                 FillRowDataKey (dataItem);
1138                                 key = new DataKey (KeyTable);
1139                         }
1140                 }
1141                 
1142                 protected internal override void PerformDataBinding (IEnumerable data)
1143                 {
1144                         base.PerformDataBinding (data);
1145                 }
1146
1147                 protected internal virtual void PrepareControlHierarchy ()
1148                 {
1149                         if (table == null)
1150                                 return;
1151
1152                         table.Caption = Caption;
1153                         table.CaptionAlign = CaptionAlign;
1154
1155                         foreach (FormViewRow row in table.Rows) {
1156                                 switch (row.RowType) {
1157                                 case DataControlRowType.Header:
1158                                         if (headerStyle != null && !headerStyle.IsEmpty)
1159                                                 row.ControlStyle.CopyFrom (headerStyle);
1160                                         break;
1161                                 case DataControlRowType.Footer:
1162                                         if (footerStyle != null && !footerStyle.IsEmpty)
1163                                                 row.ControlStyle.CopyFrom (footerStyle);
1164                                         break;
1165                                 case DataControlRowType.Pager:
1166                                         if (pagerStyle != null && !pagerStyle.IsEmpty)
1167                                                 row.ControlStyle.CopyFrom (pagerStyle);
1168                                         break;
1169                                 case DataControlRowType.EmptyDataRow:
1170                                         if (emptyDataRowStyle != null && !emptyDataRowStyle.IsEmpty)
1171                                                 row.ControlStyle.CopyFrom (emptyDataRowStyle);
1172                                         break;
1173                                 case DataControlRowType.DataRow:
1174                                         if (rowStyle != null && !rowStyle.IsEmpty)
1175                                                 row.ControlStyle.CopyFrom (rowStyle);
1176                                         if ((row.RowState & (DataControlRowState.Edit | DataControlRowState.Insert)) != 0 && editRowStyle != null && !editRowStyle.IsEmpty)
1177                                                 row.ControlStyle.CopyFrom (editRowStyle);
1178                                         if ((row.RowState & DataControlRowState.Insert) != 0 && insertRowStyle != null && !insertRowStyle.IsEmpty)
1179                                                 row.ControlStyle.CopyFrom (insertRowStyle);
1180                                         break;
1181                                 default:
1182                                         break;
1183                                 }
1184                         }
1185                 }
1186                 
1187                 protected internal override void OnInit (EventArgs e)
1188                 {
1189                         Page.RegisterRequiresControlState (this);
1190                         base.OnInit (e);
1191                 }
1192                 
1193                 protected override bool OnBubbleEvent (object source, EventArgs e)
1194                 {
1195                         FormViewCommandEventArgs args = e as FormViewCommandEventArgs;
1196                         if (args != null) {
1197                                 bool causesValidation = false;
1198                                 IButtonControl button = args.CommandSource as IButtonControl;
1199                                 if (button != null && button.CausesValidation) {
1200                                         Page.Validate (button.ValidationGroup);
1201                                         causesValidation = true;
1202                                 }
1203                                 ProcessCommand (args, causesValidation);
1204                                 return true;
1205                         }
1206                         return base.OnBubbleEvent (source, e);
1207                 }
1208
1209                 void ProcessCommand (FormViewCommandEventArgs args, bool causesValidation)
1210                 {
1211                         OnItemCommand (args);
1212                         ProcessEvent (args.CommandName, args.CommandArgument as string, causesValidation);
1213                 }
1214                 
1215                 void IPostBackEventHandler.RaisePostBackEvent (string eventArgument)
1216                 {
1217                         RaisePostBackEvent (eventArgument);
1218                 }
1219
1220                 protected virtual void RaisePostBackEvent (string eventArgument)
1221                 {
1222                         int i = eventArgument.IndexOf ('$');
1223                         CommandEventArgs arg;
1224                         if (i != -1)
1225                                 arg = new CommandEventArgs (eventArgument.Substring (0, i), eventArgument.Substring (i + 1));
1226                         else
1227                                 arg = new CommandEventArgs (eventArgument, null);
1228                         ProcessCommand (new FormViewCommandEventArgs (this, arg), false);
1229                 }
1230
1231                 void ProcessEvent (string eventName, string param, bool causesValidation)
1232                 {
1233                         switch (eventName)
1234                         {
1235                         case DataControlCommands.PageCommandName:
1236                                 int newIndex = -1;
1237                                 switch (param) {
1238                                 case DataControlCommands.FirstPageCommandArgument:
1239                                         newIndex = 0;
1240                                         break;
1241                                 case DataControlCommands.LastPageCommandArgument:
1242                                         newIndex = PageCount - 1;
1243                                         break;
1244                                 case DataControlCommands.NextPageCommandArgument:
1245                                         newIndex = PageIndex + 1;
1246                                         break;
1247                                 case DataControlCommands.PreviousPageCommandArgument:
1248                                         newIndex = PageIndex - 1;
1249                                         break;
1250                                 default:
1251                                         int paramIndex = 0;
1252                                         int.TryParse (param, out paramIndex);
1253                                         newIndex = paramIndex - 1;
1254                                         break;
1255                                 }
1256                                 ShowPage (newIndex);
1257                                 break;
1258                                         
1259                         case DataControlCommands.FirstPageCommandArgument:
1260                                 ShowPage (0);
1261                                 break;
1262
1263                         case DataControlCommands.LastPageCommandArgument:
1264                                 ShowPage (PageCount - 1);
1265                                 break;
1266                                         
1267                         case DataControlCommands.NextPageCommandArgument:
1268                                 if (PageIndex < PageCount - 1)
1269                                         ShowPage (PageIndex + 1);
1270                                 break;
1271
1272                         case DataControlCommands.PreviousPageCommandArgument:
1273                                 if (PageIndex > 0)
1274                                         ShowPage (PageIndex - 1);
1275                                 break;
1276                                         
1277                         case DataControlCommands.EditCommandName:
1278                                 ProcessChangeMode (FormViewMode.Edit, false);
1279                                 break;
1280                                         
1281                         case DataControlCommands.NewCommandName:
1282                                 ProcessChangeMode (FormViewMode.Insert, false);
1283                                 break;
1284                                         
1285                         case DataControlCommands.UpdateCommandName:
1286                                 UpdateItem (param, causesValidation);
1287                                 break;
1288                                         
1289                         case DataControlCommands.CancelCommandName:
1290                                 CancelEdit ();
1291                                 break;
1292                                         
1293                         case DataControlCommands.DeleteCommandName:
1294                                 DeleteItem ();
1295                                 break;
1296                                         
1297                         case DataControlCommands.InsertCommandName:
1298                                 InsertItem (causesValidation);
1299                                 break;
1300                         }
1301                 }
1302                 
1303                 void ShowPage (int index)
1304                 {
1305                         FormViewPageEventArgs args = new FormViewPageEventArgs (index);
1306                         OnPageIndexChanging (args);
1307
1308                         if (args.Cancel || !IsBoundUsingDataSourceID)
1309                                 return;
1310
1311                         int newIndex = args.NewPageIndex;
1312                         if (newIndex < 0 || newIndex >= PageCount)
1313                                 return;
1314                         EndRowEdit (false, false);
1315                         PageIndex = newIndex;
1316                         OnPageIndexChanged (EventArgs.Empty);
1317                 }
1318                 
1319                 public void ChangeMode (FormViewMode newMode)
1320                 {
1321                         if (CurrentMode == newMode)
1322                                 return;
1323                         CurrentMode = newMode;
1324                         RequireBinding ();
1325                 }
1326
1327                 void ProcessChangeMode (FormViewMode newMode, bool cancelingEdit)
1328                 {
1329                         FormViewModeEventArgs args = new FormViewModeEventArgs (newMode, cancelingEdit);
1330                         OnModeChanging (args);
1331
1332                         if (args.Cancel || !IsBoundUsingDataSourceID)
1333                                 return;
1334
1335                         ChangeMode (args.NewMode);
1336
1337                         OnModeChanged (EventArgs.Empty);
1338                 }
1339                 
1340                 void CancelEdit ()
1341                 {
1342                         EndRowEdit (true, true);
1343                 }
1344
1345                 public virtual void UpdateItem (bool causesValidation)
1346                 {
1347                         UpdateItem (null, causesValidation);
1348                 }
1349                 
1350                 void UpdateItem (string param, bool causesValidation)
1351                 {
1352                         if (causesValidation && Page != null && !Page.IsValid)
1353                                 return;
1354                         
1355                         if (currentMode != FormViewMode.Edit) throw new HttpException ("Must be in Edit mode");
1356
1357                         currentEditOldValues = OldEditValues.Values;
1358                         currentEditRowKeys = DataKey.Values;
1359                         currentEditNewValues = GetRowValues (false);
1360                         
1361                         FormViewUpdateEventArgs args = new FormViewUpdateEventArgs (param, currentEditRowKeys, currentEditOldValues, currentEditNewValues);
1362                         OnItemUpdating (args);
1363
1364                         if (args.Cancel || !IsBoundUsingDataSourceID)
1365                                 return;
1366                         
1367                         DataSourceView view = GetData ();
1368                         if (view == null)
1369                                 throw new HttpException ("The DataSourceView associated to data bound control was null");
1370                         view.Update (currentEditRowKeys, currentEditNewValues, currentEditOldValues, new DataSourceViewOperationCallback (UpdateCallback));
1371                 }
1372
1373                 bool UpdateCallback (int recordsAffected, Exception exception)
1374                 {
1375                         FormViewUpdatedEventArgs dargs = new FormViewUpdatedEventArgs (recordsAffected, exception, currentEditRowKeys, currentEditOldValues, currentEditNewValues);
1376                         OnItemUpdated (dargs);
1377
1378                         if (!dargs.KeepInEditMode)                              
1379                                 EndRowEdit (true, false);
1380
1381                         return dargs.ExceptionHandled;
1382                 }
1383
1384                 public virtual void InsertItem (bool causesValidation)
1385                 {
1386                         InsertItem (null, causesValidation);
1387                 }
1388                 
1389                 void InsertItem (string param, bool causesValidation)
1390                 {
1391                         if (causesValidation && Page != null && !Page.IsValid)
1392                                 return;
1393                         
1394                         if (currentMode != FormViewMode.Insert) throw new HttpException ("Must be in Insert mode");
1395                         
1396                         currentEditNewValues = GetRowValues (true);
1397                         FormViewInsertEventArgs args = new FormViewInsertEventArgs (param, currentEditNewValues);
1398                         OnItemInserting (args);
1399
1400                         if (args.Cancel || !IsBoundUsingDataSourceID)
1401                                 return;
1402
1403                         DataSourceView view = GetData ();
1404                         if (view == null)
1405                                 throw new HttpException ("The DataSourceView associated to data bound control was null");
1406                         view.Insert (currentEditNewValues, new DataSourceViewOperationCallback (InsertCallback));
1407                 }
1408                 
1409                 bool InsertCallback (int recordsAffected, Exception exception)
1410                 {
1411                         FormViewInsertedEventArgs dargs = new FormViewInsertedEventArgs (recordsAffected, exception, currentEditNewValues);
1412                         OnItemInserted (dargs);
1413
1414                         if (!dargs.KeepInInsertMode)                            
1415                                 EndRowEdit (true, false);
1416
1417                         return dargs.ExceptionHandled;
1418                 }
1419
1420                 public virtual void DeleteItem ()
1421                 {
1422                         currentEditRowKeys = DataKey.Values;
1423                         currentEditNewValues = GetRowValues (true);
1424                         
1425                         FormViewDeleteEventArgs args = new FormViewDeleteEventArgs (PageIndex, currentEditRowKeys, currentEditNewValues);
1426                         OnItemDeleting (args);
1427
1428                         if (args.Cancel || !IsBoundUsingDataSourceID)
1429                                 return;
1430
1431                         if (PageIndex > 0 && PageIndex == PageCount - 1)
1432                                 PageIndex--;
1433                                 
1434                         RequireBinding ();
1435                                 
1436                         DataSourceView view = GetData ();
1437                         if (view != null)
1438                                 view.Delete (currentEditRowKeys, currentEditNewValues, new DataSourceViewOperationCallback (DeleteCallback));
1439                         else {
1440                                 FormViewDeletedEventArgs dargs = new FormViewDeletedEventArgs (0, null, currentEditRowKeys, currentEditNewValues);
1441                                 OnItemDeleted (dargs);
1442                         }
1443                 }       
1444
1445                 bool DeleteCallback (int recordsAffected, Exception exception)
1446                 {
1447                         FormViewDeletedEventArgs dargs = new FormViewDeletedEventArgs (recordsAffected, exception, currentEditRowKeys, currentEditNewValues);
1448                         OnItemDeleted (dargs);
1449                         return dargs.ExceptionHandled;
1450                 }
1451                 
1452                 void EndRowEdit (bool switchToDefaultMode, bool cancelingEdit) 
1453                 {
1454                         if (switchToDefaultMode)
1455                                 ProcessChangeMode (DefaultMode, cancelingEdit);
1456                         oldEditValues = new DataKey (new OrderedDictionary ());
1457                         currentEditRowKeys = null;
1458                         currentEditOldValues = null;
1459                         currentEditNewValues = null;
1460                         RequireBinding ();
1461                 }
1462
1463                 protected internal override void LoadControlState (object ob)
1464                 {
1465                         if (ob == null) return;
1466                         object[] state = (object[]) ob;
1467                         base.LoadControlState (state[0]);
1468                         pageIndex = (int) state[1];
1469                         pageCount = (int) state[2];
1470                         CurrentMode = (FormViewMode) state[3];
1471                         defaultMode = (FormViewMode) state[4];
1472                         dataKeyNames = (string[]) state[5];
1473                         if (state [6] != null)
1474                                 ((IStateManager) DataKey).LoadViewState (state [6]);
1475                         if (state [7] != null)
1476                                 ((IStateManager) OldEditValues).LoadViewState (state [7]);
1477                 }
1478                 
1479                 protected internal override object SaveControlState ()
1480                 {
1481                         object bstate = base.SaveControlState ();
1482                         return new object [] {
1483                                 bstate, 
1484                                 pageIndex, 
1485                                 pageCount, 
1486                                 CurrentMode, 
1487                                 defaultMode, 
1488                                 dataKeyNames,
1489                                 (key == null ? null : ((IStateManager)key).SaveViewState()),
1490                                 (oldEditValues == null ? null : ((IStateManager) oldEditValues).SaveViewState ())
1491                         };
1492                 }
1493                 
1494                 protected override void TrackViewState()
1495                 {
1496                         base.TrackViewState();
1497                         if (pagerSettings != null) ((IStateManager)pagerSettings).TrackViewState();
1498                         if (footerStyle != null) ((IStateManager)footerStyle).TrackViewState();
1499                         if (headerStyle != null) ((IStateManager)headerStyle).TrackViewState();
1500                         if (pagerStyle != null) ((IStateManager)pagerStyle).TrackViewState();
1501                         if (rowStyle != null) ((IStateManager)rowStyle).TrackViewState();
1502                         if (editRowStyle != null) ((IStateManager)editRowStyle).TrackViewState();
1503                         if (insertRowStyle != null) ((IStateManager)insertRowStyle).TrackViewState();
1504                         if (emptyDataRowStyle != null) ((IStateManager)emptyDataRowStyle).TrackViewState();
1505                 }
1506
1507                 protected override object SaveViewState()
1508                 {
1509                         object[] states = new object [10];
1510                         states[0] = base.SaveViewState();
1511                         states[1] = (pagerSettings == null ? null : ((IStateManager)pagerSettings).SaveViewState());
1512                         states[2] = (footerStyle == null ? null : ((IStateManager)footerStyle).SaveViewState());
1513                         states[3] = (headerStyle == null ? null : ((IStateManager)headerStyle).SaveViewState());
1514                         states[4] = (pagerStyle == null ? null : ((IStateManager)pagerStyle).SaveViewState());
1515                         states[5] = (rowStyle == null ? null : ((IStateManager)rowStyle).SaveViewState());
1516                         states[6] = (insertRowStyle == null ? null : ((IStateManager)insertRowStyle).SaveViewState());
1517                         states[7] = (editRowStyle == null ? null : ((IStateManager)editRowStyle).SaveViewState());
1518                         states[8] = (emptyDataRowStyle == null ? null : ((IStateManager)emptyDataRowStyle).SaveViewState());
1519                         
1520                         for (int i = states.Length - 1; i >= 0; i--) {
1521                                 if (states [i] != null)
1522                                         return states;
1523                         }
1524
1525                         return null;
1526                 }
1527
1528                 protected override void LoadViewState (object savedState)
1529                 {
1530                         if (savedState == null) {
1531                                 base.LoadViewState (null);
1532                                 return;
1533                         }
1534
1535                         object [] states = (object []) savedState;
1536                         
1537                         base.LoadViewState (states[0]);
1538                         
1539                         if (states[1] != null) ((IStateManager)PagerSettings).LoadViewState (states[1]);
1540                         if (states[2] != null) ((IStateManager)FooterStyle).LoadViewState (states[2]);
1541                         if (states[3] != null) ((IStateManager)HeaderStyle).LoadViewState (states[3]);
1542                         if (states[4] != null) ((IStateManager)PagerStyle).LoadViewState (states[4]);
1543                         if (states[5] != null) ((IStateManager)RowStyle).LoadViewState (states[5]);
1544                         if (states[6] != null) ((IStateManager)InsertRowStyle).LoadViewState (states[6]);
1545                         if (states[7] != null) ((IStateManager)EditRowStyle).LoadViewState (states[7]);
1546                         if (states[8] != null) ((IStateManager)EmptyDataRowStyle).LoadViewState (states[8]);
1547                 }
1548                 
1549                 protected internal override void Render (HtmlTextWriter writer)
1550                 {
1551                         PrepareControlHierarchy ();
1552                         
1553                         if (table == null)
1554                                 return;
1555
1556                         table.Render (writer);
1557                 }
1558
1559                 PostBackOptions IPostBackContainer.GetPostBackOptions (IButtonControl control)
1560                 {
1561                         if (control == null)
1562                                 throw new ArgumentNullException ("control");
1563
1564                         if (control.CausesValidation)
1565                                 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.");
1566
1567                         PostBackOptions options = new PostBackOptions (this);
1568                         options.Argument = control.CommandName + "$" + control.CommandArgument;
1569                         options.RequiresJavaScriptProtocol = true;
1570
1571                         return options;
1572                 }
1573
1574         }
1575 }
1576
1577 #endif