2009-01-28 Ivan N. Zlatev <contact@i-nz.net>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / DataGridView.cs
index 12865d8e11994d821e79a8c6bced8f4b131f8837..462552804f86cbab147c53d7a1a976c660eb9e20 100644 (file)
@@ -21,6 +21,7 @@
 //
 // Author:
 //     Pedro Martínez Juliá <pedromj@gmail.com>
+//     Ivan N. Zlatev <contact@i-nz.net>
 //
 
 #if NET_2_0
@@ -117,7 +118,10 @@ namespace System.Windows.Forms {
                private HScrollBar horizontalScrollBar;
                private VScrollBar verticalScrollBar;
                private Control editingControl;
-
+               private bool is_autogenerating_columns = false;
+               private bool is_binding = false;
+               private bool new_row_editing = false;
+               
                // These are used to implement selection behaviour with SHIFT pressed.
                private int selected_row = -1;
                private int selected_column = -1;
@@ -137,6 +141,13 @@ namespace System.Windows.Forms {
                DataGridViewHeaderCell pressed_header_cell;
                DataGridViewHeaderCell entered_header_cell;
 
+               // For column/row resizing via mouse
+               private bool column_resize_active = false;
+               private bool row_resize_active = false;
+               private int resize_band = -1;
+               private int resize_band_start = 0;
+               private int resize_band_delta = 0;
+               
                public DataGridView ()
                {
                        SetStyle (ControlStyles.Opaque, true);
@@ -163,7 +174,7 @@ namespace System.Windows.Forms {
                        backColor = Control.DefaultBackColor;
                        backgroundColor = SystemColors.AppWorkspace;
                        borderStyle = BorderStyle.FixedSingle;
-                       cellBorderStyle = DataGridViewCellBorderStyle.None;
+                       cellBorderStyle = DataGridViewCellBorderStyle.Single;
                        clipboardCopyMode = DataGridViewClipboardCopyMode.EnableWithAutoHeaderText;
                        columnHeadersBorderStyle = DataGridViewHeaderBorderStyle.Single;
                        columnHeadersDefaultCellStyle = new DataGridViewCellStyle();
@@ -179,6 +190,7 @@ namespace System.Windows.Forms {
                        columnHeadersVisible = true;
                        columns = CreateColumnsInstance();
                        columns.CollectionChanged += OnColumnCollectionChanged;
+                       currentCellAddress = new Point (-1, -1);
                        dataMember = String.Empty;
                        defaultCellStyle = new DataGridViewCellStyle();
                        defaultCellStyle.BackColor = SystemColors.Window;
@@ -189,6 +201,8 @@ namespace System.Windows.Forms {
                        defaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft;
                        defaultCellStyle.WrapMode = DataGridViewTriState.False;
                        editMode = DataGridViewEditMode.EditOnKeystrokeOrF2;
+                       firstDisplayedScrollingColumnHiddenWidth = 0;
+                       isCurrentCellDirty = false;
                        multiSelect = true;
                        readOnly = false;
                        rowHeadersBorderStyle = DataGridViewHeaderBorderStyle.Single;
@@ -252,7 +266,11 @@ namespace System.Windows.Forms {
 
                [DefaultValue (true)]
                public bool AllowUserToAddRows {
-                       get { return allowUserToAddRows; }
+                       get { 
+                               if (allowUserToAddRows && DataManager != null)
+                                       return DataManager.AllowNew;
+                               return allowUserToAddRows;
+                       }
                        set {
                                if (allowUserToAddRows != value) {
                                        allowUserToAddRows = value;
@@ -265,7 +283,11 @@ namespace System.Windows.Forms {
 
                [DefaultValue (true)]
                public bool AllowUserToDeleteRows {
-                       get { return allowUserToDeleteRows; }
+                       get {
+                               if (allowUserToDeleteRows && DataManager != null)
+                                       return DataManager.AllowRemove;
+                               return allowUserToDeleteRows;
+                       }
                        set {
                                if (allowUserToDeleteRows != value) {
                                        allowUserToDeleteRows = value;
@@ -476,8 +498,60 @@ namespace System.Windows.Forms {
                        get { return cellBorderStyle; }
                        set {
                                if (cellBorderStyle != value) {
+                                       if (value == DataGridViewCellBorderStyle.Custom)
+                                               throw new ArgumentException ("CellBorderStyle cannot be set to Custom.");
+
                                        cellBorderStyle = value;
-                                       OnCellBorderStyleChanged(EventArgs.Empty);
+
+                                       DataGridViewAdvancedBorderStyle border = new DataGridViewAdvancedBorderStyle ();
+
+                                       switch (cellBorderStyle) {
+                                               case DataGridViewCellBorderStyle.Single:
+                                                       border.All = DataGridViewAdvancedCellBorderStyle.Single;
+                                                       break;
+                                               case DataGridViewCellBorderStyle.Raised:
+                                               case DataGridViewCellBorderStyle.RaisedVertical:
+                                                       border.Bottom = DataGridViewAdvancedCellBorderStyle.None;
+                                                       border.Top = DataGridViewAdvancedCellBorderStyle.None;
+                                                       border.Left = DataGridViewAdvancedCellBorderStyle.Outset;
+                                                       border.Right = DataGridViewAdvancedCellBorderStyle.Outset;
+                                                       break;
+                                               case DataGridViewCellBorderStyle.Sunken:
+                                                       border.All = DataGridViewAdvancedCellBorderStyle.Inset;
+                                                       break;
+                                               case DataGridViewCellBorderStyle.None:
+                                                       border.All = DataGridViewAdvancedCellBorderStyle.None;
+                                                       break;
+                                               case DataGridViewCellBorderStyle.SingleVertical:
+                                                       border.Bottom = DataGridViewAdvancedCellBorderStyle.None;
+                                                       border.Top = DataGridViewAdvancedCellBorderStyle.None;
+                                                       border.Left = DataGridViewAdvancedCellBorderStyle.None;
+                                                       border.Right = DataGridViewAdvancedCellBorderStyle.Single;
+                                                       break;
+                                               case DataGridViewCellBorderStyle.SunkenVertical:
+                                                       border.Bottom = DataGridViewAdvancedCellBorderStyle.None;
+                                                       border.Top = DataGridViewAdvancedCellBorderStyle.None;
+                                                       border.Left = DataGridViewAdvancedCellBorderStyle.Inset;
+                                                       border.Right = DataGridViewAdvancedCellBorderStyle.Inset;
+                                                       break;
+                                               case DataGridViewCellBorderStyle.SingleHorizontal:
+                                               case DataGridViewCellBorderStyle.SunkenHorizontal:
+                                                       border.Bottom = DataGridViewAdvancedCellBorderStyle.Inset;
+                                                       border.Top = DataGridViewAdvancedCellBorderStyle.Inset;
+                                                       border.Left = DataGridViewAdvancedCellBorderStyle.None;
+                                                       border.Right = DataGridViewAdvancedCellBorderStyle.None;
+                                                       break;
+                                               case DataGridViewCellBorderStyle.RaisedHorizontal:
+                                                       border.Bottom = DataGridViewAdvancedCellBorderStyle.Outset;
+                                                       border.Top = DataGridViewAdvancedCellBorderStyle.Outset;
+                                                       border.Left = DataGridViewAdvancedCellBorderStyle.None;
+                                                       border.Right = DataGridViewAdvancedCellBorderStyle.None;
+                                                       break;
+                                       }
+                                       
+                                       advancedCellBorderStyle = border;
+                                       
+                                       OnCellBorderStyleChanged (EventArgs.Empty);
                                }
                        }
                }
@@ -606,11 +680,12 @@ namespace System.Windows.Forms {
                                /// to the data cache, or the new cell is in a hidden
                                /// row.
                                /////////////////////////////////////////////////////
-                               if (value.DataGridView != this) {
+                               if (value == null)
+                                       MoveCurrentCell (-1, -1, true, false, false, true);
+                               else if (value.DataGridView != this)
                                        throw new ArgumentException("The cell is not in this DataGridView.");
-                               }
-                               currentCell = value;
-                               currentRow = currentCell.OwningRow;
+                               else
+                                       MoveCurrentCell (value.OwningColumn.Index, value.OwningRow.Index, true, false, false, true);
                        }
                }
 
@@ -621,7 +696,11 @@ namespace System.Windows.Forms {
 
                [Browsable (false)]
                public DataGridViewRow CurrentRow {
-                       get { return currentRow; }
+                       get { 
+                               if (currentCell != null)
+                                       return currentCell.OwningRow;
+                               return null;
+                       }
                }
 
                [DefaultValue ("")]
@@ -630,12 +709,9 @@ namespace System.Windows.Forms {
                        get { return dataMember; }
                        set {
                                if (dataMember != value) {
-                                       ClearBinding ();
-                                       
                                        dataMember = value;
+                                       ReBind ();
                                        OnDataMemberChanged(EventArgs.Empty);
-                                       
-                                       DoBinding ();
                                }
                        }
                }
@@ -646,24 +722,30 @@ namespace System.Windows.Forms {
                public object DataSource {
                        get { return dataSource; }
                        set {
-                               if (dataSource != value) {
-                                       /* The System.Windows.Forms.DataGridView class supports the standard Windows Forms data-binding model. This means the data source can be of any type that implements:
-                                        - the System.Collections.IList interface, including one-dimensional arrays.
-                                        - the System.ComponentModel.IListSource interface, such as the System.Data.DataTable and System.Data.DataSet classes.
-                                        - the System.ComponentModel.IBindingList interface, such as the System.ComponentModel.Collections.BindingList<> class.
-                                        - the System.ComponentModel.IBindingListView interface, such as the System.Windows.Forms.BindingSource class.
-                                       */
-                                       if (!(value == null || value is IList || value is IListSource || value is IBindingList || value is IBindingListView)) {
-                                               throw new NotSupportedException("Type cant be binded.");
-                                       }
-                                               
-                                       ClearBinding ();
-                                       
-                                       dataSource = value;
-                                       OnDataSourceChanged (EventArgs.Empty);
+                               /* The System.Windows.Forms.DataGridView class supports the standard Windows Forms data-binding model. This means the data source can be of any type that implements:
+                                - the System.Collections.IList interface, including one-dimensional arrays.
+                                - the System.ComponentModel.IListSource interface, such as the System.Data.DataTable and System.Data.DataSet classes.
+                                - the System.ComponentModel.IBindingList interface, such as the System.ComponentModel.Collections.BindingList<> class.
+                                - the System.ComponentModel.IBindingListView interface, such as the System.Windows.Forms.BindingSource class.
+                               */
+                               if (!(value == null || value is IList || value is IListSource || value is IBindingList || value is IBindingListView))
+                                       throw new NotSupportedException ("Type cannot be bound.");
                                        
-                                       DoBinding ();
+                               dataSource = value;
+                               ReBind ();
+                               OnDataSourceChanged (EventArgs.Empty);
+                       }
+               }
+
+               internal CurrencyManager DataManager {
+                       get {
+                               if (DataSource != null && BindingContext != null) {
+                                       string dataMember = DataMember;
+                                       if (dataMember == null)
+                                               dataMember = String.Empty;
+                                       return (CurrencyManager) this.BindingContext[DataSource, dataMember];
                                }
+                               return null;
                        }
                }
 
@@ -874,7 +956,7 @@ namespace System.Windows.Forms {
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                public int NewRowIndex {
                        get {
-                               if (!allowUserToAddRows) {
+                               if (!AllowUserToAddRows || ColumnCount == 0) {
                                        return -1;
                                }
                                return rows.Count - 1;
@@ -915,7 +997,7 @@ namespace System.Windows.Forms {
                                if (value < 0) {
                                        throw new ArgumentException("RowCount must be >= 0.");
                                }
-                               if (value < 1 && allowUserToAddRows) {
+                               if (value < 1 && AllowUserToAddRows) {
                                        throw new ArgumentException("RowCount must be >= 1 if AllowUserToAddRows is true.");
                                }
                                if (dataSource != null) {
@@ -933,7 +1015,7 @@ namespace System.Windows.Forms {
                                                ColumnCount = 1;
 
                                        for (int i = rows.Count; i < value; i++) {
-                                               DataGridViewRow row = (DataGridViewRow) RowTemplate.Clone ();
+                                               DataGridViewRow row = (DataGridViewRow) RowTemplateFull;
                                                rows.AddInternal (row, false);
                                                
                                                foreach (DataGridViewColumn col in columns)
@@ -1029,6 +1111,7 @@ namespace System.Windows.Forms {
                        }
                }
 
+               // RowTemplate is just the row, it does not contain Cells
                [Browsable (true)]
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
                public DataGridViewRow RowTemplate {
@@ -1044,6 +1127,8 @@ namespace System.Windows.Forms {
                        }
                }
 
+               // Take the RowTemplate, clone it, and add Cells
+               // Note this is not stored, so you don't need to Clone it
                internal DataGridViewRow RowTemplateFull {
                        get {
                                DataGridViewRow row = (DataGridViewRow) RowTemplate.Clone ();
@@ -2164,13 +2249,13 @@ namespace System.Windows.Forms {
                public virtual bool BeginEdit (bool selectAll) {
                        if (currentCell == null || currentCell.IsInEditMode)
                                return false;
-                       
+
                        if (currentCell.RowIndex >= 0) {
                                if ((currentCell.InheritedState & DataGridViewElementStates.ReadOnly) == DataGridViewElementStates.ReadOnly) {
                                        return false;
                                }
                        }
-                       
+
                        DataGridViewCell cell = currentCell;
                        Type editType = cell.EditType;
                        
@@ -2183,7 +2268,7 @@ namespace System.Windows.Forms {
 
                        if (e.Cancel)
                                return false;
-                               
+
                        cell.SetIsInEditMode (true);
                        
                        // The cell has an editing control we need to setup
@@ -2209,11 +2294,17 @@ namespace System.Windows.Forms {
                                cell.PositionEditingControl (true, true, this.GetCellDisplayRectangle (cell.ColumnIndex, cell.RowIndex, false), bounds, style, false, false, (columns [cell.ColumnIndex].DisplayIndex == 0), (cell.RowIndex == 0));
 
                                // Show the editing control
-                               EditingControlInternal.Visible = true;
+                               if (EditingControlInternal != null)
+                                       EditingControlInternal.Visible = true;
 
-                               // Allow editing control to set focus as needed
-                               (EditingControlInternal as IDataGridViewEditingControl).PrepareEditingControlForEdit (selectAll);
-                               
+                               IDataGridViewEditingControl dgvEditingControl = (IDataGridViewEditingControl) EditingControlInternal;
+                               if (dgvEditingControl != null) {
+                                       dgvEditingControl.EditingControlDataGridView = this;
+                                       dgvEditingControl.EditingControlRowIndex = currentCell.OwningRow.Index;
+                                       dgvEditingControl.ApplyCellStyleToEditingControl (style);
+                                       dgvEditingControl.PrepareEditingControlForEdit (selectAll);
+                                       dgvEditingControl.EditingControlFormattedValue = currentCell.EditedFormattedValue;
+                               }
                                return true;
                        }
 
@@ -2226,10 +2317,21 @@ namespace System.Windows.Forms {
 
                public bool CancelEdit ()
                {
-                       if (currentCell != null && currentCell.IsInEditMode) {
-                               currentCell.SetIsInEditMode (false);
-                               currentCell.DetachEditingControl ();
-                               OnCellEndEdit (new DataGridViewCellEventArgs (currentCell.ColumnIndex, currentCell.RowIndex));
+                       if (currentCell != null) {
+                               if (currentCell.IsInEditMode) {
+                                       currentCell.SetIsInEditMode (false);
+                                       currentCell.DetachEditingControl ();
+                               }
+
+                               if (currentCell.RowIndex == NewRowIndex) {
+                                       if (DataManager != null)
+                                               DataManager.CancelCurrentEdit ();
+
+                                       new_row_editing = false;
+                                       PrepareEditingRow (false, false);
+                                       MoveCurrentCell (currentCell.ColumnIndex, NewRowIndex, true, false, false, true);
+                                       OnUserDeletedRow (new DataGridViewRowEventArgs (EditingRow));
+                               }
                        }
 
                        return true;
@@ -2247,14 +2349,21 @@ namespace System.Windows.Forms {
 
                public bool CommitEdit (DataGridViewDataErrorContexts context)
                {
-                       if (currentCell != null && currentCell.IsInEditMode) {
-                               IDataGridViewEditingControl ctrl = EditingControl as IDataGridViewEditingControl;
-                               ctrl.GetEditingControlFormattedValue (DataGridViewDataErrorContexts.Commit);
-                               currentCell.Value = ctrl.GetEditingControlFormattedValue (DataGridViewDataErrorContexts.Commit);
+                       if (currentCell == null)
                                return true;
+
+                       try {
+                               currentCell.Value = currentCell.ParseFormattedValue (currentCell.EditedFormattedValue, 
+                                                                                    currentCell.InheritedStyle, null, null);
+                       } catch (Exception e) {
+                               DataGridViewDataErrorEventArgs args = new DataGridViewDataErrorEventArgs (e, currentCell.ColumnIndex, currentCell.RowIndex, 
+                                                                                                         DataGridViewDataErrorContexts.Commit);
+                               OnDataError (false, args);
+                               if (args.ThrowException)
+                                       throw e;
+                               return false;
                        }
-                       
-                       return false;
+                       return true;
                }
 
                [MonoTODO ("Always includes partial columns")]
@@ -2271,45 +2380,59 @@ namespace System.Windows.Forms {
                        return result;
                }
 
-               [MonoTODO ("Always includes partial rows")]
                public int DisplayedRowCount (bool includePartialRow)
                {
                        int result = 0;
-                       
-                       for (int i = first_row_index; i < Rows.Count; i++)
-                               if (Rows[i].Displayed)
+                       int rowTop = 0;
+
+                       if (ColumnHeadersVisible)
+                               rowTop += ColumnHeadersHeight;
+
+                       for (int index = first_row_index; index < Rows.Count; index++) {
+                               DataGridViewRow row = GetRowInternal (index);
+                               if (rowTop + row.Height <= ClientSize.Height) {
                                        result++;
-                               else
+                                       rowTop += row.Height;
+                               } else {
+                                       if (includePartialRow)
+                                               result++;
                                        break;
+                               }
+                       }
                                        
                        return result;
                }
 
                public bool EndEdit ()
                {
-                       if (currentCell != null && currentCell.IsInEditMode) {
-                               if (EditingControl != null) {
-                                       IDataGridViewEditingControl ctrl = EditingControl as IDataGridViewEditingControl;
-                                       ctrl.GetEditingControlFormattedValue (DataGridViewDataErrorContexts.Commit);
-                                       currentCell.Value = ctrl.GetEditingControlFormattedValue (DataGridViewDataErrorContexts.Commit);
-                                       
-                                       currentCell.SetIsInEditMode (false);
-                                       currentCell.DetachEditingControl ();    
-                               } else if (currentCell is IDataGridViewEditingCell) {
-                                       currentCell.Value = (currentCell as IDataGridViewEditingCell).EditingCellFormattedValue;
-                                       currentCell.SetIsInEditMode (false);
-                               }
-
-                               OnCellEndEdit (new DataGridViewCellEventArgs (currentCell.ColumnIndex, currentCell.RowIndex));
-                       }
-                       
-                       return true;
+                       return EndEdit (DataGridViewDataErrorContexts.Commit);
                }
 
                [MonoTODO ("Does not use context parameter")]
                public bool EndEdit (DataGridViewDataErrorContexts context)
                {
-                       return EndEdit ();
+                       if (currentCell == null || !currentCell.IsInEditMode)
+                               return true;
+
+                       if (!CommitEdit (context)) {
+                               if (DataManager != null)
+                                       DataManager.EndCurrentEdit ();
+                               if (EditingControl != null)
+                                       EditingControl.Focus ();
+                               return false;
+                       }
+
+                       currentCell.SetIsInEditMode (false);
+                       currentCell.DetachEditingControl ();
+                       OnCellEndEdit (new DataGridViewCellEventArgs (currentCell.ColumnIndex, currentCell.RowIndex));
+                       Focus ();
+                       if (currentCell.RowIndex == NewRowIndex) {
+                               new_row_editing = false;
+                               editing_row = null; // editing row becomes a real row
+                               PrepareEditingRow (true, false); // add a new editing row
+                               MoveCurrentCell (currentCell.ColumnIndex, NewRowIndex, true, false, false, true);
+                       }
+                       return true;
                }
 
                public int GetCellCount (DataGridViewElementStates includeFilter) {
@@ -2747,7 +2870,8 @@ namespace System.Windows.Forms {
                }
 
                public virtual void NotifyCurrentCellDirty (bool dirty) {
-                       throw new NotImplementedException();
+                       if (currentCell != null)
+                               InvalidateCell (currentCell);
                }
 
                public bool RefreshEdit ()
@@ -2820,40 +2944,45 @@ namespace System.Windows.Forms {
                                throw new ArgumentNullException ("dataGridViewColumn");
                        if (dataGridViewColumn.DataGridView != this)
                                throw new ArgumentException ("dataGridViewColumn");
-                       // XXX: This is thrown too much, disable for now..
-                       //if (DataSource != null && !dataGridViewColumn.IsDataBound)
-                       //        throw new ArgumentException ("dataGridViewColumn");
-                       if (VirtualMode && !dataGridViewColumn.IsDataBound)
-                               throw new InvalidOperationException ();
+
+                       if (!EndEdit ())
+                               return;
 
                        if (SortedColumn != null)
                                SortedColumn.HeaderCell.SortGlyphDirection = SortOrder.None;
 
-                       EndEdit ();
-                       
-                       // Figure out if this is a numeric sort or text sort
-                       bool is_numeric = true;
-                       double n;
+                       sortedColumn = dataGridViewColumn;
+                       sortOrder = direction == ListSortDirection.Ascending ? SortOrder.Ascending : SortOrder.Descending;
                        
-                       foreach (DataGridViewRow row in Rows) {
-                               object val = row.Cells[dataGridViewColumn.Index].Value;
+                       if (Rows.Count == 0)
+                               return;
+
+                       if (dataGridViewColumn.IsDataBound) {
+                               IBindingList bindingList = DataManager.List as IBindingList;
+                               if (bindingList != null && bindingList.SupportsSorting) {
+                                       bindingList.ApplySort (DataManager.GetItemProperties()[dataGridViewColumn.DataPropertyName], direction);
+                                       dataGridViewColumn.HeaderCell.SortGlyphDirection = sortOrder;
+                               }
+                       } else {
+                               // Figure out if this is a numeric sort or text sort
+                               bool is_numeric = true;
+                               double n;
                                
-                               if (val != null && !double.TryParse (val.ToString (), out n)) {
-                                       is_numeric = false;
-                                       break;
+                               foreach (DataGridViewRow row in Rows) {
+                                       object val = row.Cells[dataGridViewColumn.Index].Value;
+                                       
+                                       if (val != null && !double.TryParse (val.ToString (), out n)) {
+                                               is_numeric = false;
+                                               break;
+                                       }
                                }
+                               
+                               ColumnSorter sorter = new ColumnSorter (dataGridViewColumn, direction, is_numeric);
+                               Rows.Sort (sorter);
+                               dataGridViewColumn.HeaderCell.SortGlyphDirection = sortOrder;
                        }
-                       
-                       ColumnSorter sorter = new ColumnSorter (dataGridViewColumn, direction, is_numeric);
-                       Rows.Sort (sorter);
-
-                       sortedColumn = dataGridViewColumn;
-                       sortOrder = (SortOrder)direction + 1;
-
-                       dataGridViewColumn.HeaderCell.SortGlyphDirection = (SortOrder)direction + 1;
 
                        Invalidate ();
-
                        OnSorted (EventArgs.Empty);
                }
                
@@ -3194,7 +3323,7 @@ namespace System.Windows.Forms {
                                eh (this, e);
                }
 
-               protected virtual void OnAutoSizeColumnModeChanged (DataGridViewAutoSizeColumnModeEventArgs e)
+               protected internal virtual void OnAutoSizeColumnModeChanged (DataGridViewAutoSizeColumnModeEventArgs e)
                {
                        DataGridViewAutoSizeColumnModeEventHandler eh = (DataGridViewAutoSizeColumnModeEventHandler)(Events [AutoSizeColumnModeChangedEvent]);
                        if (eh != null)
@@ -3225,6 +3354,7 @@ namespace System.Windows.Forms {
                protected override void OnBindingContextChanged (EventArgs e)
                {
                        base.OnBindingContextChanged(e);
+                       ReBind();
                }
 
                protected virtual void OnBorderStyleChanged (EventArgs e)
@@ -3455,6 +3585,10 @@ namespace System.Windows.Forms {
                                eh (this, e);
                }
 
+               internal void OnCellStateChangedInternal (DataGridViewCellStateChangedEventArgs e) {
+                       this.OnCellStateChanged (e);
+               }
+
                protected virtual void OnCellStateChanged (DataGridViewCellStateChangedEventArgs e)
                {
                        DataGridViewCellStateChangedEventHandler eh = (DataGridViewCellStateChangedEventHandler)(Events [CellStateChangedEvent]);
@@ -3509,7 +3643,7 @@ namespace System.Windows.Forms {
                                eh (this, e);
                }
 
-               protected virtual void OnCellValueNeeded (DataGridViewCellValueEventArgs e)
+               protected internal virtual void OnCellValueNeeded (DataGridViewCellValueEventArgs e)
                {
                        DataGridViewCellValueEventHandler eh = (DataGridViewCellValueEventHandler)(Events [CellValueNeededEvent]);
                        if (eh != null)
@@ -3526,10 +3660,14 @@ namespace System.Windows.Forms {
                internal void OnColumnAddedInternal (DataGridViewColumnEventArgs e)
                {
                        if (e.Column.CellTemplate != null) {
-                               RowTemplate.Cells.Add ((DataGridViewCell)e.Column.CellTemplate.Clone ());
+                               // The first column has just been added programatically instead of 
+                               // autogenerated so we need to create the rows for the first time.
+                               //
+                               if (!is_autogenerating_columns && columns.Count == 1)
+                                       ReBind ();
 
                                foreach (DataGridViewRow row in Rows)
-                                       row.Cells.Add ((DataGridViewCell)RowTemplate.Cells[RowTemplate.Cells.Count - 1].Clone ());
+                                       row.Cells.Add ((DataGridViewCell)e.Column.CellTemplate.Clone ());
                        }
                        
                        AutoResizeColumnsInternal ();
@@ -3664,6 +3802,20 @@ namespace System.Windows.Forms {
                                eh (this, e);
                }
 
+               internal void OnColumnRemovedInternal (DataGridViewColumnEventArgs e)
+               {
+                       if (e.Column.CellTemplate != null) {
+                               int index = e.Column.Index;
+
+                               foreach (DataGridViewRow row in Rows)
+                                       row.Cells.RemoveAt (index);
+                       }
+
+                       AutoResizeColumnsInternal ();
+                       OnColumnRemoved (e);
+                       PrepareEditingRow (false, true);
+               }
+
                protected virtual void OnColumnRemoved (DataGridViewColumnEventArgs e)
                {
                        DataGridViewColumnEventHandler eh = (DataGridViewColumnEventHandler)(Events [ColumnRemovedEvent]);
@@ -3815,7 +3967,7 @@ namespace System.Windows.Forms {
                {
                        base.OnHandleCreated(e);
                        
-                       if (Rows.Count > 0 && Columns.Count > 0)
+                       if (CurrentCell == null && Rows.Count > 0 && Columns.Count > 0)
                                MoveCurrentCell (ColumnDisplayIndexToIndex (0), 0, true, false, false, false);
                }
 
@@ -3853,7 +4005,8 @@ namespace System.Windows.Forms {
                                horizontalScrollBar.Bounds = new Rectangle (BorderWidth, Height - BorderWidth - horizontalScrollBar.Height, Width - (2 * BorderWidth), horizontalScrollBar.Height);
                        else if (verticalScrollBar.Visible)
                                verticalScrollBar.Bounds = new Rectangle (Width - BorderWidth - verticalScrollBar.Width, BorderWidth, verticalScrollBar.Width,  Height - (2 * BorderWidth));
-                               
+
+                       AutoResizeColumnsInternal ();
                        Invalidate ();
                }
 
@@ -3874,6 +4027,10 @@ namespace System.Windows.Forms {
                protected override void OnMouseClick (MouseEventArgs e)
                {
                        base.OnMouseClick(e);
+                       
+                       if (column_resize_active || row_resize_active)
+                               return;
+                               
                        //Console.WriteLine("Mouse: Clicks: {0}; Delta: {1}; X: {2}; Y: {3};", e.Clicks, e.Delta, e.X, e.Y);
                        HitTestInfo hit = HitTest (e.X, e.Y);
 
@@ -4049,18 +4206,50 @@ namespace System.Windows.Forms {
                {
                        base.OnMouseDown(e);
                        
+                       if (!EndEdit ())
+                               return;
+
                        HitTestInfo hitTest = HitTest(e.X, e.Y);
                        
                        DataGridViewCell cell = null;
                        DataGridViewRow row = null;
                        Rectangle cellBounds;
 
+                       if (hitTest.Type == DataGridViewHitTestType.ColumnHeader && MouseOverColumnResize (hitTest.ColumnIndex, e.X)) {
+                               if (e.Clicks == 2) {
+                                       AutoResizeColumn (hitTest.ColumnIndex);
+                                       return;
+                               }
+                               
+                               resize_band = hitTest.ColumnIndex;
+                               column_resize_active = true;
+                               resize_band_start = e.X;
+                               resize_band_delta = 0;
+                               DrawVerticalResizeLine (resize_band_start);
+                               return;
+                       }
+
+                       if (hitTest.Type == DataGridViewHitTestType.RowHeader && MouseOverRowResize (hitTest.RowIndex, e.Y)) {
+                               if (e.Clicks == 2) {
+                                       AutoResizeRow (hitTest.RowIndex);
+                                       return;
+                               }
+
+                               resize_band = hitTest.RowIndex;
+                               row_resize_active = true;
+                               resize_band_start = e.Y;
+                               resize_band_delta = 0;
+                               DrawHorizontalResizeLine (resize_band_start);
+                               return;
+                       }
+
                        if (hitTest.Type == DataGridViewHitTestType.Cell) {
+                               row = rows [hitTest.RowIndex];
+                               cell = row.Cells [hitTest.ColumnIndex];
+                               SetCurrentCellAddressCore (cell.ColumnIndex, cell.RowIndex, false, true, true);
                                cellBounds = GetCellDisplayRectangle (hitTest.ColumnIndex, hitTest.RowIndex, false);
                                OnCellMouseDown (new DataGridViewCellMouseEventArgs (hitTest.ColumnIndex, hitTest.RowIndex, e.X - cellBounds.X, e.Y - cellBounds.Y, e));
                                OnCellClick (new DataGridViewCellEventArgs (hitTest.ColumnIndex, hitTest.RowIndex));
-                               row = rows [hitTest.RowIndex];
-                               cell = row.Cells [hitTest.ColumnIndex];
                        }
                        
                        DoSelectionOnMouseDown (hitTest);
@@ -4074,25 +4263,16 @@ namespace System.Windows.Forms {
                                return;
                        }
                        
-                       if (cell == currentCell) {
-                               BeginEdit (true);
-                               return;
-                       } else if (currentCell != null) {
-                               EndEdit ();
-                               OnCellLeave(new DataGridViewCellEventArgs(currentCell.ColumnIndex, currentCell.RowIndex));
-                       }
-                       currentCell = cell;
-                       currentCellAddress = new Point (currentCell.ColumnIndex, currentCell.RowIndex);
-                       currentRow = cell.OwningRow;
-                       OnCurrentCellChanged(EventArgs.Empty);
-                       OnCellEnter(new DataGridViewCellEventArgs(cell.ColumnIndex, cell.RowIndex));
-                       if (editMode == DataGridViewEditMode.EditOnEnter) {
-                               BeginEdit (true);
-                       }
                        Invalidate();
                        return;
                }
 
+               private void UpdateBindingPosition (int position)
+               {
+                       if (DataManager != null)
+                               DataManager.Position = position;
+               }
+
                protected override void OnMouseEnter (EventArgs e)
                {
                        base.OnMouseEnter(e);
@@ -4113,7 +4293,30 @@ namespace System.Windows.Forms {
                protected override void OnMouseMove (MouseEventArgs e)
                {
                        base.OnMouseMove (e);
-                       
+
+                       if (column_resize_active) {
+                               // Erase the old line
+                               DrawVerticalResizeLine (resize_band_start + resize_band_delta);
+
+                               resize_band_delta = e.X - resize_band_start;
+
+                               // Draw the new line
+                               DrawVerticalResizeLine (resize_band_start + resize_band_delta);
+                               return;
+                       }
+
+                       if (row_resize_active) {
+                               // Erase the old line
+                               DrawHorizontalResizeLine (resize_band_start + resize_band_delta);
+
+                               resize_band_delta = e.Y - resize_band_start;
+
+                               // Draw the new line
+                               DrawHorizontalResizeLine (resize_band_start + resize_band_delta);
+                               return;
+                       }
+
+                       Cursor new_cursor = Cursors.Default;
                        HitTestInfo hit = this.HitTest (e.X, e.Y);
                        
                        if (hit.Type == DataGridViewHitTestType.Cell) {
@@ -4172,6 +4375,9 @@ namespace System.Windows.Forms {
 
                                EnteredHeaderCell = new_cell;
 
+                               if (MouseOverRowResize (hit.RowIndex, e.Y))
+                                       new_cursor = Cursors.HSplit;
+
                                // Check if we have moved into an error icon area
                                Rectangle icon = new_cell.InternalErrorIconsBounds;
 
@@ -4209,9 +4415,12 @@ namespace System.Windows.Forms {
                                }
                        
                        } else {
-                               if (hit.Type == DataGridViewHitTestType.ColumnHeader)
+                               if (hit.Type == DataGridViewHitTestType.ColumnHeader) {
                                        EnteredHeaderCell = Columns [hit.ColumnIndex].HeaderCell;
-                               else
+                                       
+                                       if (MouseOverColumnResize (hit.ColumnIndex, e.X))
+                                               new_cursor = Cursors.VSplit;
+                               } else
                                        EnteredHeaderCell = null;
 
                                // We have left the cell area
@@ -4220,12 +4429,36 @@ namespace System.Windows.Forms {
                                        hover_cell = null;
                                }
                        }
+                       
+                       Cursor = new_cursor;
                }
 
                protected override void OnMouseUp (MouseEventArgs e)
                {
                        base.OnMouseUp(e);
 
+                       if (column_resize_active) {
+                               column_resize_active = false;
+                               
+                               if (resize_band_delta + Columns[resize_band].Width < 0)
+                                       resize_band_delta = -Columns[resize_band].Width;
+
+                               Columns[resize_band].Width = Math.Max (resize_band_delta + Columns[resize_band].Width, Columns[resize_band].MinimumWidth);
+                               Invalidate ();
+                               return;
+                       }
+
+                       if (row_resize_active) {
+                               row_resize_active = false;
+
+                               if (resize_band_delta + Rows[resize_band].Height < 0)
+                                       resize_band_delta = -Rows[resize_band].Height;
+
+                               Rows[resize_band].Height = Math.Max (resize_band_delta + Rows[resize_band].Height, Rows[resize_band].MinimumHeight);
+                               Invalidate ();
+                               return;
+                       }
+               
                        HitTestInfo hit = this.HitTest (e.X, e.Y);
 
                        if (hit.Type == DataGridViewHitTestType.Cell) {
@@ -4313,7 +4546,6 @@ namespace System.Windows.Forms {
                        gridWidth = rowHeadersVisible ? rowHeadersWidth : 0;
                        gridHeight = 0;
                        
-                       int rows_displayed = 0;
                        int first_row_height = Rows.Count > 0 ? Rows[Math.Min (Rows.Count - 1, first_row_index)].Height : 0;
 //                     int room_left = this.Height;
                        
@@ -4353,9 +4585,7 @@ namespace System.Windows.Forms {
                                bounds.Y += bounds.Height;
                                bounds.X = BorderWidth;
                                
-                               if (bounds.Y < ClientSize.Height - (horizontalScrollBar.Visible ? horizontalScrollBar.Height : 0))
-                                       rows_displayed++;
-                               else
+                               if (bounds.Y >= ClientSize.Height - (horizontalScrollBar.Visible ? horizontalScrollBar.Height : 0))
                                        break;
                                        
                                gridHeight += row.Height;
@@ -4403,13 +4633,19 @@ namespace System.Windows.Forms {
                                        horizontalScrollBar.Minimum = 0;
                                        horizontalScrollBar.Maximum = gridWidth;
                                        horizontalScrollBar.SmallChange = Columns[first_col_index].Width;
-                                       horizontalScrollBar.LargeChange = ClientSize.Width - rowHeadersWidth;
+                                       int largeChange = ClientSize.Width - rowHeadersWidth;
+                                       if (largeChange <= 0)
+                                               largeChange = ClientSize.Width;
+                                       horizontalScrollBar.LargeChange = largeChange;
                                }
                                if (verticalVisible) {
                                        verticalScrollBar.Minimum = 0;
                                        verticalScrollBar.Maximum = gridHeight;
                                        verticalScrollBar.SmallChange = first_row_height + 1;
-                                       verticalScrollBar.LargeChange = ClientSize.Height - columnHeadersHeight;
+                                       int largeChange = ClientSize.Height - columnHeadersHeight;
+                                       if (largeChange <= 0)
+                                               largeChange = ClientSize.Height;
+                                       verticalScrollBar.LargeChange = largeChange;
                                }
                        }
 
@@ -4592,6 +4828,9 @@ namespace System.Windows.Forms {
 
                internal void OnRowsAddedInternal (DataGridViewRowsAddedEventArgs e)
                {
+                       if (hover_cell != null && hover_cell.RowIndex >= e.RowIndex)
+                               hover_cell = null;
+                       AutoResizeColumnsInternal ();
                        Invalidate ();
                        OnRowsAdded (e);
                }
@@ -4608,7 +4847,34 @@ namespace System.Windows.Forms {
                        if (eh != null) eh (this, e);
                }
 
-               protected internal virtual void OnRowsRemoved (DataGridViewRowsRemovedEventArgs e)
+               internal void OnRowsRemovedInternal (DataGridViewRowsRemovedEventArgs e)
+               {
+                       if (selected_rows != null)
+                               selected_rows.InternalClear ();
+                       if (selected_columns != null)
+                               selected_columns.InternalClear ();
+
+                       if (Rows.Count == 0) {
+                               MoveCurrentCell (-1, -1, true, false, false, true);
+                               hover_cell = null;
+                       } else if (Columns.Count == 0) {
+                               MoveCurrentCell (-1, -1, true, false, false, true);
+                               hover_cell = null;
+                       } else {
+                               int nextRowIndex = e.RowIndex;
+                               if (nextRowIndex >= Rows.Count)
+                                       nextRowIndex = Rows.Count - 1;
+                               MoveCurrentCell (currentCell != null ? currentCell.ColumnIndex : 0, nextRowIndex, 
+                                                true, false, false, true);
+                               if (hover_cell != null && hover_cell.RowIndex >= e.RowIndex)
+                                       hover_cell = null;
+                       }
+
+                       Invalidate ();
+                       OnRowsRemoved (e);
+               }
+
+               protected virtual void OnRowsRemoved (DataGridViewRowsRemovedEventArgs e)
                {
                        DataGridViewRowsRemovedEventHandler eh = (DataGridViewRowsRemovedEventHandler)(Events [RowsRemovedEvent]);
                        if (eh != null) eh (this, e);
@@ -4663,6 +4929,19 @@ namespace System.Windows.Forms {
 
                protected virtual void OnUserAddedRow (DataGridViewRowEventArgs e)
                {
+                       PrepareEditingRow (false, false);
+
+                       new_row_editing = true;
+                       if (DataManager != null) {
+                               // Switch the current editing row with a real one
+                               if (editing_row != null) {
+                                       Rows.RemoveInternal (editing_row);
+                                       editing_row = null;
+                               }
+                               DataManager.AddNew (); // will raise OnListPositionChanged
+                       }
+
+                       e = new DataGridViewRowEventArgs (Rows[NewRowIndex]);
                        DataGridViewRowEventHandler eh = (DataGridViewRowEventHandler)(Events [UserAddedRowEvent]);
                        if (eh != null) eh (this, e);
                }
@@ -4671,7 +4950,6 @@ namespace System.Windows.Forms {
                {
                        DataGridViewRowEventHandler eh = (DataGridViewRowEventHandler)(Events [UserDeletedRowEvent]);
                        if (eh != null) eh (this, e);
-
                }
 
                protected virtual void OnUserDeletingRow (DataGridViewRowCancelEventArgs e)
@@ -4771,13 +5049,6 @@ namespace System.Windows.Forms {
                                        Rows.RemoveAt (row.Index);
                        }
 
-                       if (selected_rows != null)
-                               selected_rows.InternalClear ();
-                       if (selected_columns != null)
-                               selected_columns.InternalClear ();
-
-                       SetSelectedCellCore (0, Math.Min (index, Rows.Count - 1), true);
-                               
                        return true;
                }
 
@@ -4801,6 +5072,12 @@ namespace System.Windows.Forms {
                                        if (ProcessDataGridViewKey (new KeyEventArgs (keyData)))
                                                return true;
                                                
+                                       break;
+                               case Keys.Enter:
+                               case Keys.Escape:
+                                       if (ProcessDataGridViewKey (new KeyEventArgs (keyData)))
+                                               return true;
+                                               
                                        break;
                        }
                        
@@ -4812,8 +5089,6 @@ namespace System.Windows.Forms {
                        int current_row = CurrentCellAddress.Y;
                        
                        if (current_row < Rows.Count - 1) {
-                               EndEdit ();
-                               
                                // Move to the last cell in the column
                                if ((keyData & Keys.Control) == Keys.Control)
                                        MoveCurrentCell (CurrentCellAddress.X, Rows.Count - 1, true, (keyData & Keys.Control) == Keys.Control, (keyData & Keys.Shift) == Keys.Shift, true);
@@ -4848,19 +5123,12 @@ namespace System.Windows.Forms {
 
                protected bool ProcessEnterKey (Keys keyData)
                {
-                       if (!IsCurrentCellInEditMode)
-                               return false;
-                               
-                       CommitEdit (DataGridViewDataErrorContexts.Commit);
-                       
-                       // Move one cell down
-                       if ((keyData & Keys.Control) == 0) {
-                               int current_row = CurrentCellAddress.Y;
-                               
-                               if (current_row < Rows.Count - 1)
-                                       MoveCurrentCell (CurrentCellAddress.X, current_row + 1, true, (keyData & Keys.Control) == Keys.Control, (keyData & Keys.Shift) == Keys.Shift, true);
-                       }
+                       if (ProcessDownKey (keyData))
+                               return true;
                        
+                       // ProcessDown may fail if we are on the last row,
+                       // but Enter should still EndEdit if this is the last row
+                       EndEdit ();
                        return true;
                }
 
@@ -4912,9 +5180,12 @@ namespace System.Windows.Forms {
                {
                        DataGridViewCell cell = CurrentCell;
                        
-                       if (cell != null)
+                       if (cell != null) {
                                if (cell.KeyEntersEditMode (new KeyEventArgs ((Keys)m.WParam.ToInt32 ())))
                                        BeginEdit (true);
+                               if (EditingControl != null && ((Msg)m.Msg == Msg.WM_KEYDOWN || (Msg)m.Msg == Msg.WM_CHAR))
+                                       XplatUI.SendMessage (EditingControl.Handle, (Msg)m.Msg, m.WParam, m.LParam);
+                       }
 
                        return base.ProcessKeyEventArgs (ref m);
                }
@@ -4951,8 +5222,6 @@ namespace System.Windows.Forms {
                        int disp_index = ColumnIndexToDisplayIndex (currentCellAddress.X);
 
                        if (disp_index > 0) {
-                               EndEdit ();
-                               
                                // Move to the first cell in the row
                                if ((keyData & Keys.Control) == Keys.Control)
                                        MoveCurrentCell (ColumnDisplayIndexToIndex (0), currentCellAddress.Y, true, (keyData & Keys.Control) == Keys.Control, (keyData & Keys.Shift) == Keys.Shift, true);
@@ -4972,8 +5241,6 @@ namespace System.Windows.Forms {
                        int current_row = CurrentCellAddress.Y;
 
                        if (current_row < Rows.Count - 1) {
-                               EndEdit ();
-
                                // Move one "page" of cells down
                                int new_row = Math.Min (Rows.Count - 1, current_row + DisplayedRowCount (false));
 
@@ -4991,8 +5258,6 @@ namespace System.Windows.Forms {
                        int current_row = CurrentCellAddress.Y;
 
                        if (current_row > 0) {
-                               EndEdit ();
-
                                // Move one "page" of cells up
                                int new_row = Math.Max (0, current_row - DisplayedRowCount (false));
 
@@ -5009,8 +5274,6 @@ namespace System.Windows.Forms {
                        int disp_index = ColumnIndexToDisplayIndex (currentCellAddress.X);
 
                        if (disp_index < Columns.Count - 1) {
-                               EndEdit ();
-                               
                                // Move to the last cell in the row
                                if ((keyData & Keys.Control) == Keys.Control)
                                        MoveCurrentCell (ColumnDisplayIndexToIndex (Columns.Count - 1), currentCellAddress.Y, true, (keyData & Keys.Control) == Keys.Control, (keyData & Keys.Shift) == Keys.Shift, true);
@@ -5058,8 +5321,6 @@ namespace System.Windows.Forms {
 
                protected bool ProcessTabKey (Keys keyData)
                {
-                       EndEdit ();
-                       
                        Form f = FindForm ();
                        
                        if (f != null)
@@ -5103,8 +5364,6 @@ namespace System.Windows.Forms {
                        int current_row = CurrentCellAddress.Y;
 
                        if (current_row > 0) {
-                               EndEdit ();
-
                                // Move to the first cell in the column
                                if ((keyData & Keys.Control) == Keys.Control)
                                        MoveCurrentCell (CurrentCellAddress.X, 0, true, (keyData & Keys.Control) == Keys.Control, (keyData & Keys.Shift) == Keys.Shift, true);
@@ -5133,7 +5392,7 @@ namespace System.Windows.Forms {
                        base.SetBoundsCore(x, y, width, height, specified);
                }
 
-               [MonoTODO ("Does not use validateCurrentCell or throughMouseClick")]
+               [MonoTODO ("Does not use validateCurrentCell")]
                protected virtual bool SetCurrentCellAddressCore (int columnIndex, int rowIndex, bool setAnchorCellAddress, bool validateCurrentCell, bool throughMouseClick)
                {
                        if ((columnIndex < 0 || columnIndex > Columns.Count - 1) && rowIndex != -1)
@@ -5151,14 +5410,56 @@ namespace System.Windows.Forms {
                        if (cell != null && !cell.Visible)
                                throw new InvalidOperationException ("cell is not visible");
                                
-                       if (setAnchorCellAddress)
-                               anchor_cell = new Point (columnIndex, rowIndex);
+                       // Always update the current cell address property
+                       // If the row has moved it would be out of date.
+                       if (currentCell != null) {
+                               if (setAnchorCellAddress) {
+                                       anchor_cell.X = currentCell.ColumnIndex;
+                                       anchor_cell.Y = currentCell.RowIndex;
+                               }
+                               currentCellAddress.X = currentCell.ColumnIndex;
+                               currentCellAddress.Y = currentCell.RowIndex;
+                       }
+
+                       if (cell != currentCell) {
+                               if (currentCell != null) {
+                                       if (currentCell.IsInEditMode) {
+                                               if (!EndEdit ())
+                                                       return false;
+                                               else if (currentCell.RowIndex == NewRowIndex && new_row_editing)
+                                                       CancelEdit ();
+                                       }
+                                       OnCellLeave (new DataGridViewCellEventArgs(currentCell.ColumnIndex, currentCell.RowIndex));
+                                       OnRowLeave (new DataGridViewCellEventArgs (currentCell.ColumnIndex, currentCell.RowIndex));
+                               }
+
+                               currentCell = cell;
+                               if (setAnchorCellAddress)
+                                       anchor_cell = new Point (columnIndex, rowIndex);
+                               currentCellAddress = new Point (columnIndex, rowIndex);
+
+                               if (cell != null) {
+                                       UpdateBindingPosition (cell.RowIndex);
+                                       OnRowEnter (new DataGridViewCellEventArgs (cell.ColumnIndex, cell.RowIndex));
+                                       OnCellEnter (new DataGridViewCellEventArgs(cell.ColumnIndex, cell.RowIndex));
+                               }
+                               OnCurrentCellChanged (EventArgs.Empty);
+
+                               if (cell != null) {
+                                       // If the user begins an edit in the NewRow, add a new row
+                                       if (AllowUserToAddRows && cell.RowIndex == NewRowIndex && !is_binding && !new_row_editing) {
+                                               // OnUserAddedRow will add a real row and reset the current cell
+                                               OnUserAddedRow (new DataGridViewRowEventArgs (Rows[NewRowIndex]));
+                                       } else {
+                                               if (editMode == DataGridViewEditMode.EditOnEnter)
+                                                       BeginEdit (true);
+                                       }
+                               }
+                       } else {
+                               if (cell != null && throughMouseClick)
+                                       BeginEdit (true);
+                       }
 
-                       currentCellAddress = new Point (columnIndex, rowIndex);
-                       CurrentCell = cell;
-                       
-                       OnCurrentCellChanged (EventArgs.Empty);
-                       
                        return true;
                }
 
@@ -5188,10 +5489,13 @@ namespace System.Windows.Forms {
                        } else if (selected && !selected_columns.Contains (col)) {
                                selected_columns.InternalAdd (col);
                        }
+
+                       Invalidate();
                }
 
                internal void SetSelectedRowCoreInternal (int rowIndex, bool selected) {
-                       SetSelectedRowCore (rowIndex, selected);
+                       if (rowIndex >= 0 && rowIndex < Rows.Count)
+                               SetSelectedRowCore (rowIndex, selected);
                }       
 
                protected virtual void SetSelectedRowCore (int rowIndex, bool selected) {
@@ -5207,6 +5511,8 @@ namespace System.Windows.Forms {
                        } else if (selected && !selected_rows.Contains (row)) {
                                selected_rows.InternalAdd (row);
                        }
+
+                       Invalidate();
                }
 
                protected override void WndProc (ref Message m)
@@ -5232,9 +5538,6 @@ namespace System.Windows.Forms {
                internal void InternalOnCellValueChanged (DataGridViewCellEventArgs e)
                {
                        OnCellValueChanged (e);
-                       
-                       if (editing_row != null && e.RowIndex == editing_row.Index)
-                               PrepareEditingRow (true, false);
                }
 
                internal void InternalOnDataError (DataGridViewDataErrorEventArgs e)
@@ -5273,12 +5576,14 @@ namespace System.Windows.Forms {
                internal void OnVScrollBarScroll (object sender, ScrollEventArgs e)
                {
                        verticalScrollingOffset = e.NewValue;
+                       if (Rows.Count == 0)
+                               return;
+
                        int top = 0;
                        
                        for (int index = 0; index < Rows.Count; index++) {
                                DataGridViewRow row = Rows[index];
-                               
-                               if (e.NewValue <= top + row.Height) {
+                               if (e.NewValue < top + row.Height) {
                                        if (first_row_index != index) {
                                                first_row_index = index;
                                                Invalidate ();
@@ -5291,10 +5596,7 @@ namespace System.Windows.Forms {
                                top += row.Height;
                        }
                        
-                       if (Rows.Count == 0)
-                               return;
-                               
-                       first_row_index = Rows.Count - DisplayedRowCount (false) + 1;
+                       first_row_index = Rows.Count - DisplayedRowCount (false);
                        Invalidate ();
                        OnScroll (e);
                }
@@ -5306,10 +5608,10 @@ namespace System.Windows.Forms {
                internal void OnColumnCollectionChanged (object sender, CollectionChangeEventArgs e) {
                        switch (e.Action) {
                                case CollectionChangeAction.Add:
-                                       OnColumnAdded(new DataGridViewColumnEventArgs(e.Element as DataGridViewColumn));
+                                       OnColumnAddedInternal(new DataGridViewColumnEventArgs(e.Element as DataGridViewColumn));
                                        break;
                                case CollectionChangeAction.Remove:
-                                       OnColumnRemoved(new DataGridViewColumnEventArgs(e.Element as DataGridViewColumn));
+                                       OnColumnRemovedInternal(new DataGridViewColumnEventArgs(e.Element as DataGridViewColumn));
                                        break;
                                case CollectionChangeAction.Refresh:
                                        break;
@@ -5330,7 +5632,7 @@ namespace System.Windows.Forms {
                {
                        float totalFillWeight = 0;
                        int FillCount = 0; // The number of columns that has AutoSizeMode.Fill set
-                       int spaceLeft = ClientSize.Width;
+                       int spaceLeft = ClientSize.Width - (verticalScrollBar.VisibleInternal ? verticalScrollBar.Width : 0);
 
                        if (RowHeadersVisible) {
                                spaceLeft -= RowHeadersWidth;
@@ -5413,7 +5715,8 @@ namespace System.Windows.Forms {
                        case DataGridViewAutoSizeColumnMode.AllCells:
                        case DataGridViewAutoSizeColumnMode.DisplayedCells:
                        case DataGridViewAutoSizeColumnMode.DisplayedCellsExceptHeader:
-                               size  = CalculateColumnCellWidth (columnIndex, col.InheritedAutoSizeMode);
+                               size  = Math.Max (CalculateColumnCellWidth (columnIndex, col.InheritedAutoSizeMode), 
+                                                 col.HeaderCell.ContentBounds.Width);
                                break;
                        case DataGridViewAutoSizeColumnMode.ColumnHeader:
                                size = col.HeaderCell.ContentBounds.Width;
@@ -5450,9 +5753,9 @@ namespace System.Windows.Forms {
                                                continue;
                                }
                                
-                               Rectangle cell_rect = GetCellDisplayRectangle (index, i, false);
-                               
-                               result = Math.Max (result, cell_rect.Width);
+                               int cell_width = Rows[i].Cells[index].PreferredSize.Width;
+
+                               result = Math.Max (result, cell_width);
                        }
                        
                        return result;
@@ -5484,87 +5787,44 @@ namespace System.Windows.Forms {
                        return bounds;
                }
 
-               private void PrepareEditingRow (bool cell_changed, bool column_changed)
+               internal void PrepareEditingRow (bool cell_changed, bool column_changed)
                {
+                       if (new_row_editing)
+                               return;
+
                        bool show = false;
                        
                        show = ColumnCount > 0 && AllowUserToAddRows;
 
                        if (!show && editing_row != null) {
-                               Rows.Remove (editing_row);
+                               Rows.RemoveInternal (editing_row);
                                editing_row = null;
                        } else if (show) {
-                               if (editing_row != null) {
-                                       if (cell_changed) {
-                                               // The row changed, it's no longer an editing row.
-                                               editing_row = null;
-                                       } else if (column_changed) {
-                                               // The number of columns has changed, we need a new editing row.
-                                               Rows.Remove (editing_row);
-                                               editing_row = null;
-                                       }
+                               if (editing_row != null && (cell_changed || column_changed)) {
+                                       // The row changed, it's no longer an editing row.
+                                       //    or
+                                       // The number of columns has changed, we need a new editing row.
+                                       Rows.RemoveInternal (editing_row);
+                                       editing_row = null;
                                }
                                if (editing_row == null) {
                                        editing_row = RowTemplateFull;
                                        Rows.AddInternal (editing_row, false);
                                }
                        }
-                               
-                       
                }
                
                internal DataGridViewRow EditingRow {
                        get { return editing_row; }
                }
 
-               private void BindIList (IList list) {
-                       if (autoGenerateColumns) {
-                               // Stuff from a DataSet
-                               if (list is DataView) {
-                                       DataView dataView = (DataView) list;
-                                       DataTable table = dataView.Table;
-
-                                       foreach (DataColumn dataColumn in table.Columns) {
-                                               DataGridViewColumn col = CreateColumnByType (dataColumn.DataType);
-                                               
-                                               col.Name = dataColumn.ColumnName;
-                                               col.DataPropertyName = dataColumn.ColumnName;
-                                               col.SetIsDataBound (true);
-                                               col.ValueType = dataColumn.DataType;
-                                               col.AutoGenerated = true;
-                                               
-                                               columns.Add (col);
-                                       }
-                               }
-                               // Its a generic something or other, like a BindingList<T>, so
-                               // we can figure out the type from the generic type
-                               else if (list.GetType ().GetGenericArguments ().Length > 0) {
-                                       GenerateColumnsFromType (list.GetType ().GetGenericArguments ()[0]);
-                               }
-                               // Its a normal array/collection type thing
-                               else if (list.GetType ().IsArray) {
-                                       GenerateColumnsFromType (list.GetType ().GetElementType ());
-                               }
-                       }
-               
-                       // Subscribe to the dataset's change notification
-                       if (list is DataView) {
-                               (list as DataView).ListChanged += OnListChanged;
-                               (list as DataView).Table.ColumnChanged += OnTableColumnChanged;
-                       }
-                       
-                       // Add the rows
-                       foreach (object element in list)
-                               AddBoundRow (element);
-               }
-
                private void AddBoundRow (object element)
                {
                        // Don't add rows if there are no columns
                        if (ColumnCount == 0)
                                return;
                                
-                       DataGridViewRow row = (DataGridViewRow)RowTemplate.Clone ();
+                       DataGridViewRow row = (DataGridViewRow)RowTemplateFull;
                        rows.InternalAdd (row);
 
                        PropertyDescriptorCollection properties = TypeDescriptor.GetProperties (element);
@@ -5580,29 +5840,20 @@ namespace System.Windows.Forms {
                                if (cell == null)
                                        continue;
                                        
-                               cell.valuex = property.GetValue (element);
-                               cell.valueType = property.PropertyType;
+                               cell.Value = property.GetValue (element);
+                               cell.ValueType = property.PropertyType;
                        }
                }
                
-               private void GenerateColumnsFromType (Type type)
+               private bool IsColumnAlreadyBound (string name)
                {
-                       foreach (PropertyDescriptor property in TypeDescriptor.GetProperties (type)) {
-                               // This keeps out things like arrays
-                               if ((typeof(ICollection).IsAssignableFrom (property.PropertyType)))
-                                       continue;
-                                       
-                               DataGridViewColumn col = CreateColumnByType (property.PropertyType);
-                               col.Name = property.DisplayName;
-                               col.DataPropertyName = property.DisplayName;
-                               col.ReadOnly = property.IsReadOnly;
-                               col.SetIsDataBound (true);
-                               col.ValueType = property.PropertyType;
-                               col.AutoGenerated = true;
-                               columns.Add (col);
-                       }
+                       foreach (DataGridViewColumn col in Columns)
+                               if (col.DataPropertyName == name)
+                                       return true;
+
+                       return false;
                }
-               
+
                private DataGridViewColumn CreateColumnByType (Type type)
                {
                        if (type == typeof (bool))
@@ -5613,29 +5864,12 @@ namespace System.Windows.Forms {
                
                private void ClearBinding ()
                {
-                       columns.ClearAutoGeneratedColumns ();
-                       rows.Clear ();
-                       PrepareEditingRow (false, true);
-
-                       if (dataSource != null) {
-                               if (dataSource is DataSet) {
-                                       (dataSource as DataSet).Tables.CollectionChanged -= OnDataSetTableChanged;
-                                       
-                                       DataTable dt = (dataSource as DataSet).Tables[dataMember];
-                                       
-                                       if (dt != null) {
-                                               DataView dv = dt.DefaultView;
-                                       
-                                               if (dv != null) {
-                                                       (dv as DataView).Table.ColumnChanged -= OnTableColumnChanged;
-                                                       (dv as DataView).ListChanged -= OnListChanged;
-                                               }
-                                       }
-                               } else if (dataSource is DataView) {
-                                       (dataSource as DataView).ListChanged -= OnListChanged;
-                                       (dataSource as DataView).Table.ColumnChanged -= OnTableColumnChanged;
-                               } else if (dataSource is DataTable)
-                                       ((dataSource as IListSource).GetList () as DataView).ListChanged -= OnListChanged;
+                       if (DataManager != null) {
+                               columns.ClearAutoGeneratedColumns ();
+                               PrepareEditingRow (false, true);
+                               rows.Clear ();
+                               DataManager.ListChanged -= OnListChanged;
+                               DataManager.PositionChanged -= OnListPositionChanged;
                        }
                }
                
@@ -5648,50 +5882,69 @@ namespace System.Windows.Forms {
                         - the System.ComponentModel.IBindingListView interface, such as the System.Windows.Forms.BindingSource class.
                        */
                        
-                       if (dataSource != null) {
-                               object value = dataSource;
-                               
-                               // DataBinding
-                               if (value is DataSet && string.IsNullOrEmpty (dataMember)) {
-                                       Invalidate ();
-                                       return;
+                       if (dataSource != null && DataManager != null) {
+                               if (autoGenerateColumns) {
+                                       is_autogenerating_columns = true;
+
+                                       foreach (PropertyDescriptor property in DataManager.GetItemProperties()) {
+                                               // This keeps out things like arrays
+                                               if ((typeof(ICollection).IsAssignableFrom (property.PropertyType)))
+                                                       continue;
+
+                                               if (IsColumnAlreadyBound (property.DisplayName))
+                                                       continue;
+
+                                               DataGridViewColumn col = CreateColumnByType (property.PropertyType);
+                                               col.Name = property.DisplayName;
+                                               col.DataPropertyName = property.DisplayName;
+                                               col.ReadOnly = !DataManager.AllowEdit || property.IsReadOnly;
+                                               col.SetIsDataBound (true);
+                                               col.ValueType = property.PropertyType;
+                                               col.AutoGenerated = true;
+                                               columns.Add (col);
+                                       }
+
+                                       is_autogenerating_columns = false;
                                }
-                               if (value is DataSet) {
-                                       (value as DataSet).Tables.CollectionChanged += OnDataSetTableChanged;
-                                       value = (value as DataSet).Tables[dataMember];
+
+                               // DataBind both autogenerated and not columns if there is a matching property
+                               foreach (PropertyDescriptor property in DataManager.GetItemProperties()) {
+                                       foreach (DataGridViewColumn col in Columns) {
+                                               if (col.DataPropertyName == property.Name)
+                                                       col.SetIsDataBound (true);
+                                       }
                                }
-                               if (value is BindingSource)
-                                       value = (value as BindingSource).List;
-                                       
-                               if (value is IList)
-                                       BindIList (value as IList);
-                               else if (value is IListSource)
-                                       BindIListSource (value as IListSource);
-                               else if (value is IBindingList)
-                                       BindIBindingList (value as IBindingList);
-                               else if (value is IBindingListView)
-                                       BindIBindingListView (value as IBindingListView);
 
+                               foreach (object element in DataManager.List)
+                                       AddBoundRow (element);
+
+                               DataManager.ListChanged += OnListChanged;
+                               DataManager.PositionChanged += OnListPositionChanged;
                                OnDataBindingComplete (new DataGridViewBindingCompleteEventArgs (ListChangedType.Reset));
+                               OnListPositionChanged (this, EventArgs.Empty);
+                       } else {
+                               if (Rows.Count > 0 && Columns.Count > 0)
+                                       MoveCurrentCell (0, 0, true, false, false, false);
                        }
 
+                       PerformLayout();
                        Invalidate ();
                }
                
-               private void BindIListSource (IListSource list) {
-                       BindIList(list.GetList());
-               }
-
-               private void BindIBindingList (IBindingList list) {
-                       BindIList(list);
-               }
-
-               private void BindIBindingListView (IBindingListView list) {
-                       BindIList(list);
-               }
-
                private void MoveCurrentCell (int x, int y, bool select, bool isControl, bool isShift, bool scroll)
                {
+                       if (x == -1 || y == -1)
+                               x = y = -1;
+
+                       if (!SetCurrentCellAddressCore (x, y, true, false, false)) {
+                               ClearSelection ();
+                               return;
+                       }
+                       if (x == -1 && y == -1) {
+                               ClearSelection ();
+                               return;
+                       }
+
                        bool full_row_selected = Rows.SharedRow(CurrentCellAddress.Y).Selected;
                        bool full_col_selected = Columns[CurrentCellAddress.X].Selected;
                        
@@ -5710,9 +5963,6 @@ namespace System.Windows.Forms {
                        else if (mode == DataGridViewSelectionMode.ColumnHeaderSelect)
                                mode = DataGridViewSelectionMode.CellSelect;
                        
-                       // Move CurrentCell
-                       SetCurrentCellAddressCore (x, y, true, false, false);
-                       
                        // If the current cell isn't visible, scroll to it
                        if (scroll) {
                                int disp_x = ColumnIndexToDisplayIndex (x);
@@ -5731,10 +5981,10 @@ namespace System.Windows.Forms {
                                }
 
                                int disp_y = y;
+                               int displayedRowsCount = DisplayedRowCount (false);
+                               int delta_y = 0;
 
                                if (disp_y < first_row_index) {
-                                       int delta_y = 0;
-
                                        if (disp_y == 0)
                                                delta_y = verticalScrollBar.Value;
                                        else
@@ -5743,13 +5993,11 @@ namespace System.Windows.Forms {
 
                                        verticalScrollBar.SafeValueSet (verticalScrollBar.Value - delta_y);
                                        OnVScrollBarScroll (this, new ScrollEventArgs (ScrollEventType.ThumbPosition, verticalScrollBar.Value));
-                               } else if (disp_y > first_row_index + DisplayedRowCount (false) - 2) {
-                                       int delta_y = 0;
-                                       
+                               } else if (disp_y > first_row_index + displayedRowsCount - 1) {
                                        if (disp_y == Rows.Count - 1)
                                                delta_y = verticalScrollBar.Maximum - verticalScrollBar.Value;
                                        else
-                                               for (int i = first_row_index + DisplayedRowCount (false) - 2; i < disp_y; i++)
+                                               for (int i = first_row_index + displayedRowsCount - 1; i < disp_y; i++)
                                                        delta_y += GetRowInternal (i).Height;
 
                                        verticalScrollBar.SafeValueSet (verticalScrollBar.Value + delta_y);
@@ -5781,6 +6029,8 @@ namespace System.Windows.Forms {
                
                private int ColumnIndexToDisplayIndex (int index)
                {
+                       if (index == -1)
+                               return index;
                        return Columns[index].DisplayIndex;
                }
                
@@ -5793,26 +6043,76 @@ namespace System.Windows.Forms {
                {
                        switch (args.ListChangedType) {
                                case ListChangedType.ItemAdded:
-                                       AddBoundRow ((sender as DataView)[args.NewIndex]);
+                                       AddBoundRow (DataManager[args.NewIndex]);
                                        break;
                                case ListChangedType.ItemDeleted:
-                                       Rows.RemoveAt (args.NewIndex);
+                                       Rows.RemoveAtInternal (args.NewIndex);
+                                       break;
+                               case ListChangedType.ItemChanged:
+                                       break;
+                               default:
+                                       ReBind ();
                                        break;
                        }
                        
                        Invalidate ();
                }
                
-               private void OnTableColumnChanged (object sender, DataColumnChangeEventArgs e)
+               private void OnListPositionChanged (object sender, EventArgs args)
+               {
+                       if (Rows.Count > 0 && Columns.Count > 0 && DataManager.Position != -1)
+                               MoveCurrentCell (currentCell != null ? currentCell.ColumnIndex : 0, DataManager.Position, 
+                                                true, false, false, true);
+                       else
+                               MoveCurrentCell (-1, -1, true, false, false, true);
+               }
+
+               private void ReBind ()
+               {
+                       if (!is_binding) {
+                               is_binding = true;
+                               ClearBinding ();
+                               DoBinding ();
+                               is_binding = false;
+                       }
+               }
+               
+               private bool MouseOverColumnResize (int col, int mousex)
+               {
+                       if (!allowUserToResizeColumns)
+                               return false;
+                               
+                       Rectangle col_bounds = GetCellDisplayRectangle (col, 0, false);
+
+                       if (mousex >= col_bounds.Right - 4 && mousex <= col_bounds.Right)
+                               return true;
+
+                       return false;
+               }
+
+               private bool MouseOverRowResize (int row, int mousey)
                {
-                       ClearBinding ();
-                       DoBinding ();
+                       if (!allowUserToResizeRows)
+                               return false;
+
+                       Rectangle row_bounds = GetCellDisplayRectangle (0, row, false);
+
+                       if (mousey >= row_bounds.Bottom - 4 && mousey <= row_bounds.Bottom)
+                               return true;
+
+                       return false;
                }
 
-               private void OnDataSetTableChanged (object sender, CollectionChangeEventArgs e)
+               private void DrawVerticalResizeLine (int x)
                {
-                       ClearBinding ();
-                       DoBinding ();
+                       Rectangle splitter = new Rectangle (x, Bounds.Y + 3 + (ColumnHeadersVisible ? ColumnHeadersHeight : 0), 1, Bounds.Height - 3 - (ColumnHeadersVisible ? ColumnHeadersHeight : 0));
+                       XplatUI.DrawReversibleRectangle (Handle, splitter, 2);
+               }
+
+               private void DrawHorizontalResizeLine (int y)
+               {
+                       Rectangle splitter = new Rectangle (Bounds.X + 3 + (RowHeadersVisible ? RowHeadersWidth : 0), y, Bounds.Width - 3 + (RowHeadersVisible ? RowHeadersWidth : 0), 1);
+                       XplatUI.DrawReversibleRectangle (Handle, splitter, 2);
                }
 
                #region Stuff for ToolTips
@@ -5883,14 +6183,19 @@ namespace System.Windows.Forms {
                                DataGridViewRow row1 = (DataGridViewRow)x;
                                DataGridViewRow row2 = (DataGridViewRow)y;
 
+                               if (row1.Cells[column].ValueType == typeof (DateTime) && row2.Cells[column].ValueType == typeof (DateTime))
+                                       return DateTime.Compare ((DateTime)row1.Cells[column].Value, (DateTime)row2.Cells[column].Value) * direction;
+
                                object val1 = row1.Cells[column].FormattedValue;
                                object val2 = row2.Cells[column].FormattedValue;
+                               object val1NullValue = row1.Cells[column].InheritedStyle.NullValue;
+                               object val2NullValue = row2.Cells[column].InheritedStyle.NullValue;
 
-                               if (val1 == null && val2 == null)
+                               if (val1 == val1NullValue && val2 == val2NullValue)
                                        return 0;
-                               if (val1 == null)
+                               if (val1 == val1NullValue)
                                        return direction;
-                               if (val2 == null)
+                               if (val2 == val2NullValue)
                                        return -1 * direction;
 
                                if (numeric_sort)
@@ -5962,7 +6267,7 @@ namespace System.Windows.Forms {
                [ComVisible (false)]
                public class DataGridViewControlCollection : Control.ControlCollection
                {
-                       private new DataGridView owner;
+                       private DataGridView owner;
                        
                        public DataGridViewControlCollection (DataGridView owner) : base (owner)
                        {