New test.
[mono.git] / mcs / class / System.Web / System.Web.UI.WebControls / GridView.cs
index b4334b32a3d68ed2156eea87bd4b7394c12fcddd..9417999257d932a3bc51b5849ff17b635a7232ac 100644 (file)
@@ -74,6 +74,7 @@ namespace System.Web.UI.WebControls
                TableItemStyle pagerStyle;
                TableItemStyle rowStyle;
                TableItemStyle selectedRowStyle;
+               ArrayList _dataKeyArrayList;
                DataKeyArray keys;
                DataKey oldEditValues;
                AutoGeneratedFieldProperties[] autoFieldProperties;
@@ -98,11 +99,10 @@ namespace System.Web.UI.WebControls
                
                // Control state
                int pageIndex;
-               int pageCount = 0;
                int selectedIndex = -1;
                int editIndex = -1;
                SortDirection sortDirection = SortDirection.Ascending;
-               string sortExpression = string.Empty;
+               string sortExpression;
                
                public GridView ()
                {
@@ -518,16 +518,38 @@ namespace System.Web.UI.WebControls
                                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 virtual int EditIndex {
@@ -535,6 +557,8 @@ namespace System.Web.UI.WebControls
                                return editIndex;
                        }
                        set {
+                               if (value == editIndex)
+                                       return;
                                editIndex = value;
                                RequireBinding ();
                        }
@@ -714,9 +738,10 @@ namespace System.Web.UI.WebControls
                [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
                public virtual int PageCount {
                        get {
-                               if (pageCount != 0) return pageCount;
-                               EnsureDataBound ();
-                               return pageCount;
+                               return ViewState.GetInt ("PageCount", 0);
+                       }
+                       private set {
+                               ViewState ["PageCount"] = value;
                        }
                }
 
@@ -728,6 +753,8 @@ namespace System.Web.UI.WebControls
                                return pageIndex;
                        }
                        set {
+                               if (value == pageIndex)
+                                       return;
                                pageIndex = value;
                                RequireBinding ();
                        }
@@ -807,7 +834,9 @@ namespace System.Web.UI.WebControls
                [BrowsableAttribute (false)]
                public virtual GridViewRowCollection Rows {
                        get {
-                               EnsureDataBound ();
+                               EnsureChildControls ();
+                               if (rows == null)
+                                       rows = new GridViewRowCollection (new ArrayList ());
                                return rows;
                        }
                }
@@ -831,7 +860,7 @@ namespace System.Web.UI.WebControls
                [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
                public virtual DataKey SelectedDataKey {
                        get {
-                               if (DataKeys == null)
+                               if (keys == null)
                                        throw new InvalidOperationException ("DataKeys");
 
                                if (selectedIndex >= 0 && selectedIndex < DataKeys.Count) {
@@ -930,12 +959,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)]
@@ -966,15 +1011,38 @@ namespace System.Web.UI.WebControls
                        return type.IsPrimitive || type == typeof(string) || 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)
                {
                        ArrayList fields = new ArrayList ();
-                       fields.AddRange (Columns);
                        
                        if (AutoGenerateEditButton || AutoGenerateDeleteButton || AutoGenerateSelectButton) {
                                CommandField field = new CommandField ();
@@ -983,6 +1051,8 @@ namespace System.Web.UI.WebControls
                                field.ShowSelectButton = AutoGenerateSelectButton;
                                fields.Add (field);
                        }
+
+                       fields.AddRange (Columns);
                        
                        if (AutoGenerateColumns) {
                                if (useDataSource)
@@ -1072,7 +1142,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;
                }
                
@@ -1080,7 +1149,6 @@ namespace System.Web.UI.WebControls
                {
                        if (Initialized) {
                                RequiresDataBinding = true;
-                               pageCount = -1;
                        }
                }
                
@@ -1091,6 +1159,15 @@ namespace System.Web.UI.WebControls
        
                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) {
@@ -1104,12 +1181,12 @@ namespace System.Web.UI.WebControls
                                        dataSource.CurrentPageIndex = PageIndex;
                                        if (view.CanPage) {
                                                dataSource.AllowServerPaging = true;
-                                               if (view.CanRetrieveTotalRowCount)
+                                               if (SelectArguments.RetrieveTotalRowCount)
                                                        dataSource.VirtualCount = SelectArguments.TotalRowCount;
                                        }
                                }
                                
-                               pageCount = dataSource.PageCount;
+                               PageCount = dataSource.PageCount;
                        }
                        else
                        {
@@ -1122,14 +1199,15 @@ namespace System.Web.UI.WebControls
                                }
                        }
 
+                       if (dataSource.DataSourceCount == 0)
+                               return 0;
+
                        bool showPager = AllowPaging && (PageCount > 1);
                        
-                       Controls.Clear ();
                        table = CreateChildTable ();
                        Controls.Add (table);
                                
                        ArrayList list = new ArrayList ();
-                       ArrayList keyList = new ArrayList ();
                        
                        // Creates the set of fields to show
                        
@@ -1148,11 +1226,17 @@ namespace System.Web.UI.WebControls
                        if (showPager && PagerSettings.Position == PagerPosition.Top || PagerSettings.Position == PagerPosition.TopAndBottom) {
                                topPagerRow = CreatePagerRow (fields.Length, dataSource);
                                table.Rows.Add (topPagerRow);
+                               OnRowCreated (new GridViewRowEventArgs (topPagerRow));
                        }
 
                        GridViewRow headerRow = CreateRow (0, 0, DataControlRowType.Header, DataControlRowState.Normal);
                        table.Rows.Add (headerRow);
                        InitializeRow (headerRow, fields);
+                       OnRowCreated (new GridViewRowEventArgs (headerRow));
+                       if (dataBinding) {
+                               headerRow.DataBind ();
+                               OnRowDataBound (new GridViewRowEventArgs (headerRow));
+                       }
                        
                        foreach (object obj in dataSource) {
                                DataControlRowState rstate = GetRowState (list.Count);
@@ -1161,36 +1245,45 @@ namespace System.Web.UI.WebControls
                                list.Add (row);
                                table.Rows.Add (row);
                                InitializeRow (row, fields);
+                               OnRowCreated (new GridViewRowEventArgs (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 {
-                                       if (EditIndex == row.RowIndex)
-                                               oldEditValues = new DataKey (new OrderedDictionary ());
-                                       keyList.Add (new DataKey (new OrderedDictionary (), DataKeyNames));
-                               }
+                                       DataKeyArrayList.Add (new DataKey (CreateRowDataKey (row), DataKeyNames));
+                               } 
 
                                if (list.Count >= PageSize)
                                        break;
                        }
-                       
-                       if (list.Count == 0)
-                               table.Rows.Add (CreateEmptyrRow (fields.Length));
+
+                       if (list.Count == 0) {
+                               GridViewRow emptyRow = CreateEmptyrRow (fields.Length);
+                               table.Rows.Add (emptyRow);
+                               OnRowCreated (new GridViewRowEventArgs (emptyRow));
+                               if (dataBinding) {
+                                       emptyRow.DataBind ();
+                                       OnRowDataBound (new GridViewRowEventArgs (emptyRow));
+                               }
+                       }
 
                        GridViewRow footerRow = CreateRow (0, 0, DataControlRowType.Footer, DataControlRowState.Normal);
                        table.Rows.Add (footerRow);
                        InitializeRow (footerRow, fields);
+                       OnRowCreated (new GridViewRowEventArgs (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);
+                               OnRowCreated (new GridViewRowEventArgs (bottomPagerRow));
                        }
 
                        rows = new GridViewRowCollection (list);
-                       keys = new DataKeyArray (keyList);
 
                        return dataSource.DataSourceCount;
                }
@@ -1227,7 +1320,7 @@ namespace System.Web.UI.WebControls
                        if (pagerTemplate != null)
                                pagerTemplate.InstantiateIn (cell);
                        else
-                               cell.Controls.Add (PagerSettings.CreatePagerControl (dataSource.CurrentPageIndex, dataSource.PageCount, pagerStyle));
+                               cell.Controls.Add (PagerSettings.CreatePagerControl (dataSource.CurrentPageIndex, dataSource.PageCount));
                        
                        row.Cells.Add (cell);
                }
@@ -1326,23 +1419,11 @@ 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);
                }
                
                protected internal override void PerformDataBinding (IEnumerable data)
@@ -1350,10 +1431,75 @@ namespace System.Web.UI.WebControls
                        base.PerformDataBinding (data);
                }
 
-               [MonoTODO]
                protected internal virtual void PrepareControlHierarchy ()
                {
-                       throw new NotImplementedException ();
+                       if (table == null)
+                               return;
+                       
+                       table.Caption = Caption;
+                       table.CaptionAlign = CaptionAlign;
+                       
+                       foreach (GridViewRow row in table.Rows) {
+                               switch (row.RowType) {
+                               case DataControlRowType.Header:
+                                       if (headerStyle != null && !headerStyle.IsEmpty)
+                                               row.ControlStyle.CopyFrom(headerStyle);
+                                       row.Visible = ShowHeader;
+                                       break;
+                               case DataControlRowType.Footer:
+                                       if (footerStyle != null && !footerStyle.IsEmpty)
+                                               row.ControlStyle.CopyFrom (footerStyle);
+                                       row.Visible = ShowFooter;
+                                       break;
+                               case DataControlRowType.Pager:
+                                       if (pagerStyle != null && !pagerStyle.IsEmpty)
+                                               row.ControlStyle.CopyFrom (pagerStyle);
+                                       break;
+                               case DataControlRowType.EmptyDataRow:
+                                       if (emptyDataRowStyle != null && !emptyDataRowStyle.IsEmpty)
+                                               row.ControlStyle.CopyFrom (emptyDataRowStyle);
+                                       break;
+                               case DataControlRowType.DataRow:
+                                       if (rowStyle != null && !rowStyle.IsEmpty)
+                                               row.ControlStyle.CopyFrom (rowStyle);
+                                       if ((row.RowState & DataControlRowState.Alternate) != 0 && alternatingRowStyle != null && !alternatingRowStyle.IsEmpty)
+                                               row.ControlStyle.CopyFrom (alternatingRowStyle);
+                                       if ((row.RowState & DataControlRowState.Selected) != 0 && selectedRowStyle != null && !selectedRowStyle.IsEmpty)
+                                               row.ControlStyle.CopyFrom (selectedRowStyle);
+                                       if ((row.RowState & DataControlRowState.Edit) != 0 && editRowStyle != null && !editRowStyle.IsEmpty)
+                                               row.ControlStyle.CopyFrom (editRowStyle);
+                                       break;
+                               default:
+                                       break;
+                               }
+
+                               foreach (TableCell cell in row.Cells) {
+                                       DataControlFieldCell fcell = cell as DataControlFieldCell;
+                                       if (fcell != null) {
+                                               DataControlField field = fcell.ContainingField;
+                                               switch (row.RowType) {
+                                               case DataControlRowType.Header:
+                                                       if (field.HeaderStyleCreated && !field.HeaderStyle.IsEmpty)
+                                                               cell.ControlStyle.CopyFrom (field.HeaderStyle);
+                                                       break;
+                                               case DataControlRowType.Footer:
+                                                       if (field.FooterStyleCreated && !field.FooterStyle.IsEmpty)
+                                                               cell.ControlStyle.CopyFrom (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.CopyFrom (field.ItemStyle);
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
                }
                
                protected internal override void OnInit (EventArgs e)
@@ -1391,6 +1537,7 @@ namespace System.Web.UI.WebControls
                                                param = row.RowIndex.ToString();
                                }
                                ProcessEvent (args.CommandName, param);
+                               return true;
                        }
                        return base.OnBubbleEvent (source, e);
                }
@@ -1424,13 +1571,15 @@ namespace System.Web.UI.WebControls
                                        newIndex = PageCount - 1;
                                        break;
                                case DataControlCommands.NextPageCommandArgument:
-                                       if (PageIndex < PageCount - 1) newIndex = PageIndex + 1;
+                                       newIndex = PageIndex + 1;
                                        break;
                                case DataControlCommands.PreviousPageCommandArgument:
-                                       if (PageIndex > 0) newIndex = PageIndex - 1;
+                                       newIndex = PageIndex - 1;
                                        break;
                                default:
-                                       newIndex = int.Parse (param) - 1;
+                                       int paramIndex = 0;
+                                       int.TryParse (param, out paramIndex);
+                                       newIndex = paramIndex - 1;
                                        break;
                                }
                                ShowPage (newIndex);
@@ -1482,15 +1631,10 @@ namespace System.Web.UI.WebControls
                
                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);
                }
                
@@ -1500,9 +1644,12 @@ namespace System.Web.UI.WebControls
                        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);
                }
@@ -1549,12 +1696,12 @@ namespace System.Web.UI.WebControls
                [MonoTODO ("Support two-way binding expressions")]
                public virtual void UpdateRow (int rowIndex, bool causesValidation)
                {
-                       if (causesValidation)
+                       if (causesValidation && Page != null)
                                Page.Validate ();
                        
                        if (rowIndex != EditIndex) throw new NotSupportedException ();
-                       
-                       currentEditOldValues = oldEditValues.Values;
+
+                       currentEditOldValues = OldEditValues.Values;
 
                        GridViewRow row = Rows [rowIndex];
                        currentEditRowKeys = DataKeys [rowIndex].Values;
@@ -1564,8 +1711,10 @@ namespace System.Web.UI.WebControls
                        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));
+                               if (view == null)
+                                       throw new HttpException ("The DataSourceView associated to data bound control was null");
+                               if(view.CanUpdate)
+                                       view.Update (currentEditRowKeys, currentEditNewValues, currentEditOldValues, new DataSourceViewOperationCallback (UpdateCallback));
                        } else
                                EndRowEdit ();
                }
@@ -1593,7 +1742,7 @@ namespace System.Web.UI.WebControls
                        if (!args.Cancel) {
                                RequireBinding ();
                                DataSourceView view = GetData ();
-                               if (view != null)
+                               if (view != null && view.CanDelete)
                                        view.Delete (currentEditRowKeys, currentEditNewValues, new DataSourceViewOperationCallback (DeleteCallback));
                                else {
                                        GridViewDeletedEventArgs dargs = new GridViewDeletedEventArgs (0, null, currentEditRowKeys, currentEditNewValues);
@@ -1624,22 +1773,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];
-                       DataKeyNames = (string []) state [7];
+                       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, DataKeyNames
+                       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();
@@ -1662,7 +1850,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());
@@ -1674,8 +1862,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];
@@ -1684,7 +1870,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--) {
@@ -1704,8 +1890,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 ();
@@ -1716,7 +1902,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]);
@@ -1728,8 +1913,6 @@ 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]);
                }
                
                void ICallbackEventHandler.RaiseCallbackEvent (string eventArgs)
@@ -1737,24 +1920,15 @@ namespace System.Web.UI.WebControls
                        RaiseCallbackEvent (eventArgs);
                }
                
-               string callbackResult;
                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 ();
-                       
-                       StringWriter sw = new StringWriter ();
-                       sw.Write (PageIndex.ToString() + '|' + SortExpression + '|');
-
-                       HtmlTextWriter writer = new HtmlTextWriter (sw);
-                       RenderGrid (writer);
-                       callbackResult = sw.ToString ();
+                       RaisePostBackEvent (clientData[3]);
+                       DataBind ();
                }
                
                string ICallbackEventHandler.GetCallbackResult ()
@@ -1764,7 +1938,14 @@ namespace System.Web.UI.WebControls
 
                protected virtual string GetCallbackResult ()
                {
-                       return callbackResult;
+                       PrepareControlHierarchy ();
+                       
+                       StringWriter sw = new StringWriter ();
+                       sw.Write (PageIndex.ToString () + '|' + SortExpression + '|' + (int) SortDirection + '|');
+
+                       HtmlTextWriter writer = new HtmlTextWriter (sw);
+                       RenderGrid (writer);
+                       return sw.ToString ();
                }
 
                string ICallbackContainer.GetCallbackScript (IButtonControl control, string argument)
@@ -1780,10 +1961,19 @@ namespace System.Web.UI.WebControls
                                return null;
                }
                
-               [MonoTODO]
                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"];
+                       }
                }
                
                protected internal override void OnPreRender (EventArgs e)
@@ -1801,6 +1991,7 @@ namespace System.Web.UI.WebControls
                                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}.sortDir = {1};\n", cgrid, ClientScriptManager.GetScriptLiteral ((int) SortDirection));
                                script += string.Format ("{0}.uid = {1};\n", cgrid, ClientScriptManager.GetScriptLiteral (UniqueID));
                                Page.ClientScript.RegisterStartupScript (typeof(TreeView), this.UniqueID, script, true);
                                
@@ -1812,6 +2003,8 @@ namespace System.Web.UI.WebControls
 
                protected internal override void Render (HtmlTextWriter writer)
                {
+                       PrepareControlHierarchy ();
+
                        if (EnableSortingAndPagingCallbacks)
                                writer.AddAttribute (HtmlTextWriterAttribute.Id, ClientID);
                        writer.RenderBeginTag (HtmlTextWriterTag.Div);
@@ -1826,66 +2019,22 @@ namespace System.Web.UI.WebControls
                        if (table == null)
                                return;
 
-                       table.Caption = Caption;
-                       table.CaptionAlign = CaptionAlign;
-                       table.RenderBeginTag (writer);
-                       
-                       foreach (GridViewRow row in table.Rows)
-                       {
-                               switch (row.RowType) {
-                               case DataControlRowType.Header:
-                                       if (!ShowHeader) continue;
-                                       if (headerStyle != null)headerStyle.AddAttributesToRender (writer, row);
-                                       break;
-                               case DataControlRowType.Footer:
-                                       if (!ShowFooter) continue;
-                                       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:
-                                       break;
-                               }
-
-                               if ((row.RowState & DataControlRowState.Normal) != 0 && rowStyle != null)
-                                       rowStyle.AddAttributesToRender (writer, row);
-                               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);
+                       table.Render (writer);
                }
 
-               [MonoTODO]
                PostBackOptions IPostBackContainer.GetPostBackOptions (IButtonControl control)
                {
-                       PostBackOptions pbo = new PostBackOptions (this, control.CommandName + "$" + control.CommandArgument);
-                       return pbo;
+                       if (control == null)
+                               throw new ArgumentNullException ("control");
+                       
+                       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.");
+                       
+                       PostBackOptions options = new PostBackOptions (this);
+                       options.Argument = control.CommandName + "$" + control.CommandArgument;
+                       options.RequiresJavaScriptProtocol = true;
+
+                       return options;
                }
        }
 }