New tests.
[mono.git] / mcs / class / System.Web / System.Web.UI.WebControls / GridView.cs
index 431e5bdaf05283d176882f264d6f6146d85fb726..26ace72c5ce04e6ab91bba0de75cd5e2295ab890 100644 (file)
@@ -40,17 +40,16 @@ using System.Reflection;
 
 namespace System.Web.UI.WebControls
 {
-       [DesignerAttribute ("System.Web.UI.Design.WebControls.GridViewDesigner, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.ComponentModel.Design.IDesigner")]
+       [SupportsEventValidation]
+       [DesignerAttribute ("System.Web.UI.Design.WebControls.GridViewDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
        [ControlValuePropertyAttribute ("SelectedValue")]
        [DefaultEventAttribute ("SelectedIndexChanged")]
        [AspNetHostingPermissionAttribute (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
        [AspNetHostingPermissionAttribute (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
-       public class GridView: CompositeDataBoundControl, ICallbackEventHandler, ICallbackContainer
+       public class GridView: CompositeDataBoundControl, ICallbackEventHandler, ICallbackContainer, IPostBackEventHandler, IPostBackContainer, IPersistedSelector
        {
                Table table;
                GridViewRowCollection rows;
-               GridViewRow headerRow;
-               GridViewRow footerRow;
                GridViewRow bottomPagerRow;
                GridViewRow topPagerRow;
                
@@ -75,30 +74,32 @@ namespace System.Web.UI.WebControls
                TableItemStyle pagerStyle;
                TableItemStyle rowStyle;
                TableItemStyle selectedRowStyle;
+               ArrayList _dataKeyArrayList;
                DataKeyArray keys;
                DataKey oldEditValues;
                AutoGeneratedFieldProperties[] autoFieldProperties;
+               string [] dataKeyNames = null;
                readonly string[] emptyKeys = new string[0];
-               
-               private static readonly object PageIndexChangedEvent = new object();
-               private static readonly object PageIndexChangingEvent = new object();
-               private static readonly object RowCancelingEditEvent = new object();
-               private static readonly object RowCommandEvent = new object();
-               private static readonly object RowCreatedEvent = new object();
-               private static readonly object RowDataBoundEvent = new object();
-               private static readonly object RowDeletedEvent = new object();
-               private static readonly object RowDeletingEvent = new object();
-               private static readonly object RowEditingEvent = new object();
-               private static readonly object RowUpdatedEvent = new object();
-               private static readonly object RowUpdatingEvent = new object();
-               private static readonly object SelectedIndexChangedEvent = new object();
-               private static readonly object SelectedIndexChangingEvent = new object();
-               private static readonly object SortedEvent = new object();
-               private static readonly object SortingEvent = new object();
+               IEnumerator _dataEnumerator;
+               
+               static readonly object PageIndexChangedEvent = new object();
+               static readonly object PageIndexChangingEvent = new object();
+               static readonly object RowCancelingEditEvent = new object();
+               static readonly object RowCommandEvent = new object();
+               static readonly object RowCreatedEvent = new object();
+               static readonly object RowDataBoundEvent = new object();
+               static readonly object RowDeletedEvent = new object();
+               static readonly object RowDeletingEvent = new object();
+               static readonly object RowEditingEvent = new object();
+               static readonly object RowUpdatedEvent = new object();
+               static readonly object RowUpdatingEvent = new object();
+               static readonly object SelectedIndexChangedEvent = new object();
+               static readonly object SelectedIndexChangingEvent = new object();
+               static readonly object SortedEvent = new object();
+               static readonly object SortingEvent = new object();
                
                // Control state
                int pageIndex;
-               int pageCount = -1;
                int selectedIndex = -1;
                int editIndex = -1;
                SortDirection sortDirection = SortDirection.Ascending;
@@ -195,16 +196,26 @@ namespace System.Web.UI.WebControls
                {
                        if (Events != null) {
                                GridViewPageEventHandler eh = (GridViewPageEventHandler) Events [PageIndexChangingEvent];
-                               if (eh != null) eh (this, e);
+                               if (eh != null) {
+                                       eh (this, e);
+                                       return;
+                               }
                        }
+                       if (!IsBoundUsingDataSourceID)
+                               throw new HttpException (String.Format ("The GridView '{0}' fired event PageIndexChanging which wasn't handled.", ID));
                }
                
                protected virtual void OnRowCancelingEdit (GridViewCancelEditEventArgs e)
                {
                        if (Events != null) {
                                GridViewCancelEditEventHandler eh = (GridViewCancelEditEventHandler) Events [RowCancelingEditEvent];
-                               if (eh != null) eh (this, e);
+                               if (eh != null) {
+                                       eh (this, e);
+                                       return;
+                               }
                        }
+                       if (!IsBoundUsingDataSourceID)
+                               throw new HttpException (String.Format ("The GridView '{0}' fired event RowCancelingEdit which wasn't handled.", ID));
                }
                
                protected virtual void OnRowCommand (GridViewCommandEventArgs e)
@@ -243,16 +254,26 @@ namespace System.Web.UI.WebControls
                {
                        if (Events != null) {
                                GridViewDeleteEventHandler eh = (GridViewDeleteEventHandler) Events [RowDeletingEvent];
-                               if (eh != null) eh (this, e);
+                               if (eh != null) {
+                                       eh (this, e);
+                                       return;
+                               }
                        }
+                       if (!IsBoundUsingDataSourceID)
+                               throw new HttpException (String.Format ("The GridView '{0}' fired event RowDeleting which wasn't handled.", ID));
                }
                
                protected virtual void OnRowEditing (GridViewEditEventArgs e)
                {
                        if (Events != null) {
                                GridViewEditEventHandler eh = (GridViewEditEventHandler) Events [RowEditingEvent];
-                               if (eh != null) eh (this, e);
+                               if (eh != null) {
+                                       eh (this, e);
+                                       return;
+                               }
                        }
+                       if (!IsBoundUsingDataSourceID)
+                               throw new HttpException (String.Format ("The GridView '{0}' fired event RowEditing which wasn't handled.", ID));
                }
                
                protected virtual void OnRowUpdated (GridViewUpdatedEventArgs e)
@@ -267,8 +288,13 @@ namespace System.Web.UI.WebControls
                {
                        if (Events != null) {
                                GridViewUpdateEventHandler eh = (GridViewUpdateEventHandler) Events [RowUpdatingEvent];
-                               if (eh != null) eh (this, e);
+                               if (eh != null) {
+                                       eh (this, e);
+                                       return;
+                               }
                        }
+                       if (!IsBoundUsingDataSourceID)
+                               throw new HttpException (String.Format ("The GridView '{0}' fired event RowUpdating which wasn't handled.", ID));
                }
                
                protected virtual void OnSelectedIndexChanged (EventArgs e)
@@ -299,20 +325,27 @@ namespace System.Web.UI.WebControls
                {
                        if (Events != null) {
                                GridViewSortEventHandler eh = (GridViewSortEventHandler) Events [SortingEvent];
-                               if (eh != null) eh (this, e);
+                               if (eh != null) {
+                                       eh (this, e);
+                                       return;
+                               }
                        }
+                       if (!IsBoundUsingDataSourceID)
+                               throw new HttpException (String.Format ("The GridView '{0}' fired event Sorting which wasn't handled.", ID));
                }
                
                
                [WebCategoryAttribute ("Paging")]
                [DefaultValueAttribute (false)]
-               public bool AllowPaging {
+               public virtual bool AllowPaging {
                        get {
                                object ob = ViewState ["AllowPaging"];
                                if (ob != null) return (bool) ob;
                                return false;
                        }
                        set {
+                               if (value == AllowPaging)
+                                       return;
                                ViewState ["AllowPaging"] = value;
                                RequireBinding ();
                        }
@@ -320,23 +353,25 @@ namespace System.Web.UI.WebControls
                
                [WebCategoryAttribute ("Behavior")]
                [DefaultValueAttribute (false)]
-               public bool AllowSorting {
+               public virtual bool AllowSorting {
                        get {
                                object ob = ViewState ["AllowSorting"];
                                if (ob != null) return (bool) ob;
                                return false;
                        }
                        set {
+                               if (value == AllowSorting)
+                                       return;
                                ViewState ["AllowSorting"] = value;
                                RequireBinding ();
                        }
                }
                
-           [WebCategoryAttribute ("Styles")]
+               [WebCategoryAttribute ("Styles")]
                [PersistenceMode (PersistenceMode.InnerProperty)]
                [NotifyParentProperty (true)]
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
-               public virtual TableItemStyle AlternatingRowStyle {
+               public TableItemStyle AlternatingRowStyle {
                        get {
                                if (alternatingRowStyle == null) {
                                        alternatingRowStyle = new TableItemStyle ();
@@ -356,6 +391,8 @@ namespace System.Web.UI.WebControls
                                return false;
                        }
                        set {
+                               if (value == AutoGenerateEditButton)
+                                       return;
                                ViewState ["AutoGenerateEditButton"] = value;
                                RequireBinding ();
                        }
@@ -370,6 +407,8 @@ namespace System.Web.UI.WebControls
                                return false;
                        }
                        set {
+                               if (value == AutoGenerateDeleteButton)
+                                       return;
                                ViewState ["AutoGenerateDeleteButton"] = value;
                                RequireBinding ();
                        }
@@ -384,6 +423,8 @@ namespace System.Web.UI.WebControls
                                return false;
                        }
                        set {
+                               if (value == AutoGenerateSelectButton)
+                                       return;
                                ViewState ["AutoGenerateSelectButton"] = value;
                                RequireBinding ();
                        }
@@ -398,6 +439,8 @@ namespace System.Web.UI.WebControls
                                return true;
                        }
                        set {
+                               if (value == AutoGenerateColumns)
+                                       return;
                                ViewState ["AutoGenerateColumns"] = value;
                                RequireBinding ();
                        }
@@ -406,16 +449,15 @@ namespace System.Web.UI.WebControls
                [UrlPropertyAttribute]
                [WebCategoryAttribute ("Appearance")]
                [DefaultValueAttribute ("")]
-               [EditorAttribute ("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
+               [EditorAttribute ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
                public virtual string BackImageUrl {
                        get {
-                               object ob = ViewState ["BackImageUrl"];
-                               if (ob != null) return (string) ob;
-                               return string.Empty;
+                               if (ControlStyleCreated)
+                                       return ((TableStyle) ControlStyle).BackImageUrl;
+                               return String.Empty;
                        }
                        set {
-                               ViewState ["BackImageUrl"] = value;
-                               RequireBinding ();
+                               ((TableStyle) ControlStyle).BackImageUrl = value;
                        }
                }
 
@@ -431,7 +473,7 @@ namespace System.Web.UI.WebControls
                [WebCategoryAttribute ("Accessibility")]
                [DefaultValueAttribute ("")]
                [LocalizableAttribute (true)]
-               public string Caption {
+               public virtual string Caption {
                        get {
                                object ob = ViewState ["Caption"];
                                if (ob != null) return (string) ob;
@@ -439,7 +481,6 @@ namespace System.Web.UI.WebControls
                        }
                        set {
                                ViewState ["Caption"] = value;
-                               RequireBinding ();
                        }
                }
                
@@ -454,7 +495,6 @@ namespace System.Web.UI.WebControls
                        }
                        set {
                                ViewState ["CaptionAlign"] = value;
-                               RequireBinding ();
                        }
                }
 
@@ -463,13 +503,12 @@ namespace System.Web.UI.WebControls
                public virtual int CellPadding
                {
                        get {
-                               object o = ViewState ["CellPadding"];
-                               if (o != null) return (int) o;
+                               if (ControlStyleCreated)
+                                       return ((TableStyle) ControlStyle).CellPadding;
                                return -1;
                        }
                        set {
-                               ViewState ["CellPadding"] = value;
-                               RequireBinding ();
+                               ((TableStyle) ControlStyle).CellPadding = value;
                        }
                }
 
@@ -478,17 +517,16 @@ namespace System.Web.UI.WebControls
                public virtual int CellSpacing
                {
                        get {
-                               object o = ViewState ["CellSpacing"];
-                               if (o != null) return (int) o;
+                               if (ControlStyleCreated)
+                                       return ((TableStyle) ControlStyle).CellSpacing;
                                return 0;
                        }
                        set {
-                               ViewState ["CellSpacing"] = value;
-                               RequireBinding ();
+                               ((TableStyle) ControlStyle).CellSpacing = value;
                        }
                }
                
-               [EditorAttribute ("System.Web.UI.Design.WebControls.DataControlFieldTypeEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
+               [EditorAttribute ("System.Web.UI.Design.WebControls.DataControlFieldTypeEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
                [MergablePropertyAttribute (false)]
                [PersistenceModeAttribute (PersistenceMode.InnerProperty)]
                [DefaultValueAttribute (null)]
@@ -505,49 +543,79 @@ namespace System.Web.UI.WebControls
                        }
                }
 
+               [BrowsableAttribute(false)]
+               public IAutoFieldGenerator ColumnsGenerator {
+                       get;
+                       set;
+               }
+
                [DefaultValueAttribute (null)]
                [WebCategoryAttribute ("Data")]
                [TypeConverter (typeof(StringArrayConverter))]
-               [EditorAttribute ("System.Web.UI.Design.WebControls.DataFieldEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
+               [EditorAttribute ("System.Web.UI.Design.WebControls.DataFieldEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
                public virtual string[] DataKeyNames
                {
                        get {
-                               object o = ViewState ["DataKeyNames"];
-                               if (o != null) return (string[]) o;
+                               if (dataKeyNames != null)
+                                       return dataKeyNames;
                                return emptyKeys;
                        }
                        set {
-                               ViewState ["DataKeyNames"] = value;
+                               dataKeyNames = value;
                                RequireBinding ();
                        }
                }
+
+               ArrayList DataKeyArrayList {
+                       get {
+                               if (_dataKeyArrayList == null) {
+                                       _dataKeyArrayList = new ArrayList ();
+                               }
+                               return _dataKeyArrayList;
+                       }
+               }
                
                [BrowsableAttribute (false)]
                [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
                public virtual DataKeyArray DataKeys {
                        get {
-                               EnsureDataBound ();
+                               if (keys == null) {
+                                       keys = new DataKeyArray (DataKeyArrayList);
+                                       if (IsTrackingViewState)
+                                               ((IStateManager) keys).TrackViewState ();
+                               }
                                return keys;
                        }
                }
 
+               DataKey OldEditValues {
+                       get {
+                               if (oldEditValues == null) {
+                                       oldEditValues = new DataKey (new OrderedDictionary ());
+                               }
+                               return oldEditValues;
+                       }
+               }
+
                [WebCategoryAttribute ("Misc")]
                [DefaultValueAttribute (-1)]
-               public int EditIndex {
+               public virtual int EditIndex {
                        get {
                                return editIndex;
                        }
                        set {
+                               if (value == editIndex)
+                                       return;
                                editIndex = value;
                                RequireBinding ();
                        }
                }
        
-           [WebCategoryAttribute ("Styles")]
+               [WebCategoryAttribute ("Styles")]
                [PersistenceMode (PersistenceMode.InnerProperty)]
                [NotifyParentProperty (true)]
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
-               public virtual TableItemStyle EditRowStyle {
+               public TableItemStyle EditRowStyle {
                        get {
                                if (editRowStyle == null) {
                                        editRowStyle = new TableItemStyle ();
@@ -558,11 +626,11 @@ namespace System.Web.UI.WebControls
                        }
                }
                
-           [WebCategoryAttribute ("Styles")]
+               [WebCategoryAttribute ("Styles")]
                [PersistenceMode (PersistenceMode.InnerProperty)]
                [NotifyParentProperty (true)]
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
-               public virtual TableItemStyle EmptyDataRowStyle {
+               public TableItemStyle EmptyDataRowStyle {
                        get {
                                if (emptyDataRowStyle == null) {
                                        emptyDataRowStyle = new TableItemStyle ();
@@ -574,12 +642,12 @@ namespace System.Web.UI.WebControls
                }
                
                [DefaultValue (null)]
-               [TemplateContainer (typeof(GridView), BindingDirection.OneWay)]
+               [TemplateContainer (typeof(GridViewRow), BindingDirection.OneWay)]
                [PersistenceMode (PersistenceMode.InnerProperty)]
-           [Browsable (false)]
-               public ITemplate EmptyDataTemplate {
+               [Browsable (false)]
+               public virtual ITemplate EmptyDataTemplate {
                        get { return emptyDataTemplate; }
-                       set { emptyDataTemplate = value; RequireBinding (); }
+                       set { emptyDataTemplate = value; }
                }
                
                [LocalizableAttribute (true)]
@@ -592,6 +660,8 @@ namespace System.Web.UI.WebControls
                                return string.Empty;
                        }
                        set {
+                               if (value == EmptyDataText)
+                                       return;
                                ViewState ["EmptyDataText"] = value;
                                RequireBinding ();
                        }
@@ -606,6 +676,8 @@ namespace System.Web.UI.WebControls
                                return false;
                        }
                        set {
+                               if (value == EnableSortingAndPagingCallbacks)
+                                       return;
                                ViewState ["EnableSortingAndPagingCallbacks"] = value;
                                RequireBinding ();
                        }
@@ -615,18 +687,30 @@ namespace System.Web.UI.WebControls
                [BrowsableAttribute (false)]
                public virtual GridViewRow FooterRow {
                        get {
-                               if (footerRow == null)
-                                       footerRow = CreateRow (0, 0, DataControlRowType.Footer, DataControlRowState.Normal);
-                               return footerRow;
+                               if (table != null) {
+                                       for (int index = table.Rows.Count - 1; index >= 0; index--) {
+                                               GridViewRow row = (GridViewRow) table.Rows [index];
+                                               switch (row.RowType) {
+                                               case DataControlRowType.Separator:
+                                               case DataControlRowType.Pager:
+                                                       continue;
+                                               case DataControlRowType.Footer:
+                                                       return row;
+                                               default:
+                                                       break;
+                                               }
+                                       }
+                               }
+                               return null;
                        }
                }
        
-           [WebCategoryAttribute ("Styles")]
+               [WebCategoryAttribute ("Styles")]
                [PersistenceMode (PersistenceMode.InnerProperty)]
                [NotifyParentProperty (true)]
                [DefaultValue (null)]
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
-               public virtual TableItemStyle FooterStyle {
+               public TableItemStyle FooterStyle {
                        get {
                                if (footerStyle == null) {
                                        footerStyle = new TableItemStyle ();
@@ -641,12 +725,12 @@ namespace System.Web.UI.WebControls
                [DefaultValueAttribute (GridLines.Both)]
                public virtual GridLines GridLines {
                        get {
-                               object ob = ViewState ["GridLines"];
-                               if (ob != null) return (GridLines) ob;
+                               if (ControlStyleCreated)
+                                       return ((TableStyle) ControlStyle).GridLines;
                                return GridLines.Both;
                        }
                        set {
-                               ViewState ["GridLines"] = value;
+                               ((TableStyle) ControlStyle).GridLines = value;
                        }
                }
 
@@ -654,18 +738,30 @@ namespace System.Web.UI.WebControls
                [BrowsableAttribute (false)]
                public virtual GridViewRow HeaderRow {
                        get {
-                               if (headerRow == null)
-                                       headerRow = CreateRow (0, 0, DataControlRowType.Header, DataControlRowState.Normal);
-                               return headerRow;
+                               if (table != null) {
+                                       for (int index = 0, total = table.Rows.Count; index < total; index++) {
+                                               GridViewRow row = (GridViewRow) table.Rows [index];
+                                               switch (row.RowType) {
+                                               case DataControlRowType.Separator:
+                                               case DataControlRowType.Pager:
+                                                       continue;
+                                               case DataControlRowType.Header:
+                                                       return row;
+                                               default:
+                                                       break;
+                                               }
+                                       }
+                               }
+                               return null;
                        }
                }
        
-           [WebCategoryAttribute ("Styles")]
+               [WebCategoryAttribute ("Styles")]
                [PersistenceMode (PersistenceMode.InnerProperty)]
                [NotifyParentProperty (true)]
                [DefaultValue (null)]
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
-               public virtual TableItemStyle HeaderStyle {
+               public TableItemStyle HeaderStyle {
                        get {
                                if (headerStyle == null) {
                                        headerStyle = new TableItemStyle ();
@@ -676,37 +772,40 @@ namespace System.Web.UI.WebControls
                        }
                }
                
+               [Category ("Layout")]
                [DefaultValueAttribute (HorizontalAlign.NotSet)]
                public virtual HorizontalAlign HorizontalAlign {
                        get {
-                               object ob = ViewState ["HorizontalAlign"];
-                               if (ob != null) return (HorizontalAlign) ob;
+                               if (ControlStyleCreated)
+                                       return ((TableStyle) ControlStyle).HorizontalAlign;
                                return HorizontalAlign.NotSet;
                        }
                        set {
-                               ViewState ["HorizontalAlign"] = value;
-                               RequireBinding ();
+                               ((TableStyle) ControlStyle).HorizontalAlign = value;
                        }
                }
 
                [BrowsableAttribute (false)]
                [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
-               public int PageCount {
+               public virtual int PageCount {
                        get {
-                               if (pageCount != -1) return pageCount;
-                               EnsureDataBound ();
-                               return pageCount;
+                               return ViewState.GetInt ("PageCount", 0);
+                       }
+                       private set {
+                               ViewState ["PageCount"] = value;
                        }
                }
 
                [WebCategoryAttribute ("Paging")]
                [BrowsableAttribute (true)]
                [DefaultValueAttribute (0)]
-               public int PageIndex {
+               public virtual int PageIndex {
                        get {
                                return pageIndex;
                        }
                        set {
+                               if (value == pageIndex)
+                                       return;
                                pageIndex = value;
                                RequireBinding ();
                        }
@@ -714,13 +813,15 @@ namespace System.Web.UI.WebControls
        
                [DefaultValueAttribute (10)]
                [WebCategoryAttribute ("Paging")]
-               public int PageSize {
+               public virtual int PageSize {
                        get {
                                object ob = ViewState ["PageSize"];
                                if (ob != null) return (int) ob;
                                return 10;
                        }
                        set {
+                               if (value == PageSize)
+                                       return;
                                ViewState ["PageSize"] = value;
                                RequireBinding ();
                        }
@@ -730,7 +831,7 @@ namespace System.Web.UI.WebControls
                [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Content)]
                [NotifyParentPropertyAttribute (true)]
                [PersistenceModeAttribute (PersistenceMode.InnerProperty)]
-               public PagerSettings PagerSettings {
+               public virtual PagerSettings PagerSettings {
                        get {
                                if (pagerSettings == null) {
                                        pagerSettings = new PagerSettings (this);
@@ -741,11 +842,11 @@ namespace System.Web.UI.WebControls
                        }
                }
        
-           [WebCategoryAttribute ("Styles")]
+               [WebCategoryAttribute ("Styles")]
                [PersistenceMode (PersistenceMode.InnerProperty)]
                [NotifyParentProperty (true)]
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
-               public virtual TableItemStyle PagerStyle {
+               public TableItemStyle PagerStyle {
                        get {
                                if (pagerStyle == null) {
                                        pagerStyle = new TableItemStyle ();
@@ -758,17 +859,18 @@ namespace System.Web.UI.WebControls
                
                
                [DefaultValue (null)]
-               [TemplateContainer (typeof(GridView), BindingDirection.OneWay)]
+               /* DataControlPagerCell isnt specified in the docs */
+               //[TemplateContainer (typeof(DataControlPagerCell), BindingDirection.OneWay)]
                [PersistenceMode (PersistenceMode.InnerProperty)]
-           [Browsable (false)]
-               public ITemplate PagerTemplate {
+               [Browsable (false)]
+               public virtual ITemplate PagerTemplate {
                        get { return pagerTemplate; }
-                       set { pagerTemplate = value; RequireBinding (); }
+                       set { pagerTemplate = value; }
                }
                
                [DefaultValueAttribute ("")]
                [WebCategoryAttribute ("Accessibility")]
-//             [TypeConverterAttribute (typeof(System.Web.UI.Design.DataColumnSelectionConverter)]
+               //              [TypeConverterAttribute (typeof(System.Web.UI.Design.DataColumnSelectionConverter)]
                public virtual string RowHeaderColumn {
                        get {
                                object ob = ViewState ["RowHeaderColumn"];
@@ -776,6 +878,8 @@ namespace System.Web.UI.WebControls
                                return string.Empty;
                        }
                        set {
+                               if (value == RowHeaderColumn)
+                                       return;
                                ViewState ["RowHeaderColumn"] = value;
                                RequireBinding ();
                        }
@@ -785,16 +889,18 @@ namespace System.Web.UI.WebControls
                [BrowsableAttribute (false)]
                public virtual GridViewRowCollection Rows {
                        get {
-                               EnsureDataBound ();
+                               EnsureChildControls ();
+                               if (rows == null)
+                                       rows = new GridViewRowCollection (new ArrayList ());
                                return rows;
                        }
                }
                
-           [WebCategoryAttribute ("Styles")]
+               [WebCategoryAttribute ("Styles")]
                [PersistenceMode (PersistenceMode.InnerProperty)]
                [NotifyParentProperty (true)]
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
-               public virtual TableItemStyle RowStyle {
+               public TableItemStyle RowStyle {
                        get {
                                if (rowStyle == null) {
                                        rowStyle = new TableItemStyle ();
@@ -809,27 +915,42 @@ namespace System.Web.UI.WebControls
                [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
                public virtual DataKey SelectedDataKey {
                        get {
+                               if (DataKeyNames.Length == 0)
+                                       throw new InvalidOperationException (String.Format ("Data keys must be specified on GridView '{0}' before the selected data keys can be retrieved.  Use the DataKeyNames property to specify data keys.", ID));
+
                                if (selectedIndex >= 0 && selectedIndex < DataKeys.Count) {
                                        return DataKeys [selectedIndex];
                                } else
                                        return null;
                        }
                }
+
+               [MonoTODO]
+               [BrowsableAttribute(false)]
+               public virtual DataKey SelectedPersistedDataKey {
+                       get; set;
+               }
+
+               [MonoTODO]
+               DataKey IPersistedSelector.DataKey {
+                       get { return SelectedPersistedDataKey; }
+                       set { SelectedPersistedDataKey = value; }
+               }
                
                [BindableAttribute (true)]
                [DefaultValueAttribute (-1)]
-               public int SelectedIndex {
+               public virtual int SelectedIndex {
                        get {
                                return selectedIndex;
                        }
                        set {
-                               if (selectedIndex >= 0 && selectedIndex < Rows.Count) {
+                               if (rows != null && selectedIndex >= 0 && selectedIndex < Rows.Count) {
                                        int oldIndex = selectedIndex;
                                        selectedIndex = -1;
                                        Rows [oldIndex].RowState = GetRowState (oldIndex);
                                }
                                selectedIndex = value;
-                               if (selectedIndex >= 0 && selectedIndex < Rows.Count) {
+                               if (rows != null && selectedIndex >= 0 && selectedIndex < Rows.Count) {
                                        Rows [selectedIndex].RowState = GetRowState (selectedIndex);
                                }
                        }
@@ -846,11 +967,11 @@ namespace System.Web.UI.WebControls
                        }
                }
                
-           [WebCategoryAttribute ("Styles")]
+               [WebCategoryAttribute ("Styles")]
                [PersistenceMode (PersistenceMode.InnerProperty)]
                [NotifyParentProperty (true)]
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
-               public virtual TableItemStyle SelectedRowStyle {
+               public TableItemStyle SelectedRowStyle {
                        get {
                                if (selectedRowStyle == null) {
                                        selectedRowStyle = new TableItemStyle ();
@@ -862,7 +983,7 @@ namespace System.Web.UI.WebControls
                }
                
                [BrowsableAttribute (false)]
-               public virtual object SelectedValue {
+               public object SelectedValue {
                        get {
                                if (SelectedDataKey != null)
                                        return SelectedDataKey.Value;
@@ -880,6 +1001,8 @@ namespace System.Web.UI.WebControls
                                return false;
                        }
                        set {
+                               if (value == ShowFooter)
+                                       return;
                                ViewState ["ShowFooter"] = value;
                                RequireBinding ();
                        }
@@ -894,6 +1017,8 @@ namespace System.Web.UI.WebControls
                                return true;
                        }
                        set {
+                               if (value == ShowHeader)
+                                       return;
                                ViewState ["ShowHeader"] = value;
                                RequireBinding ();
                        }
@@ -905,12 +1030,28 @@ namespace System.Web.UI.WebControls
                [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
                public virtual SortDirection SortDirection {
                        get { return sortDirection; }
+                       private set {
+                               if (sortDirection == value)
+                                       return;
+                               sortDirection = value;
+                               RequireBinding ();
+                       }
                }
                
                [BrowsableAttribute (false)]
                [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
                public virtual string SortExpression {
-                       get { return sortExpression; }
+                       get {
+                               if (sortExpression == null)
+                                       return String.Empty;
+                               return sortExpression;
+                       }
+                       private set {
+                               if (sortExpression == value)
+                                       return;
+                               sortExpression = value;
+                               RequireBinding ();
+                       }
                }
                
                [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
@@ -931,6 +1072,8 @@ namespace System.Web.UI.WebControls
                                return true;
                        }
                        set {
+                               if (value == UseAccessibleHeader)
+                                       return;
                                ViewState ["UseAccessibleHeader"] = value;
                                RequireBinding ();
                        }
@@ -938,16 +1081,48 @@ namespace System.Web.UI.WebControls
        
                public virtual bool IsBindableType (Type type)
                {
-                       return type.IsPrimitive || type == typeof(string) || type == typeof(DateTime) || type == typeof(Guid);
+                       return type.IsPrimitive || type == typeof (string) || type == typeof (decimal) || type == typeof (DateTime) || type == typeof (Guid);
                }
                
+               // MSDN: The CreateDataSourceSelectArguments method is a helper method called by 
+               // the GridView control to create the DataSourceSelectArguments object that 
+               // contains the arguments passed to the data source. In this implementation, 
+               // the DataSourceSelectArguments object contains the arguments for paging operations.
                protected override DataSourceSelectArguments CreateDataSourceSelectArguments ()
                {
-                       return base.CreateDataSourceSelectArguments ();
+                       DataSourceSelectArguments arg = DataSourceSelectArguments.Empty;
+                       DataSourceView view= GetData();
+                       if (AllowPaging && view.CanPage) {
+                               arg.StartRowIndex = PageIndex * PageSize;
+                               if (view.CanRetrieveTotalRowCount) {
+                                       arg.RetrieveTotalRowCount = true;
+                                       arg.MaximumRows = PageSize;
+                               }
+                               else {
+                                       arg.MaximumRows = -1;
+                               }
+                       }
+
+                       if (IsBoundUsingDataSourceID && !String.IsNullOrEmpty (sortExpression)) {
+                               if (sortDirection == SortDirection.Ascending)
+                                       arg.SortExpression = sortExpression;
+                               else
+                                       arg.SortExpression = sortExpression + " DESC";
+                       }
+                       
+                       return arg;
                }
                
                protected virtual ICollection CreateColumns (PagedDataSource dataSource, bool useDataSource)
                {
+                       bool autoGenerate = AutoGenerateColumns;
+
+                       if (autoGenerate) {
+                               IAutoFieldGenerator fieldGenerator = ColumnsGenerator;
+                               if (fieldGenerator != null)
+                                       return fieldGenerator.GenerateFields (this);
+                       }
+                       
                        ArrayList fields = new ArrayList ();
                        
                        if (AutoGenerateEditButton || AutoGenerateDeleteButton || AutoGenerateSelectButton) {
@@ -957,8 +1132,10 @@ namespace System.Web.UI.WebControls
                                field.ShowSelectButton = AutoGenerateSelectButton;
                                fields.Add (field);
                        }
+
+                       fields.AddRange (Columns);
                        
-                       if (AutoGenerateColumns) {
+                       if (autoGenerate) {
                                if (useDataSource)
                                        autoFieldProperties = CreateAutoFieldProperties (dataSource);
        
@@ -968,8 +1145,6 @@ namespace System.Web.UI.WebControls
                                }
                        }
                        
-                       fields.AddRange (Columns);
-                       
                        return fields;
                }
                
@@ -992,9 +1167,9 @@ namespace System.Web.UI.WebControls
                                object fitem = null;
                                prop_type = null;
                                PropertyInfo prop_item =  source.DataSource.GetType().GetProperty("Item",
-                                                 BindingFlags.Instance | BindingFlags.Static |
-                                                 BindingFlags.Public, null, null,
-                                                 new Type[] { typeof(int) }, null);
+                                                                                                 BindingFlags.Instance | BindingFlags.Static |
+                                                                                                 BindingFlags.Public, null, null,
+                                                                                                 new Type[] { typeof(int) }, null);
                                
                                if (prop_item != null) {
                                        prop_type = prop_item.PropertyType;
@@ -1002,8 +1177,10 @@ namespace System.Web.UI.WebControls
                                
                                if (prop_type == null || prop_type == typeof(object)) {
                                        IEnumerator en = source.GetEnumerator();
-                                       if (en.MoveNext())
+                                       if (en != null && en.MoveNext ()) {
                                                fitem = en.Current;
+                                               _dataEnumerator = en;
+                                       }
                                        if (fitem != null)
                                                prop_type = fitem.GetType();
                                }
@@ -1032,7 +1209,12 @@ namespace System.Web.UI.WebControls
                                                ((IStateManager)field).TrackViewState();
                                                field.Name = current.Name;
                                                field.DataField = current.Name;
-                                               field.IsReadOnly = current.IsReadOnly;
+                                               for (int i = 0; i < DataKeyNames.Length; i++) {
+                                                       if (string.Compare (DataKeyNames [i], current.Name, StringComparison.InvariantCultureIgnoreCase) == 0) {
+                                                               field.IsReadOnly = true;
+                                                               break;
+                                                       }
+                                               }
                                                field.Type = current.PropertyType;
                                                retVal.Add (field);
                                        }
@@ -1048,7 +1230,6 @@ namespace System.Web.UI.WebControls
                protected virtual GridViewRow CreateRow (int rowIndex, int dataSourceIndex, DataControlRowType rowType, DataControlRowState rowState)
                {
                        GridViewRow row = new GridViewRow (rowIndex, dataSourceIndex, rowType, rowState);
-                       OnRowCreated (new GridViewRowEventArgs (row));
                        return row;
                }
                
@@ -1056,24 +1237,25 @@ namespace System.Web.UI.WebControls
                {
                        if (Initialized) {
                                RequiresDataBinding = true;
-                               pageCount = -1;
                        }
                }
                
                protected virtual Table CreateChildTable ()
                {
-                       Table table = new Table ();
-                       table.Caption = Caption;
-                       table.CaptionAlign = CaptionAlign;
-                       table.CellPadding = CellPadding;
-                       table.CellSpacing = CellSpacing;
-                       table.HorizontalAlign = HorizontalAlign;
-                       table.BackImageUrl = BackImageUrl;
-                       return table;
+                       return new ContainedTable (this);
                }
        
                protected override int CreateChildControls (IEnumerable data, bool dataBinding)
                {
+                       // clear GridView
+                       Controls.Clear ();
+                       table = null;
+                       rows = null;
+
+                       if (data == null) {
+                               return 0;
+                       }
+
                        PagedDataSource dataSource;
 
                        if (dataBinding) {
@@ -1084,20 +1266,17 @@ namespace System.Web.UI.WebControls
                                if (AllowPaging) {
                                        dataSource.AllowPaging = true;
                                        dataSource.PageSize = PageSize;
-                                       dataSource.CurrentPageIndex = PageIndex;
                                        if (view.CanPage) {
                                                dataSource.AllowServerPaging = true;
-                                               if (view.CanRetrieveTotalRowCount)
+                                               if (SelectArguments.RetrieveTotalRowCount)
                                                        dataSource.VirtualCount = SelectArguments.TotalRowCount;
-                                               else {
-                                                       dataSource.DataSourceView = view;
-                                                       dataSource.DataSourceSelectArguments = SelectArguments;
-                                                       dataSource.SetItemCountFromPageIndex (PageIndex + PagerSettings.PageButtonCount);
-                                               }
                                        }
+                                       if (PageIndex >= dataSource.PageCount)
+                                               pageIndex = dataSource.PageCount - 1;
+                                       dataSource.CurrentPageIndex = PageIndex;
                                }
                                
-                               pageCount = dataSource.PageCount;
+                               PageCount = dataSource.PageCount;
                        }
                        else
                        {
@@ -1110,81 +1289,144 @@ namespace System.Web.UI.WebControls
                                }
                        }
 
-                       bool showPager = AllowPaging && (PageCount > 1);
-                       
-                       Controls.Clear ();
-                       table = CreateChildTable ();
-                       Controls.Add (table);
-                               
+                       bool createPager = AllowPaging && (PageCount >= 1) && PagerSettings.Visible;
+
                        ArrayList list = new ArrayList ();
-                       ArrayList keyList = new ArrayList ();
                        
                        // Creates the set of fields to show
-                       
+
+                       _dataEnumerator = null;
                        ICollection fieldCollection = CreateColumns (dataSource, dataBinding);
-                       DataControlField[] fields = new DataControlField [fieldCollection.Count];
+                       int fieldCount = fieldCollection.Count;
+                       DataControlField dcf;
+                       DataControlField[] fields = new DataControlField [fieldCount];
                        fieldCollection.CopyTo (fields, 0);
-
-                       foreach (DataControlField field in fields) {
-                               field.Initialize (AllowSorting, this);
+                       
+                       for (int i = 0; i < fieldCount; i++) {
+                               dcf = fields [i];
+                               dcf.Initialize (AllowSorting, this);
                                if (EnableSortingAndPagingCallbacks)
-                                       field.ValidateSupportsCallback ();
+                                       dcf.ValidateSupportsCallback ();
                        }
 
-                       // Main table creation
-                       
-                       if (showPager && PagerSettings.Position == PagerPosition.Top || PagerSettings.Position == PagerPosition.TopAndBottom) {
-                               topPagerRow = CreatePagerRow (fields.Length, dataSource);
-                               table.Rows.Add (topPagerRow);
+                       bool skip_first = false;
+                       IEnumerator enumerator;
+                       if (_dataEnumerator != null) {
+                               // replaced when creating bound columns
+                               enumerator = _dataEnumerator;
+                               skip_first = true;
                        }
-
-                       if (ShowHeader) {
-                               headerRow = CreateRow (0, 0, DataControlRowType.Header, DataControlRowState.Normal);
-                               table.Rows.Add (headerRow);
-                               InitializeRow (headerRow, fields);
+                       else {
+                               enumerator = dataSource.GetEnumerator ();
                        }
-                       
-                       foreach (object obj in dataSource) {
+
+                       // Main table creation
+                       Table mainTable = ContainedTable;
+                       while (skip_first || enumerator.MoveNext ()) {
+                               skip_first = false;
+                               object obj = enumerator.Current;
+                               
+                               if (list.Count == 0) {
+                                       if (createPager && (PagerSettings.Position == PagerPosition.Top || PagerSettings.Position == PagerPosition.TopAndBottom)) {
+                                               topPagerRow = CreatePagerRow (fieldCount, dataSource);
+                                               OnRowCreated (new GridViewRowEventArgs (topPagerRow));
+                                               mainTable.Rows.Add (topPagerRow);
+                                               if (dataBinding) {
+                                                       topPagerRow.DataBind ();
+                                                       OnRowDataBound (new GridViewRowEventArgs (topPagerRow));
+                                               }
+                                               if (PageCount == 1)
+                                                       topPagerRow.Visible = false;
+                                       }
+
+                                       GridViewRow headerRow = CreateRow (-1, -1, DataControlRowType.Header, DataControlRowState.Normal);
+                                       InitializeRow (headerRow, fields);
+                                       OnRowCreated (new GridViewRowEventArgs (headerRow));
+                                       mainTable.Rows.Add (headerRow);
+                                       if (dataBinding) {
+                                               headerRow.DataBind ();
+                                               OnRowDataBound (new GridViewRowEventArgs (headerRow));
+                                       }
+                               }
+                               
                                DataControlRowState rstate = GetRowState (list.Count);
                                GridViewRow row = CreateRow (list.Count, list.Count, DataControlRowType.DataRow, rstate);
                                row.DataItem = obj;
                                list.Add (row);
-                               table.Rows.Add (row);
                                InitializeRow (row, fields);
+                               OnRowCreated (new GridViewRowEventArgs (row));
+                               mainTable.Rows.Add (row);
                                if (dataBinding) {
-//                                     row.DataBind ();
-                                       OnRowDataBound (new GridViewRowEventArgs (row));
-                                       if (EditIndex == row.RowIndex)
-                                               oldEditValues = new DataKey (GetRowValues (row, false, true));
-                                       keyList.Add (new DataKey (CreateRowDataKey (row), DataKeyNames));
-                               } else {
+                                       row.DataBind ();                                        
                                        if (EditIndex == row.RowIndex)
-                                               oldEditValues = new DataKey (new OrderedDictionary ());
-                                       keyList.Add (new DataKey (new OrderedDictionary (), DataKeyNames));
-                               }
-
-                               if (list.Count >= PageSize)
-                                       break;
+                                               oldEditValues = new DataKey (GetRowValues (row, true, true));
+                                       DataKeyArrayList.Add (new DataKey (CreateRowDataKey (row), DataKeyNames));
+                                       OnRowDataBound (new GridViewRowEventArgs (row));
+                               } 
                        }
-                       
-                       if (list.Count == 0)
-                               table.Rows.Add (CreateEmptyrRow (fields.Length));
 
-                       if (ShowFooter) {
-                               footerRow = CreateRow (0, 0, DataControlRowType.Footer, DataControlRowState.Normal);
-                               table.Rows.Add (footerRow);
-                               InitializeRow (footerRow, fields);
+                       if (list.Count == 0) {
+                               GridViewRow emptyRow = CreateEmptyrRow (fieldCount);
+                               if (emptyRow != null) {
+                                       OnRowCreated (new GridViewRowEventArgs (emptyRow));
+                                       mainTable.Rows.Add (emptyRow);
+                                       if (dataBinding) {
+                                               emptyRow.DataBind ();
+                                               OnRowDataBound (new GridViewRowEventArgs (emptyRow));
+                                       }
+                               }
+                               return 0;
                        }
+                       else {
+                               GridViewRow footerRow = CreateRow (-1, -1, DataControlRowType.Footer, DataControlRowState.Normal);
+                               InitializeRow (footerRow, fields);
+                               OnRowCreated (new GridViewRowEventArgs (footerRow));
+                               mainTable.Rows.Add (footerRow);
+                               if (dataBinding) {
+                                       footerRow.DataBind ();
+                                       OnRowDataBound (new GridViewRowEventArgs (footerRow));
+                               }
 
-                       if (showPager && PagerSettings.Position == PagerPosition.Bottom || PagerSettings.Position == PagerPosition.TopAndBottom) {
-                               bottomPagerRow = CreatePagerRow (fields.Length, dataSource);
-                               table.Rows.Add (bottomPagerRow);
+                               if (createPager && (PagerSettings.Position == PagerPosition.Bottom || PagerSettings.Position == PagerPosition.TopAndBottom)) {
+                                       bottomPagerRow = CreatePagerRow (fieldCount, dataSource);
+                                       OnRowCreated (new GridViewRowEventArgs (bottomPagerRow));
+                                       mainTable.Rows.Add (bottomPagerRow);
+                                       if (dataBinding) {
+                                               bottomPagerRow.DataBind ();
+                                               OnRowDataBound (new GridViewRowEventArgs (bottomPagerRow));
+                                       }
+                                       if (PageCount == 1)
+                                               bottomPagerRow.Visible = false;
+                               }
                        }
 
                        rows = new GridViewRowCollection (list);
-                       keys = new DataKeyArray (keyList);
-                       
-                       return dataSource.DataSourceCount;
+
+                       if (!dataBinding)
+                               return -1;
+
+                       if (AllowPaging)
+                               return dataSource.DataSourceCount;
+                       else
+                               return list.Count;
+               }
+
+               Table ContainedTable  {
+                       get {
+                               if (table == null) {
+                                       table = CreateChildTable ();
+                                       Controls.Add (table);
+                               }
+                               return table;
+                       }
+               }
+
+               protected override Style CreateControlStyle ()
+               {
+                       TableStyle style = new TableStyle (ViewState);
+                       style.GridLines = GridLines.Both;
+                       style.CellSpacing = 0;
+                       return style;
                }
                
                DataControlRowState GetRowState (int index)
@@ -1205,7 +1447,8 @@ namespace System.Web.UI.WebControls
                protected virtual void InitializePager (GridViewRow row, int columnSpan, PagedDataSource dataSource)
                {
                        TableCell cell = new TableCell ();
-                       cell.ColumnSpan = columnSpan;
+                       if (columnSpan > 1)
+                               cell.ColumnSpan = columnSpan;
                        
                        if (pagerTemplate != null)
                                pagerTemplate.InstantiateIn (cell);
@@ -1217,6 +1460,9 @@ namespace System.Web.UI.WebControls
                
                GridViewRow CreateEmptyrRow (int fieldCount)
                {
+                       if (emptyDataTemplate == null && String.IsNullOrEmpty (EmptyDataText))
+                               return null;
+
                        GridViewRow row = CreateRow (-1, -1, DataControlRowType.EmptyDataRow, DataControlRowState.Normal);
                        TableCell cell = new TableCell ();
                        cell.ColumnSpan = fieldCount;
@@ -1236,20 +1482,21 @@ namespace System.Web.UI.WebControls
                        bool accessibleHeader = false;
 
                        switch (row.RowType) {
-                               case DataControlRowType.Header:
-                                       ctype = DataControlCellType.Header; 
-                                       accessibleHeader = UseAccessibleHeader;
-                                       break;
-                               case DataControlRowType.Footer:
-                                       ctype = DataControlCellType.Footer;
-                                       break;
-                               default:
-                                       ctype = DataControlCellType.DataCell;
-                                       break;
+                       case DataControlRowType.Header:
+                               ctype = DataControlCellType.Header; 
+                               accessibleHeader = UseAccessibleHeader;
+                               break;
+                       case DataControlRowType.Footer:
+                               ctype = DataControlCellType.Footer;
+                               break;
+                       default:
+                               ctype = DataControlCellType.DataCell;
+                               break;
                        }
                        
                        for (int n=0; n<fields.Length; n++) {
                                DataControlField field = fields [n];
+                               
                                DataControlFieldCell cell;
                                if (((field is BoundField) && ((BoundField)field).DataField == RowHeaderColumn) || accessibleHeader)
                                        cell = new DataControlFieldHeaderCell (field, accessibleHeader ? TableHeaderScope.Column : TableHeaderScope.Row);
@@ -1266,9 +1513,9 @@ namespace System.Web.UI.WebControls
                                PropertyDescriptorCollection props = TypeDescriptor.GetProperties (row.DataItem);
                                cachedKeyProperties = new PropertyDescriptor [DataKeyNames.Length];
                                for (int n=0; n<DataKeyNames.Length; n++) { 
-                                       PropertyDescriptor p = props [DataKeyNames[n]];
+                                       PropertyDescriptor p = props.Find (DataKeyNames [n], true);
                                        if (p == null)
-                                               new InvalidOperationException ("Property '" + DataKeyNames[n] + "' not found in object of type " + row.DataItem.GetType());
+                                               throw new InvalidOperationException ("Property '" + DataKeyNames [n] + "' not found in object of type " + row.DataItem.GetType ());
                                        cachedKeyProperties [n] = p;
                                }
                        }
@@ -1288,10 +1535,17 @@ namespace System.Web.UI.WebControls
                
                protected virtual void ExtractRowValues (IOrderedDictionary fieldValues, GridViewRow row, bool includeReadOnlyFields, bool includePrimaryKey)
                {
+                       DataControlField field;
                        foreach (TableCell cell in row.Cells) {
                                DataControlFieldCell c = cell as DataControlFieldCell;
-                               if (c != null)
-                                       c.ContainingField.ExtractValuesFromCell (fieldValues, c, row.RowState, includeReadOnlyFields);
+                               if (c == null)
+                                       continue;
+                               
+                               field = c.ContainingField;
+                               if (field != null && !field.Visible)
+                                       continue;
+                               
+                               c.ContainingField.ExtractValuesFromCell (fieldValues, c, row.RowState, includeReadOnlyFields);
                        }
                        if (!includePrimaryKey && DataKeyNames != null)
                                foreach (string key in DataKeyNames)
@@ -1309,31 +1563,106 @@ namespace System.Web.UI.WebControls
                
                public sealed override void DataBind ()
                {
-                       DataSourceView view = GetData ();
-                       if (AllowPaging && view.CanPage) {
-                               SelectArguments.StartRowIndex = PageIndex * PageSize;
-                               SelectArguments.MaximumRows = PageSize;
-                               if (view.CanRetrieveTotalRowCount)
-                                       SelectArguments.RetrieveTotalRowCount = true;
-                       }
-
-                       if (sortExpression != "") {
-                               if (sortDirection == SortDirection.Ascending)
-                                       SelectArguments.SortExpression = sortExpression;
-                               else
-                                       SelectArguments.SortExpression = sortExpression + " DESC";
-                       }
-                       
+                       DataKeyArrayList.Clear ();
                        cachedKeyProperties = null;
                        base.DataBind ();
+
+                       keys = new DataKeyArray (DataKeyArrayList);
+                       
+                       GridViewRow row = HeaderRow;
+                       if (row != null)
+                               row.Visible = ShowHeader;
+
+                       row = FooterRow;
+                       if (row != null)
+                               row.Visible = ShowFooter;
                }
                
-               protected override void PerformDataBinding (IEnumerable data)
+               protected internal override void PerformDataBinding (IEnumerable data)
                {
                        base.PerformDataBinding (data);
                }
+
+               protected internal virtual void PrepareControlHierarchy ()
+               {
+                       if (table == null)
+                               return;
+
+                       table.Caption = Caption;
+                       table.CaptionAlign = CaptionAlign;
+                       table.CopyBaseAttributes (this);
+                       
+                       foreach (GridViewRow row in table.Rows) {
+                               switch (row.RowType) {
+                               case DataControlRowType.Header:
+                                       if (headerStyle != null && !headerStyle.IsEmpty)
+                                               row.ControlStyle.MergeWith(headerStyle);
+                                       row.Visible = ShowHeader;
+                                       break;
+                               case DataControlRowType.Footer:
+                                       if (footerStyle != null && !footerStyle.IsEmpty)
+                                               row.ControlStyle.MergeWith (footerStyle);
+                                       row.Visible = ShowFooter;
+                                       break;
+                               case DataControlRowType.Pager:
+                                       if (pagerStyle != null && !pagerStyle.IsEmpty)
+                                               row.ControlStyle.MergeWith (pagerStyle);
+                                       break;
+                               case DataControlRowType.EmptyDataRow:
+                                       if (emptyDataRowStyle != null && !emptyDataRowStyle.IsEmpty)
+                                               row.ControlStyle.MergeWith (emptyDataRowStyle);
+                                       break;
+                               case DataControlRowType.DataRow:
+                                       if ((row.RowState & DataControlRowState.Edit) != 0 && editRowStyle != null && !editRowStyle.IsEmpty)
+                                               row.ControlStyle.MergeWith (editRowStyle);
+                                       if ((row.RowState & DataControlRowState.Selected) != 0 && selectedRowStyle != null && !selectedRowStyle.IsEmpty)
+                                               row.ControlStyle.MergeWith (selectedRowStyle);
+                                       if ((row.RowState & DataControlRowState.Alternate) != 0 && alternatingRowStyle != null && !alternatingRowStyle.IsEmpty)
+                                               row.ControlStyle.MergeWith (alternatingRowStyle);
+                                       if (rowStyle != null && !rowStyle.IsEmpty)
+                                               row.ControlStyle.MergeWith (rowStyle);
+                                       break;
+                               default:
+                                       break;
+                               }
+
+                               foreach (TableCell cell in row.Cells) {
+                                       DataControlFieldCell fcell = cell as DataControlFieldCell;
+                                       if (fcell != null) {
+                                               DataControlField field = fcell.ContainingField;
+                                               if (field == null)
+                                                       continue;
+                                               if (!field.Visible) {
+                                                       cell.Visible = false;
+                                                       continue;
+                                               }
+                                               
+                                               switch (row.RowType) {
+                                               case DataControlRowType.Header:
+                                                       if (field.HeaderStyleCreated && !field.HeaderStyle.IsEmpty)
+                                                               cell.ControlStyle.MergeWith (field.HeaderStyle);
+                                                       break;
+                                               case DataControlRowType.Footer:
+                                                       if (field.FooterStyleCreated && !field.FooterStyle.IsEmpty)
+                                                               cell.ControlStyle.MergeWith (field.FooterStyle);
+                                                       break;
+                                               default:
+                                                       if (field.ControlStyleCreated && !field.ControlStyle.IsEmpty)
+                                                               foreach (Control c in cell.Controls) {
+                                                                       WebControl wc = c as WebControl;
+                                                                       if (wc != null)
+                                                                               wc.ControlStyle.MergeWith (field.ControlStyle);
+                                                               }
+                                                       if (field.ItemStyleCreated && !field.ItemStyle.IsEmpty)
+                                                               cell.ControlStyle.MergeWith (field.ItemStyle);
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+               }
                
-               protected override void OnInit (EventArgs e)
+               protected internal override void OnInit (EventArgs e)
                {
                        Page.RegisterRequiresControlState (this);
                        base.OnInit (e);
@@ -1360,115 +1689,139 @@ namespace System.Web.UI.WebControls
                {
                        GridViewCommandEventArgs args = e as GridViewCommandEventArgs;
                        if (args != null) {
+                               bool causesValidation = false;
+                               IButtonControl button = args.CommandSource as IButtonControl;
+                               if (button != null && button.CausesValidation) {
+                                       Page.Validate (button.ValidationGroup);
+                                       causesValidation = true;
+                               }
                                OnRowCommand (args);
-                               ProcessEvent (args.CommandName, args.CommandArgument as string);
+                               string param = args.CommandArgument as string;
+                               if (param == null || param.Length == 0) {
+                                       GridViewRow row = args.Row;
+                                       if (row != null)
+                                               param = row.RowIndex.ToString();
+                               }
+                               ProcessEvent (args.CommandName, param, causesValidation);
+                               return true;
                        }
                        return base.OnBubbleEvent (source, e);
                }
                
+               void IPostBackEventHandler.RaisePostBackEvent (string eventArgument)
+               {
+                       ValidateEvent (UniqueID, eventArgument);
+                       RaisePostBackEvent (eventArgument);
+               }
+
                // This is prolly obsolete
                protected virtual void RaisePostBackEvent (string eventArgument)
                {
+                       GridViewCommandEventArgs args;
                        int i = eventArgument.IndexOf ('$');
                        if (i != -1)
-                               ProcessEvent (eventArgument.Substring (0, i), eventArgument.Substring (i + 1));
+                               args = new GridViewCommandEventArgs (this, new CommandEventArgs (eventArgument.Substring (0, i), eventArgument.Substring (i + 1)));
                        else
-                               ProcessEvent (eventArgument, null);
+                               args = new GridViewCommandEventArgs (this, new CommandEventArgs (eventArgument, null));
+
+                       OnRowCommand (args);
+                       ProcessEvent (args.CommandName, (string) args.CommandArgument, false);
                }
-               
-               void ProcessEvent (string eventName, string param)
+
+               void ProcessEvent (string eventName, string param, bool causesValidation)
                {
                        switch (eventName)
                        {
-                               case "Page":
-                                       int newIndex = -1;
-                                       switch (param) {
-                                               case "First":
-                                                       newIndex = 0;
-                                                       break;
-                                               case "Last":
-                                                       newIndex = PageCount - 1;
-                                                       break;
-                                               case "Next":
-                                                       if (PageIndex < PageCount - 1) newIndex = PageIndex + 1;
-                                                       break;
-                                               case "Prev":
-                                                       if (PageIndex > 0) newIndex = PageIndex - 1;
-                                                       break;
-                                               default:
-                                                       newIndex = int.Parse (param) - 1;
-                                                       break;
-                                       }
-                                       ShowPage (newIndex);
+                       case DataControlCommands.PageCommandName:
+                               int newIndex = -1;
+                               switch (param) {
+                               case DataControlCommands.FirstPageCommandArgument:
+                                       newIndex = 0;
                                        break;
-                                       
-                               case "First":
-                                       ShowPage (0);
+                               case DataControlCommands.LastPageCommandArgument:
+                                       newIndex = PageCount - 1;
                                        break;
-
-                               case "Last":
-                                       ShowPage (PageCount - 1);
+                               case DataControlCommands.NextPageCommandArgument:
+                                       newIndex = PageIndex + 1;
                                        break;
-                                       
-                               case "Next":
-                                       if (PageIndex < PageCount - 1)
-                                               ShowPage (PageIndex + 1);
+                               case DataControlCommands.PreviousPageCommandArgument:
+                                       newIndex = PageIndex - 1;
                                        break;
-
-                               case "Prev":
-                                       if (PageIndex > 0)
-                                               ShowPage (PageIndex - 1);
+                               default:
+                                       int paramIndex = 0;
+                                       int.TryParse (param, out paramIndex);
+                                       newIndex = paramIndex - 1;
                                        break;
+                               }
+                               ShowPage (newIndex);
+                               break;
                                        
-                               case "Select":
-                                       SelectRow (int.Parse (param));
-                                       break;
+                       case DataControlCommands.FirstPageCommandArgument:
+                               ShowPage (0);
+                               break;
+
+                       case DataControlCommands.LastPageCommandArgument:
+                               ShowPage (PageCount - 1);
+                               break;
                                        
-                               case "Edit":
-                                       EditRow (int.Parse (param));
-                                       break;
+                       case DataControlCommands.NextPageCommandArgument:
+                               if (PageIndex < PageCount - 1)
+                                       ShowPage (PageIndex + 1);
+                               break;
+
+                       case DataControlCommands.PreviousPageCommandArgument:
+                               if (PageIndex > 0)
+                                       ShowPage (PageIndex - 1);
+                               break;
                                        
-                               case "Update":
-                                       UpdateRow (EditIndex, true);
-                                       break;
+                       case DataControlCommands.SelectCommandName:
+                               SelectRow (int.Parse (param));
+                               break;
                                        
-                               case "Cancel":
-                                       CancelEdit ();
-                                       break;
+                       case DataControlCommands.EditCommandName:
+                               EditRow (int.Parse (param));
+                               break;
                                        
-                               case "Delete":
-                                       DeleteRow (int.Parse (param));
-                                       break;
+                       case DataControlCommands.UpdateCommandName:
+                               int editIndex = int.Parse (param);
+                               UpdateRow (Rows [editIndex], editIndex, causesValidation);
+                               break;
                                        
-                               case "Sort":
-                                       Sort (param);
-                                       break;
+                       case DataControlCommands.CancelCommandName:
+                               CancelEdit ();
+                               break;
+                                       
+                       case DataControlCommands.DeleteCommandName:
+                               DeleteRow (int.Parse (param));
+                               break;
+                                       
+                       case DataControlCommands.SortCommandName:
+                               Sort (param);
+                               break;
                        }
                }
                
                void Sort (string newSortExpression)
                {
-                       SortDirection newDirection;
-                       if (sortExpression == newSortExpression) {
-                               if (sortDirection == SortDirection.Ascending)
-                                       newDirection = SortDirection.Descending;
-                               else
-                                       newDirection = SortDirection.Ascending;
-                       } else
-                               newDirection = sortDirection;
-                       
+                       SortDirection newDirection = SortDirection.Ascending;
+                       if (sortExpression == newSortExpression && sortDirection == SortDirection.Ascending)
+                               newDirection = SortDirection.Descending;
+
                        Sort (newSortExpression, newDirection);
                }
                
-               public void Sort (string newSortExpression, SortDirection newSortDirection)
+               public virtual void Sort (string newSortExpression, SortDirection newSortDirection)
                {
                        GridViewSortEventArgs args = new GridViewSortEventArgs (newSortExpression, newSortDirection);
                        OnSorting (args);
                        if (args.Cancel) return;
                        
-                       sortExpression = args.SortExpression;
-                       sortDirection = args.SortDirection;
-                       RequireBinding ();
+                       if (IsBoundUsingDataSourceID) {
+                               EditIndex = -1;
+                               PageIndex = 0;
+                               SortExpression = args.SortExpression;
+                               SortDirection = args.SortDirection;
+                       }
                        
                        OnSorted (EventArgs.Empty);
                }
@@ -1478,6 +1831,7 @@ namespace System.Web.UI.WebControls
                        GridViewSelectEventArgs args = new GridViewSelectEventArgs (index);
                        OnSelectedIndexChanging (args);
                        if (!args.Cancel) {
+                               RequireBinding ();
                                SelectedIndex = args.NewSelectedIndex;
                                OnSelectedIndexChanged (EventArgs.Empty);
                        }
@@ -1487,56 +1841,76 @@ namespace System.Web.UI.WebControls
                {
                        GridViewPageEventArgs args = new GridViewPageEventArgs (newIndex);
                        OnPageIndexChanging (args);
-                       if (!args.Cancel) {
-                               EndRowEdit ();
-                               PageIndex = args.NewPageIndex;
-                               OnPageIndexChanged (EventArgs.Empty);
-                       }
+                       
+                       if (args.Cancel || !IsBoundUsingDataSourceID)
+                               return;
+                       
+                       EndRowEdit ();
+                       PageIndex = args.NewPageIndex;
+                       OnPageIndexChanged (EventArgs.Empty);
                }
                
                void EditRow (int index)
                {
                        GridViewEditEventArgs args = new GridViewEditEventArgs (index);
                        OnRowEditing (args);
-                       if (!args.Cancel) {
-                               EditIndex = args.NewEditIndex;
-                       }
+                       
+                       if (args.Cancel || !IsBoundUsingDataSourceID)
+                               return;
+                       
+                       EditIndex = args.NewEditIndex;
                }
                
                void CancelEdit ()
                {
                        GridViewCancelEditEventArgs args = new GridViewCancelEditEventArgs (EditIndex);
                        OnRowCancelingEdit (args);
-                       if (!args.Cancel) {
-                               EndRowEdit ();
-                       }
+                       
+                       if (args.Cancel || !IsBoundUsingDataSourceID)
+                               return;
+
+                       EndRowEdit ();
                }
 
                [MonoTODO ("Support two-way binding expressions")]
                public virtual void UpdateRow (int rowIndex, bool causesValidation)
                {
-                       if (causesValidation)
-                               Page.Validate ();
-                       
                        if (rowIndex != EditIndex) throw new NotSupportedException ();
                        
-                       currentEditOldValues = oldEditValues.Values;
-
                        GridViewRow row = Rows [rowIndex];
-                       currentEditRowKeys = DataKeys [rowIndex].Values;
+                       UpdateRow (row, rowIndex, causesValidation);
+               }
+
+               void UpdateRow (GridViewRow row, int rowIndex, bool causesValidation)
+               {
+                       if (causesValidation && Page != null && !Page.IsValid)
+                               return;
+
+                       currentEditOldValues = CopyOrderedDictionary (OldEditValues.Values);
+                       currentEditRowKeys = CopyOrderedDictionary (DataKeys [rowIndex].Values);
                        currentEditNewValues = GetRowValues (row, false, false);
                        
-                       GridViewUpdateEventArgs args = new GridViewUpdateEventArgs (EditIndex, currentEditRowKeys, currentEditOldValues, currentEditNewValues);
+                       GridViewUpdateEventArgs args = new GridViewUpdateEventArgs (rowIndex, currentEditRowKeys, currentEditOldValues, currentEditNewValues);
                        OnRowUpdating (args);
-                       if (!args.Cancel) {
-                               DataSourceView view = GetData ();
-                               if (view == null) throw new HttpException ("The DataSourceView associated to data bound control was null");
-                               view.Update (currentEditRowKeys, currentEditNewValues, currentEditOldValues, new DataSourceViewOperationCallback (UpdateCallback));
-                       } else
-                               EndRowEdit ();
+                       
+                       if (args.Cancel || !IsBoundUsingDataSourceID)
+                               return;
+                       
+                       DataSourceView view = GetData ();
+                       if (view == null)
+                               throw new HttpException ("The DataSourceView associated to data bound control was null");
+                       view.Update (currentEditRowKeys, currentEditNewValues, currentEditOldValues, new DataSourceViewOperationCallback (UpdateCallback));
+               }
+
+               static IOrderedDictionary CopyOrderedDictionary (IOrderedDictionary sourceDic) {
+                       OrderedDictionary copyDic = new OrderedDictionary ();
+                       foreach (object key in sourceDic.Keys) {
+                               copyDic.Add (key, sourceDic [key]);
+                       }
+                       return copyDic;
                }
 
-        bool UpdateCallback (int recordsAffected, Exception exception)
+               bool UpdateCallback (int recordsAffected, Exception exception)
                {
                        GridViewUpdatedEventArgs dargs = new GridViewUpdatedEventArgs (recordsAffected, exception, currentEditRowKeys, currentEditOldValues, currentEditNewValues);
                        OnRowUpdated (dargs);
@@ -1547,28 +1921,29 @@ namespace System.Web.UI.WebControls
                        return dargs.ExceptionHandled;
                }
                
-               public void DeleteRow (int rowIndex)
+               public virtual void DeleteRow (int rowIndex)
                {
                        GridViewRow row = Rows [rowIndex];
-                       currentEditRowKeys = DataKeys [rowIndex].Values;
+                       currentEditRowKeys = CopyOrderedDictionary (DataKeys [rowIndex].Values);
                        currentEditNewValues = GetRowValues (row, true, true);
                        
                        GridViewDeleteEventArgs args = new GridViewDeleteEventArgs (rowIndex, currentEditRowKeys, currentEditNewValues);
                        OnRowDeleting (args);
 
-                       if (!args.Cancel) {
-                               RequireBinding ();
-                               DataSourceView view = GetData ();
-                               if (view != null)
-                                       view.Delete (currentEditRowKeys, currentEditNewValues, new DataSourceViewOperationCallback (DeleteCallback));
-                               else {
-                                       GridViewDeletedEventArgs dargs = new GridViewDeletedEventArgs (0, null, currentEditRowKeys, currentEditNewValues);
-                                       OnRowDeleted (dargs);
-                               }
+                       if (args.Cancel || !IsBoundUsingDataSourceID)
+                               return;
+                       
+                       RequireBinding ();
+                       DataSourceView view = GetData ();
+                       if (view != null)
+                               view.Delete (currentEditRowKeys, currentEditNewValues, new DataSourceViewOperationCallback (DeleteCallback));
+                       else {
+                               GridViewDeletedEventArgs dargs = new GridViewDeletedEventArgs (0, null, currentEditRowKeys, currentEditNewValues);
+                               OnRowDeleted (dargs);
                        }
                }
 
-        bool DeleteCallback (int recordsAffected, Exception exception)
+               bool DeleteCallback (int recordsAffected, Exception exception)
                {
                        GridViewDeletedEventArgs dargs = new GridViewDeletedEventArgs (recordsAffected, exception, currentEditRowKeys, currentEditNewValues);
                        OnRowDeleted (dargs);
@@ -1590,21 +1965,61 @@ namespace System.Web.UI.WebControls
                        object[] state = (object[]) ob;
                        base.LoadControlState (state[0]);
                        pageIndex = (int) state[1];
-                       pageCount = (int) state[2];
-                       selectedIndex = (int) state[3];
-                       editIndex = (int) state[4];
-                       sortExpression = (string) state[5];
-                       sortDirection = (SortDirection) state[6];
+                       selectedIndex = (int) state[2];
+                       editIndex = (int) state[3];
+                       sortExpression = (string) state[4];
+                       sortDirection = (SortDirection) state[5];
+                       DataKeyNames = (string []) state [6];
+                       if (state [7] != null)
+                               LoadDataKeyArrayState ((object []) state [7]);
+                       if (state [8] != null)
+                               ((IStateManager) OldEditValues).LoadViewState (state [8]);
                }
                
                protected internal override object SaveControlState ()
                {
+                       if (EnableSortingAndPagingCallbacks) {
+                               Page.ClientScript.RegisterHiddenField (ClientID + "_Page", PageIndex.ToString ());
+                               Page.ClientScript.RegisterHiddenField (ClientID + "_SortExpression", SortExpression);
+                               Page.ClientScript.RegisterHiddenField (ClientID + "_SortDirection", ((int)SortDirection).ToString());
+                       }
+
                        object bstate = base.SaveControlState ();
-                       return new object[] {
-                               bstate, pageIndex, pageCount, selectedIndex, editIndex, sortExpression, sortDirection
-                       };
+                       return new object [] {
+                               bstate, 
+                               pageIndex, 
+                               selectedIndex, 
+                               editIndex, 
+                               sortExpression, 
+                               sortDirection, 
+                               DataKeyNames,
+                               SaveDataKeyArrayState (),
+                               (oldEditValues == null ? null : ((IStateManager)oldEditValues).SaveViewState ())
+                                       };
                }
-               
+
+               object [] SaveDataKeyArrayState ()
+               {
+                       if (keys == null)
+                               return null;
+
+                       object [] state = new object [keys.Count];
+                       for (int i = 0; i < keys.Count; i++) {
+                               state [i] = ((IStateManager) keys [i]).SaveViewState ();
+                       }
+                       return state;
+               }
+
+               void LoadDataKeyArrayState (object [] state)
+               {
+                       for (int i = 0; i < state.Length; i++) {
+                               DataKey dataKey = new DataKey (new OrderedDictionary (DataKeyNames.Length), DataKeyNames);
+                               ((IStateManager) dataKey).LoadViewState (state [i]);
+                               DataKeyArrayList.Add (dataKey);
+                       }
+                       keys = new DataKeyArray (DataKeyArrayList);
+               }
+
                protected override void TrackViewState()
                {
                        base.TrackViewState();
@@ -1627,7 +2042,7 @@ namespace System.Web.UI.WebControls
 
                protected override object SaveViewState()
                {
-                       object[] states = new object [14];
+                       object[] states = new object [12];
                        states[0] = base.SaveViewState();
                        states[1] = (columns == null ? null : ((IStateManager)columns).SaveViewState());
                        states[2] = (pagerSettings == null ? null : ((IStateManager)pagerSettings).SaveViewState());
@@ -1639,8 +2054,6 @@ namespace System.Web.UI.WebControls
                        states[8] = (selectedRowStyle == null ? null : ((IStateManager)selectedRowStyle).SaveViewState());
                        states[9] = (editRowStyle == null ? null : ((IStateManager)editRowStyle).SaveViewState());
                        states[10] = (emptyDataRowStyle == null ? null : ((IStateManager)emptyDataRowStyle).SaveViewState());
-                       states[11] = (keys == null ? null : ((IStateManager)keys).SaveViewState());
-                       states[12] = (oldEditValues == null ? null : ((IStateManager)oldEditValues).SaveViewState());
                        
                        if (autoFieldProperties != null) {
                                object[] data = new object [autoFieldProperties.Length];
@@ -1649,7 +2062,7 @@ namespace System.Web.UI.WebControls
                                        data [n] = ((IStateManager)autoFieldProperties [n]).SaveViewState ();
                                        if (data [n] != null) allNull = false;
                                }
-                               if (!allNull) states [13] = data;
+                               if (!allNull) states [11] = data;
                        }
 
                        for (int i = states.Length - 1; i >= 0; i--) {
@@ -1669,8 +2082,8 @@ namespace System.Web.UI.WebControls
 
                        object [] states = (object []) savedState;
                        
-                       if (states[13] != null) {
-                               object[] data = (object[]) states [13];
+                       if (states[11] != null) {
+                               object[] data = (object[]) states [11];
                                autoFieldProperties = new AutoGeneratedFieldProperties [data.Length];
                                for (int n=0; n<data.Length; n++) {
                                        IStateManager p = new AutoGeneratedFieldProperties ();
@@ -1681,7 +2094,6 @@ namespace System.Web.UI.WebControls
                        }
 
                        base.LoadViewState (states[0]);
-                       EnsureChildControls ();
                        
                        if (states[1] != null) ((IStateManager)Columns).LoadViewState (states[1]);
                        if (states[2] != null) ((IStateManager)PagerSettings).LoadViewState (states[2]);
@@ -1693,34 +2105,41 @@ namespace System.Web.UI.WebControls
                        if (states[8] != null) ((IStateManager)SelectedRowStyle).LoadViewState (states[8]);
                        if (states[9] != null) ((IStateManager)EditRowStyle).LoadViewState (states[9]);
                        if (states[10] != null) ((IStateManager)EmptyDataRowStyle).LoadViewState (states[10]);
-                       if (states[11] != null) ((IStateManager)DataKeys).LoadViewState (states[11]);
-                       if (states[12] != null && oldEditValues != null) ((IStateManager)oldEditValues).LoadViewState (states[12]);
                }
                
-               string ICallbackEventHandler.RaiseCallbackEvent (string eventArgs)
+               void ICallbackEventHandler.RaiseCallbackEvent (string eventArgs)
                {
-                       return RaiseCallbackEvent (eventArgs);
+                       RaiseCallbackEvent (eventArgs);
                }
                
-               protected virtual string RaiseCallbackEvent (string eventArgs)
+               protected virtual void RaiseCallbackEvent (string eventArgs)
                {
                        string[] clientData = eventArgs.Split ('|');
-                       pageIndex = int.Parse (clientData[0]);
-                       sortExpression = HttpUtility.UrlDecode (clientData[1]);
-                       if (sortExpression == "") sortExpression = null;
-                       RequireBinding ();
+                       PageIndex = int.Parse (clientData[0]);
+                       SortExpression = HttpUtility.UrlDecode (clientData [1]);
+                       SortDirection = (SortDirection) int.Parse (clientData [2]);
                        
-                       RaisePostBackEvent (clientData[2]);
-                       EnsureDataBound ();
+                       RaisePostBackEvent (clientData[3]);
+                       DataBind ();
+               }
+               
+               string ICallbackEventHandler.GetCallbackResult ()
+               {
+                       return GetCallbackResult ();
+               }
+
+               protected virtual string GetCallbackResult ()
+               {
+                       PrepareControlHierarchy ();
                        
                        StringWriter sw = new StringWriter ();
-                       sw.Write (PageIndex.ToString() + '|' + SortExpression + '|');
+                       sw.Write (PageIndex.ToString () + '|' + SortExpression + '|' + (int) SortDirection + '|');
 
                        HtmlTextWriter writer = new HtmlTextWriter (sw);
                        RenderGrid (writer);
                        return sw.ToString ();
                }
-               
+
                string ICallbackContainer.GetCallbackScript (IButtonControl control, string argument)
                {
                        return GetCallbackScript (control, argument);
@@ -1728,117 +2147,98 @@ namespace System.Web.UI.WebControls
                
                protected virtual string GetCallbackScript (IButtonControl control, string argument)
                {
-                       if (EnableSortingAndPagingCallbacks)
+                       if (EnableSortingAndPagingCallbacks) {
+                               Page page = Page;
+                               if (page != null)
+                                       page.ClientScript.RegisterForEventValidation (UniqueID, argument);
                                return "javascript:GridView_ClientEvent (\"" + ClientID + "\",\"" + control.CommandName + "$" + control.CommandArgument + "\"); return false;";
-                       else
+                       else
                                return null;
                }
                
-               protected override void OnPreRender (EventArgs e)
+               protected override void OnPagePreLoad (object sender, EventArgs e)
+               {
+                       base.OnPagePreLoad (sender, e);
+
+                       if (Page.IsPostBack && EnableSortingAndPagingCallbacks) {
+                               int page;
+                               if (int.TryParse (Page.Request.Form [ClientID + "_Page"], out page))
+                                       PageIndex = page;
+                               int dir;
+                               if (int.TryParse (Page.Request.Form [ClientID + "_SortDirection"], out dir))
+                                       SortDirection = (SortDirection) dir;
+                               SortExpression = Page.Request.Form [ClientID + "_SortExpression"];
+                       }
+               }
+
+
+               const string onPreRenderScript = @"var {0} = new Object ();
+{0}.pageIndex = {1};
+{0}.sortExp = {2};
+{0}.sortDir = {3};
+{0}.uid = {4};
+{0}.form = {5};
+";
+               protected internal override void OnPreRender (EventArgs e)
                {
                        base.OnPreRender (e);
-                       
-                       if (EnableSortingAndPagingCallbacks)
-                       {
+
+                       if (EnableSortingAndPagingCallbacks) {
                                if (!Page.ClientScript.IsClientScriptIncludeRegistered (typeof(GridView), "GridView.js")) {
                                        string url = Page.ClientScript.GetWebResourceUrl (typeof(GridView), "GridView.js");
                                        Page.ClientScript.RegisterClientScriptInclude (typeof(GridView), "GridView.js", url);
                                }
                                
                                string cgrid = ClientID + "_data";
-                               string script = string.Format ("var {0} = new Object ();\n", cgrid);
-                               script += string.Format ("{0}.pageIndex = {1};\n", cgrid, ClientScriptManager.GetScriptLiteral (PageIndex));
-                               script += string.Format ("{0}.sortExp = {1};\n", cgrid, ClientScriptManager.GetScriptLiteral (SortExpression == null ? "" : SortExpression));
-                               script += string.Format ("{0}.uid = {1};\n", cgrid, ClientScriptManager.GetScriptLiteral (UniqueID));
+                               string script = String.Format (onPreRenderScript,
+                                                       cgrid,
+                                                       ClientScriptManager.GetScriptLiteral (PageIndex),
+                                                       ClientScriptManager.GetScriptLiteral (SortExpression == null ? "" : SortExpression),
+                                                       ClientScriptManager.GetScriptLiteral ((int) SortDirection),
+                                                       ClientScriptManager.GetScriptLiteral (UniqueID),
+                                                       Page.theForm);
+                               
                                Page.ClientScript.RegisterStartupScript (typeof(TreeView), this.UniqueID, script, true);
                                
                                // Make sure the basic script infrastructure is rendered
-                       Page.ClientScript.GetCallbackEventReference (this, "null", "", "null");
+                               Page.ClientScript.GetCallbackEventReference (this, "null", "", "null");
                                Page.ClientScript.GetPostBackClientHyperlink (this, "");
                        }
                }
                
-               protected override void Render (HtmlTextWriter writer)
+               protected internal override void Render (HtmlTextWriter writer)
                {
+                       PrepareControlHierarchy ();
                        if (EnableSortingAndPagingCallbacks)
-                               base.RenderBeginTag (writer);
+                               writer.AddAttribute (HtmlTextWriterAttribute.Id, ClientID + "_div");
+                       writer.RenderBeginTag (HtmlTextWriterTag.Div);
 
                        RenderGrid (writer);
-                       
-                       if (EnableSortingAndPagingCallbacks)
-                               base.RenderEndTag (writer);
+
+                       writer.RenderEndTag ();
                }
                
                void RenderGrid (HtmlTextWriter writer)
                {
-                       switch (GridLines) {
-                               case GridLines.Horizontal:
-                                       writer.AddAttribute (HtmlTextWriterAttribute.Rules, "rows");
-                                       writer.AddAttribute (HtmlTextWriterAttribute.Border, "1");
-                                       break;
-                               case GridLines.Vertical:
-                                       writer.AddAttribute (HtmlTextWriterAttribute.Rules, "cols");
-                                       writer.AddAttribute (HtmlTextWriterAttribute.Border, "1");
-                                       break;
-                               case GridLines.Both:
-                                       writer.AddAttribute (HtmlTextWriterAttribute.Rules, "all");
-                                       writer.AddAttribute (HtmlTextWriterAttribute.Border, "1");
-                                       break;
-                               default:
-                                       writer.AddAttribute (HtmlTextWriterAttribute.Border, "0");
-                                       break;
-                       }
+                       if (table == null)
+                               return;
+
+                       table.Render (writer);
+               }
+
+               PostBackOptions IPostBackContainer.GetPostBackOptions (IButtonControl control)
+               {
+                       if (control == null)
+                               throw new ArgumentNullException ("control");
                        
-                       writer.AddAttribute (HtmlTextWriterAttribute.Cellspacing, "0");
-                       writer.AddStyleAttribute (HtmlTextWriterStyle.BorderCollapse, "collapse");
-                       table.RenderBeginTag (writer);
+                       if (control.CausesValidation)
+                               throw new InvalidOperationException ("A button that causes validation in GridView '" + 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.");
                        
-                       foreach (GridViewRow row in table.Rows)
-                       {
-                               switch (row.RowType) {
-                                       case DataControlRowType.Header:
-                                               if (headerStyle != null)headerStyle.AddAttributesToRender (writer, row);
-                                               break;
-                                       case DataControlRowType.Footer:
-                                               if (footerStyle != null) footerStyle.AddAttributesToRender (writer, row);
-                                               break;
-                                       case DataControlRowType.Pager:
-                                               if (pagerStyle != null) pagerStyle.AddAttributesToRender (writer, row);
-                                               break;
-                                       case DataControlRowType.EmptyDataRow:
-                                               if (emptyDataRowStyle != null) emptyDataRowStyle.AddAttributesToRender (writer, row);
-                                               break;
-                                       default:
-                                               if (rowStyle != null) rowStyle.AddAttributesToRender (writer, row);
-                                               break;
-                               }
+                       PostBackOptions options = new PostBackOptions (this);
+                       options.Argument = control.CommandName + "$" + control.CommandArgument;
+                       options.RequiresJavaScriptProtocol = true;
 
-                               if ((row.RowState & DataControlRowState.Alternate) != 0 && alternatingRowStyle != null)
-                                       alternatingRowStyle.AddAttributesToRender (writer, row);
-                               if ((row.RowState & DataControlRowState.Edit) != 0 && editRowStyle != null)
-                                       editRowStyle.AddAttributesToRender (writer, row);
-                               if ((row.RowState & DataControlRowState.Selected) != 0 && selectedRowStyle != null)
-                                       selectedRowStyle.AddAttributesToRender (writer, row);
-                               
-                               row.RenderBeginTag (writer);
-                               
-                               foreach (TableCell cell in row.Cells) {
-                                       DataControlFieldCell fcell = cell as DataControlFieldCell;
-                                       if (fcell != null) {
-                                               Style cellStyle = null;
-                                               switch (row.RowType) {
-                                                       case DataControlRowType.Header: cellStyle = fcell.ContainingField.HeaderStyle; break;
-                                                       case DataControlRowType.Footer: cellStyle = fcell.ContainingField.FooterStyle; break;
-                                                       default: cellStyle = fcell.ContainingField.ItemStyle; break;
-                                               }
-                                               if (cellStyle != null)
-                                                       cellStyle.AddAttributesToRender (writer, cell);
-                                       }
-                                       cell.Render (writer);
-                               }
-                               row.RenderEndTag (writer);
-                       }
-                       table.RenderEndTag (writer);
+                       return options;
                }
        }
 }