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