New tests.
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / DataGridView.cs
index 39b94c1b7cfb5992d307eae911ae204060c1e48d..6e811bfe84bbc930753ad9b6a8f889cfbb3f4a01 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,9 @@ namespace System.Windows.Forms {
                private HScrollBar horizontalScrollBar;
                private VScrollBar verticalScrollBar;
                private Control editingControl;
-               private bool new_row_commited = true;
+               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;
@@ -132,9 +135,6 @@ namespace System.Windows.Forms {
                private DataGridViewSelectedColumnCollection selected_columns;
                private DataGridViewRow editing_row;
                
-               private int gridWidth;
-               private int gridHeight;
-
                DataGridViewHeaderCell pressed_header_cell;
                DataGridViewHeaderCell entered_header_cell;
 
@@ -187,6 +187,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;
@@ -211,6 +212,7 @@ namespace System.Windows.Forms {
                        selectionMode = DataGridViewSelectionMode.RowHeaderSelect;
                        showCellErrors = true;
                        showEditingIcon = true;
+                       scrollBars = ScrollBars.Both;
                        userSetCursor = Cursor.Current;
                        virtualMode = false;
 
@@ -262,12 +264,22 @@ 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;
+                                       if (!value) {
+                                               if (new_row_editing)
+                                                       CancelEdit ();
+                                               RemoveEditingRow ();
+                                       } else {
+                                               PrepareEditingRow (false, false);
+                                       }
                                        OnAllowUserToAddRowsChanged(EventArgs.Empty);
-                                       PrepareEditingRow (false, false);
                                        Invalidate ();
                                }
                        }
@@ -275,7 +287,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;
@@ -566,12 +582,12 @@ namespace System.Windows.Forms {
                                        throw new InvalidOperationException("Cant change column count if DataSource is set.");
                                }
                                if (value < columns.Count) {
-                                       for (int i = value; i < columns.Count; i++) {
+                                       for (int i = columns.Count -1; i >= value; i--) {
                                                columns.RemoveAt(i);
                                        }
                                }
                                else if (value > columns.Count) {
-                                       for (int i = 0; i < value; i++) {
+                                       for (int i = columns.Count; i < value; i++) {
                                                DataGridViewTextBoxColumn col = new DataGridViewTextBoxColumn ();
                                                columns.Add(col);
                                        }
@@ -668,13 +684,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.");
-
-                               if (value != null)
-                                       MoveCurrentCell (value.OwningColumn.Index, value.OwningRow.Index, true, false, false, true);
                                else
-                                       MoveCurrentCell (-1, -1, true, false, false, true);
+                                       MoveCurrentCell (value.OwningColumn.Index, value.OwningRow.Index, true, false, false, true);
                        }
                }
 
@@ -698,12 +713,10 @@ namespace System.Windows.Forms {
                        get { return dataMember; }
                        set {
                                if (dataMember != value) {
-                                       ClearBinding ();
-                                       
                                        dataMember = value;
+                                       if (BindingContext != null)
+                                               ReBind ();
                                        OnDataMemberChanged(EventArgs.Empty);
-                                       
-                                       DoBinding ();
                                }
                        }
                }
@@ -723,12 +736,35 @@ namespace System.Windows.Forms {
                                if (!(value == null || value is IList || value is IListSource || value is IBindingList || value is IBindingListView))
                                        throw new NotSupportedException ("Type cannot be bound.");
                                        
-                               ClearBinding ();
-                               
-                               dataSource = value;
-                               OnDataSourceChanged (EventArgs.Empty);
-                               
-                               DoBinding ();
+                               if (value != DataSource) {
+                                       if (IsHandleCreated && value != null && BindingContext != null && BindingContext[value] != null)
+                                               DataMember = String.Empty;
+                                       ClearBinding ();
+       
+       
+                                       // Do not set dataSource prior to te BindingContext check because there is some lazy initialization 
+                                       // code which might result in double call to ReBind here and in OnBindingContextChanged
+                                       if (BindingContext != null) {
+                                               dataSource = value;
+                                               ReBind ();
+                                       } else {
+                                               dataSource = value;
+                                       }
+
+                                       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;
                        }
                }
 
@@ -884,11 +920,12 @@ namespace System.Windows.Forms {
                [Browsable (false)]
                public bool IsCurrentRowDirty {
                        get {
-                               if (!virtualMode) {
+                               if (!virtualMode)
                                        return IsCurrentCellDirty;
-                               }
-                               // Calcular
-                               throw new NotImplementedException();
+
+                               QuestionEventArgs args = new QuestionEventArgs ();
+                               OnRowDirtyStateNeeded (args);
+                               return args.Response;
                        }
                }
 
@@ -939,7 +976,7 @@ namespace System.Windows.Forms {
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                public int NewRowIndex {
                        get {
-                               if (!allowUserToAddRows || ColumnCount == 0) {
+                               if (!AllowUserToAddRows || ColumnCount == 0) {
                                        return -1;
                                }
                                return rows.Count - 1;
@@ -980,30 +1017,34 @@ 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) {
                                        throw new InvalidOperationException("Cant change row count if DataSource is set.");
                                }
+
                                if (value < rows.Count) {
-                                       for (int i = value; i < rows.Count; i++) {
+                                       int removeRangeEndIndex = rows.Count - 1;
+                                       if (AllowUserToAddRows)
+                                               removeRangeEndIndex--; // do not remove editing row
+
+                                       int removeRangeStartIndex = value - 1;
+                                       if (AllowUserToAddRows)
+                                               removeRangeStartIndex--; // remove an extra row before/instead of the editing row
+
+                                       for (int i = removeRangeEndIndex; i > removeRangeStartIndex; i--)
                                                rows.RemoveAt(i);
-                                       }
-                               }
-                               else if (value > rows.Count) {
+                               } else if (value > rows.Count) {
                                        // If we need to add rows and don't have any columns,
                                        // we create one column
                                        if (ColumnCount == 0)
                                                ColumnCount = 1;
 
-                                       for (int i = rows.Count; i < value; i++) {
-                                               DataGridViewRow row = (DataGridViewRow) RowTemplateFull;
-                                               rows.AddInternal (row, false);
-                                               
-                                               foreach (DataGridViewColumn col in columns)
-                                                       row.Cells.Add (col.CellTemplate.Clone () as DataGridViewCell);
-                                       }
+                                       List<DataGridViewRow> newRows = new List<DataGridViewRow> (value - rows.Count);
+                                       for (int i = rows.Count; i < value; i++)
+                                               newRows.Add ((DataGridViewRow) RowTemplateFull);
+                                       rows.AddRange (newRows.ToArray());
                                }
                        }
                }
@@ -1106,7 +1147,6 @@ namespace System.Windows.Forms {
                        }
                        set {
                                rowTemplate = value;
-                               rowTemplate.SetDataGridView(this);
                        }
                }
 
@@ -1148,6 +1188,8 @@ namespace System.Windows.Forms {
                                /// or canceled.
                                ///////////////////////////////////////////////////////////
                                scrollBars = value;
+                               PerformLayout ();
+                               Invalidate ();
                        }
                }
 
@@ -1272,8 +1314,16 @@ namespace System.Windows.Forms {
                                return topLeftHeaderCell;
                        }
                        set {
+                               if (topLeftHeaderCell == value)
+                                       return;
+
+                               if (topLeftHeaderCell != null)
+                                       topLeftHeaderCell.SetDataGridView (null);
+
                                topLeftHeaderCell = value;
-                               topLeftHeaderCell.SetDataGridView (this);
+
+                               if (topLeftHeaderCell != null)
+                                       topLeftHeaderCell.SetDataGridView (this);
                        }
                }
 
@@ -2232,13 +2282,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;
                        
@@ -2252,12 +2302,6 @@ namespace System.Windows.Forms {
                        if (e.Cancel)
                                return false;
 
-                       // If the user begins an edit in the NewRow, add a new row
-                       if (CurrentCell.RowIndex == NewRowIndex) {
-                               new_row_commited = false;
-                               OnUserAddedRow (new DataGridViewRowEventArgs (Rows[NewRowIndex]));
-                       }
-               
                        cell.SetIsInEditMode (true);
                        
                        // The cell has an editing control we need to setup
@@ -2283,7 +2327,8 @@ 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;
 
                                IDataGridViewEditingControl dgvEditingControl = (IDataGridViewEditingControl) EditingControlInternal;
                                if (dgvEditingControl != null) {
@@ -2305,21 +2350,21 @@ namespace System.Windows.Forms {
 
                public bool CancelEdit ()
                {
-                       if (currentCell != null && currentCell.IsInEditMode) {
-                               // The user's typing caused a new row to be created, but
-                               // now they are canceling that typing, we have to remove
-                               // the new row we added.
-                               if (!new_row_commited) {
-                                       DataGridViewRow delete_row = EditingRow;
-                                       Rows.RemoveInternal (delete_row);
-                                       editing_row = Rows[currentCell.RowIndex];
-                                       OnUserDeletedRow (new DataGridViewRowEventArgs (delete_row));
-                                       new_row_commited = true;
+                       if (currentCell != null) {
+                               if (currentCell.IsInEditMode) {
+                                       currentCell.SetIsInEditMode (false);
+                                       currentCell.DetachEditingControl ();
                                }
 
-                               currentCell.SetIsInEditMode (false);
-                               currentCell.DetachEditingControl ();
-                               OnCellEndEdit (new DataGridViewCellEventArgs (currentCell.ColumnIndex, currentCell.RowIndex));
+                               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;
@@ -2337,40 +2382,63 @@ namespace System.Windows.Forms {
 
                public bool CommitEdit (DataGridViewDataErrorContexts context)
                {
-                       if (currentCell != null && currentCell.OwningRow.DataBoundItem != null) {
-                               Object ob = currentCell.OwningRow.DataBoundItem;
-                               PropertyDescriptor property = TypeDescriptor.GetProperties (ob)[currentCell.OwningColumn.DataPropertyName];
-                               if (property != null && !property.IsReadOnly) {
-                                       try {
-                                               object value = currentCell.Value;
-                                               if (property.Converter != null && 
-                                                   property.Converter.CanConvertFrom (value.GetType()))
-                                                       value = property.Converter.ConvertFrom (value);
-                                               property.SetValue (ob, value);
-                                               return true;
-                                       } catch (Exception exc) {
-                                               DataGridViewDataErrorEventArgs args = new DataGridViewDataErrorEventArgs (exc, currentCell.ColumnIndex, 
-                                                                                                                         currentCell.RowIndex, context);
-                                               InternalOnDataError (args);
-                                               if (args.ThrowException)
-                                                       throw exc;
-                                       }
-                               }
+                       if (currentCell == null)
+                               return true;
+
+                       try {
+                               // convert
+                               object newValue = currentCell.ParseFormattedValue (currentCell.EditedFormattedValue, 
+                                                                                  currentCell.InheritedStyle, null, null);
+
+                               DataGridViewCellValidatingEventArgs validateArgs = new DataGridViewCellValidatingEventArgs (currentCell.ColumnIndex, 
+                                                                                                                           currentCell.RowIndex, 
+                                                                                                                           newValue);
+                               // validate
+                               OnCellValidating (validateArgs);
+                               if (validateArgs.Cancel)
+                                       return false;
+                               OnCellValidated (new DataGridViewCellEventArgs (currentCell.ColumnIndex, currentCell.RowIndex));
+
+                               // commit
+                               currentCell.Value = newValue;
+
+                       } 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")]
                public int DisplayedColumnCount (bool includePartialColumns)
                {
                        int result = 0;
-                       
-                       for (int i = first_col_index; i < Columns.Count; i++)
-                               if (Columns.ColumnDisplayIndexSortedArrayList[i].Displayed)
+                       int columnLeft = 0;
+
+                       if (RowHeadersVisible)
+                               columnLeft += RowHeadersWidth;
+
+                       Size visibleClientArea = ClientSize;
+                       if (verticalScrollBar.Visible)
+                               visibleClientArea.Width -= verticalScrollBar.Width;
+                       if (horizontalScrollBar.Visible)
+                               visibleClientArea.Height -= horizontalScrollBar.Height;
+
+                       for (int index = first_col_index; index < Columns.Count; index++) {
+                               DataGridViewColumn column = Columns[ColumnDisplayIndexToIndex (index)];
+                               if (columnLeft + column.Width <= visibleClientArea.Width) {
                                        result++;
-                               else
+                                       columnLeft += column.Width;
+                               } else {
+                                       if (includePartialColumns)
+                                               result++;
                                        break;
-
+                               }
+                       }
+                                       
                        return result;
                }
 
@@ -2382,9 +2450,15 @@ namespace System.Windows.Forms {
                        if (ColumnHeadersVisible)
                                rowTop += ColumnHeadersHeight;
 
+                       Size visibleClientArea = ClientSize;
+                       if (verticalScrollBar.Visible)
+                               visibleClientArea.Width -= verticalScrollBar.Width;
+                       if (horizontalScrollBar.Visible)
+                               visibleClientArea.Height -= horizontalScrollBar.Height;
+
                        for (int index = first_row_index; index < Rows.Count; index++) {
                                DataGridViewRow row = GetRowInternal (index);
-                               if (rowTop + row.Height < ClientSize.Height) {
+                               if (rowTop + row.Height <= visibleClientArea.Height) {
                                        result++;
                                        rowTop += row.Height;
                                } else {
@@ -2405,25 +2479,27 @@ namespace System.Windows.Forms {
                [MonoTODO ("Does not use context parameter")]
                public bool EndEdit (DataGridViewDataErrorContexts context)
                {
-                       if (currentCell != null && currentCell.IsInEditMode) {
-                               if (!CommitEdit (context))
-                                       return false;
-
-                               if (EditingControl != null) {
-                                       IDataGridViewEditingControl ctrl = EditingControl as IDataGridViewEditingControl;
-                                       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);
-                               }
+                       if (currentCell == null || !currentCell.IsInEditMode)
+                               return true;
 
-                               new_row_commited = true;
-                               OnCellEndEdit (new DataGridViewCellEventArgs (currentCell.ColumnIndex, currentCell.RowIndex));
+                       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;
                }
 
@@ -2480,7 +2556,10 @@ namespace System.Windows.Forms {
                        }
                        
                        for (int i = first_row_index; i < Rows.Count; i++) {
-                               if (i == rowIndex) {
+                               if (!rows[i].Visible)
+                                       continue;
+                                       
+                               if (rows[i].Index == rowIndex) {
                                        h = rows [i].Height;
                                        break;
                                }
@@ -2740,13 +2819,17 @@ namespace System.Windows.Forms {
                        if (ColumnHeadersVisible)
                                y += ColumnHeadersHeight;
 
+
                        for (int i = first_row_index; i < Rows.Count; i++) {
-                               if (i == rowIndex) {
-                                       h = rows[i].Height;
+                               if (!rows[i].Visible)
+                                       continue;
+                                       
+                               if (rows[i].Index == rowIndex) {
+                                       h = rows [i].Height;
                                        break;
                                }
-
-                               y += rows[i].Height;
+                               
+                               y += rows [i].Height;
                        }
 
                        return new Rectangle (0, y, Width, h);
@@ -2782,6 +2865,8 @@ namespace System.Windows.Forms {
                        
                        for (int i = first_row_index; i < Rows.Count; i++) {
                                DataGridViewRow row = Rows[i];
+                               if (!row.Visible)
+                                       continue;
                                
                                if (y > top && y <= (top + row.Height)) {
                                        rowindex = i;
@@ -2819,7 +2904,6 @@ namespace System.Windows.Forms {
                        return new HitTestInfo (-1, x, -1, y, DataGridViewHitTestType.None);
                }
 
-               [MonoTODO ("Invalidates whole grid")]
                public void InvalidateCell (DataGridViewCell dataGridViewCell)
                {
                        if (dataGridViewCell == null)
@@ -2831,7 +2915,6 @@ namespace System.Windows.Forms {
                        InvalidateCell (dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex);
                }
 
-               [MonoTODO ("Invalidates whole grid")]
                public void InvalidateCell (int columnIndex, int rowIndex)
                {
                        if (columnIndex < 0 || columnIndex >= columns.Count)
@@ -2840,25 +2923,26 @@ namespace System.Windows.Forms {
                        if (rowIndex < 0 || rowIndex >= rows.Count)
                                throw new ArgumentOutOfRangeException ("Row index is out of range.");
 
-                       Invalidate (GetCellDisplayRectangle (columnIndex, rowIndex, true));
+                       if (!is_binding)
+                               Invalidate (GetCellDisplayRectangle (columnIndex, rowIndex, true));
                }
 
-               [MonoTODO ("Invalidates whole grid")]
                public void InvalidateColumn (int columnIndex)
                {
                        if (columnIndex < 0 || columnIndex >= columns.Count)
                                throw new ArgumentOutOfRangeException ("Column index is out of range.");
 
-                       Invalidate (GetColumnDisplayRectangle (columnIndex, true));
+                       if (!is_binding)
+                               Invalidate (GetColumnDisplayRectangle (columnIndex, true));
                }
 
-               [MonoTODO ("Invalidates whole grid")]
                public void InvalidateRow (int rowIndex)
                {
                        if (rowIndex < 0 || rowIndex >= rows.Count)
                                throw new ArgumentOutOfRangeException ("Row index is out of range.");
 
-                       Invalidate (GetRowDisplayRectangle (rowIndex, true));
+                       if (!is_binding)
+                               Invalidate (GetRowDisplayRectangle (rowIndex, true));
                }
 
                public virtual void NotifyCurrentCellDirty (bool dirty) {
@@ -2949,11 +3033,10 @@ namespace System.Windows.Forms {
                        if (Rows.Count == 0)
                                return;
 
-                       IBindingList bindingList = DataSource as IBindingList;
                        if (dataGridViewColumn.IsDataBound) {
+                               IBindingList bindingList = DataManager.List as IBindingList;
                                if (bindingList != null && bindingList.SupportsSorting) {
-                                       CurrencyManager currencyManager = (CurrencyManager) this.BindingContext[DataSource];
-                                       bindingList.ApplySort (currencyManager.GetItemProperties()[dataGridViewColumn.DataPropertyName], direction);
+                                       bindingList.ApplySort (DataManager.GetItemProperties()[dataGridViewColumn.DataPropertyName], direction);
                                        dataGridViewColumn.HeaderCell.SortGlyphDirection = sortOrder;
                                }
                        } else {
@@ -3020,8 +3103,53 @@ namespace System.Windows.Forms {
                                InvalidateRow (i);
                }
 
-               public void UpdateRowHeightInfo (int rowIndex, bool updateToEnd) {
-                       throw new NotImplementedException();
+               public void UpdateRowHeightInfo (int rowIndex, bool updateToEnd)
+               {
+                       if (rowIndex < 0 && updateToEnd)
+                               throw new ArgumentOutOfRangeException ("rowIndex");
+                       if (rowIndex < -1 && !updateToEnd)
+                               throw new ArgumentOutOfRangeException ("rowIndex");
+                       if (rowIndex >= Rows.Count)
+                               throw new ArgumentOutOfRangeException ("rowIndex");
+                       
+                       if (!VirtualMode && DataManager == null)
+                               return;
+
+                       if (rowIndex == -1) {
+                               updateToEnd = true;
+                               rowIndex = 0;
+                       }
+
+                       if (updateToEnd) {
+                               for (int i = rowIndex; i < Rows.Count; i++) {
+                                       DataGridViewRow row = Rows[i];
+                                       if (!row.Visible)
+                                               continue;
+
+                                       DataGridViewRowHeightInfoNeededEventArgs rowInfo = 
+                                               new DataGridViewRowHeightInfoNeededEventArgs (row.Index, row.Height, row.MinimumHeight);
+                                       OnRowHeightInfoNeeded (rowInfo);
+
+                                       if (row.Height != rowInfo.Height || row.MinimumHeight != rowInfo.MinimumHeight) {
+                                               row.Height = rowInfo.Height;
+                                               row.MinimumHeight = rowInfo.MinimumHeight;
+                                               OnRowHeightInfoPushed (new DataGridViewRowHeightInfoPushedEventArgs (row.Index, rowInfo.Height, 
+                                                                                                                    rowInfo.MinimumHeight));
+                                       }
+                               }
+                       } else {
+                               DataGridViewRow row = Rows[rowIndex];
+                               DataGridViewRowHeightInfoNeededEventArgs rowInfo = 
+                                       new DataGridViewRowHeightInfoNeededEventArgs (row.Index, row.Height, row.MinimumHeight);
+                               OnRowHeightInfoNeeded (rowInfo);
+
+                               if (row.Height != rowInfo.Height || row.MinimumHeight != rowInfo.MinimumHeight) {
+                                       row.Height = rowInfo.Height;
+                                       row.MinimumHeight = rowInfo.MinimumHeight;
+                                       OnRowHeightInfoPushed (new DataGridViewRowHeightInfoPushedEventArgs (row.Index, rowInfo.Height, 
+                                                                                                            rowInfo.MinimumHeight));
+                               }
+                       }
                }
 
                protected override bool CanEnableIme {
@@ -3136,6 +3264,8 @@ namespace System.Windows.Forms {
                        }
                        
                        foreach (DataGridViewRow row in Rows) {
+                               if (!row.Visible)
+                                       continue;
                                if (!displayed_only || row.Displayed) {
                                        int new_height = row.GetPreferredHeight (row.Index, mode, fixedWidth);
 
@@ -3347,6 +3477,7 @@ namespace System.Windows.Forms {
                protected override void OnBindingContextChanged (EventArgs e)
                {
                        base.OnBindingContextChanged(e);
+                       ReBind();
                }
 
                protected virtual void OnBorderStyleChanged (EventArgs e)
@@ -3442,6 +3573,9 @@ namespace System.Windows.Forms {
 
                protected virtual void OnCellEnter (DataGridViewCellEventArgs e)
                {
+                       DataGridViewCell cell = GetCellInternal (e.ColumnIndex, e.RowIndex);
+                       cell.OnEnterInternal (e.RowIndex, true);
+
                        DataGridViewCellEventHandler eh = (DataGridViewCellEventHandler)(Events [CellEnterEvent]);
                        if (eh != null)
                                eh (this, e);
@@ -3475,6 +3609,9 @@ namespace System.Windows.Forms {
 
                protected virtual void OnCellLeave (DataGridViewCellEventArgs e)
                {
+                       DataGridViewCell cell = GetCellInternal (e.ColumnIndex, e.RowIndex);
+                       cell.OnLeaveInternal (e.RowIndex, true);
+
                        DataGridViewCellEventHandler eh = (DataGridViewCellEventHandler)(Events [CellLeaveEvent]);
                        if (eh != null)
                                eh (this, e);
@@ -3652,15 +3789,42 @@ namespace System.Windows.Forms {
                internal void OnColumnAddedInternal (DataGridViewColumnEventArgs e)
                {
                        if (e.Column.CellTemplate != null) {
-                               foreach (DataGridViewRow row in Rows)
-                                       row.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) {
+                                       DataGridViewCell newCell = (DataGridViewCell)e.Column.CellTemplate.Clone ();
+                                       if (row.Cells.Count == columns.Count)
+                                               row.Cells.Replace (e.Column.Index, newCell);
+                                       else if (e.Column.Index >= row.Cells.Count)
+                                               row.Cells.Add (newCell);
+                                       else
+                                               row.Cells.Insert (e.Column.Index, newCell);
+                               }
                        }
                        
+                       e.Column.DataColumnIndex = FindDataColumnIndex (e.Column);
                        AutoResizeColumnsInternal ();
                        OnColumnAdded (e);
                        PrepareEditingRow (false, true);
                }
 
+               private int FindDataColumnIndex (DataGridViewColumn column)
+               {
+                       if (column != null && DataManager != null) {
+                               PropertyDescriptorCollection properties = DataManager.GetItemProperties();
+                               for (int i = 0; i < properties.Count; i++) {
+                                       if (String.Compare (column.DataPropertyName, properties[i].Name, true) == 0)
+                                               return i;
+                               }
+                       }
+
+                       return -1;
+               }
+
                protected virtual void OnColumnAdded (DataGridViewColumnEventArgs e)
                {
                        DataGridViewColumnEventHandler eh = (DataGridViewColumnEventHandler)(Events [ColumnAddedEvent]);
@@ -3788,7 +3952,22 @@ namespace System.Windows.Forms {
                                eh (this, e);
                }
 
-               internal void OnColumnRemovedInternal (DataGridViewColumnEventArgs e)
+               internal void OnColumnPreRemovedInternal (DataGridViewColumnEventArgs e)
+               {
+                       if (Columns.Count - 1 == 0) {
+                               MoveCurrentCell (-1, -1, true, false, false, true);
+                               rows.ClearInternal ();
+                       } else if (currentCell != null && CurrentCell.ColumnIndex == e.Column.Index) {
+                               int nextColumnIndex = e.Column.Index;
+                               if (nextColumnIndex >= Columns.Count - 1)
+                                       nextColumnIndex = Columns.Count - 1 - 1;
+                               MoveCurrentCell (nextColumnIndex, currentCell.RowIndex, true, false, false, true);
+                               if (hover_cell != null && hover_cell.ColumnIndex >= e.Column.Index)
+                                       hover_cell = null;
+                       }
+               }
+
+               private void OnColumnPostRemovedInternal (DataGridViewColumnEventArgs e)
                {
                        if (e.Column.CellTemplate != null) {
                                int index = e.Column.Index;
@@ -3798,8 +3977,9 @@ namespace System.Windows.Forms {
                        }
 
                        AutoResizeColumnsInternal ();
-                       OnColumnRemoved (e);
                        PrepareEditingRow (false, true);
+
+                       OnColumnRemoved (e);
                }
 
                protected virtual void OnColumnRemoved (DataGridViewColumnEventArgs e)
@@ -3898,6 +4078,11 @@ namespace System.Windows.Forms {
 
                protected override void OnDoubleClick (EventArgs e) {
                        base.OnDoubleClick(e);
+
+                       Point mouseLocation = this.PointToClient (Control.MousePosition);
+                       HitTestInfo hitInfo = HitTest (mouseLocation.X, mouseLocation.Y);
+                       if (hitInfo.Type == DataGridViewHitTestType.Cell)
+                               OnCellDoubleClick (new DataGridViewCellEventArgs (hitInfo.ColumnIndex, hitInfo.RowIndex));
                }
 
                protected virtual void OnEditingControlShowing (DataGridViewEditingControlShowingEventArgs e) {
@@ -3952,8 +4137,9 @@ namespace System.Windows.Forms {
                protected override void OnHandleCreated (EventArgs e)
                {
                        base.OnHandleCreated(e);
+                       ReBind ();
                        
-                       if (CurrentCell == null && Rows.Count > 0 && Columns.Count > 0)
+                       if (DataManager == null && CurrentCell == null && Rows.Count > 0 && Columns.Count > 0)
                                MoveCurrentCell (ColumnDisplayIndexToIndex (0), 0, true, false, false, false);
                }
 
@@ -4047,6 +4233,11 @@ namespace System.Windows.Forms {
                protected override void OnMouseDoubleClick (MouseEventArgs e)
                {
                        base.OnMouseDoubleClick(e);
+
+                       HitTestInfo hitInfo = HitTest (e.X, e.Y);
+                       if (hitInfo.Type == DataGridViewHitTestType.Cell)
+                               OnCellMouseDoubleClick (new DataGridViewCellMouseEventArgs (hitInfo.ColumnIndex, hitInfo.RowIndex,
+                                                                                           hitInfo.ColumnX, hitInfo.RowY, e));
                }
 
                private void DoSelectionOnMouseDown (HitTestInfo hitTest)
@@ -4192,15 +4383,18 @@ 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 (!EndEdit())
-                                       return;
+                       if ((hitTest.Type == DataGridViewHitTestType.ColumnHeader ||
+                            (hitTest.Type == DataGridViewHitTestType.Cell && !ColumnHeadersVisible)) 
+                           && MouseOverColumnResize (hitTest.ColumnIndex, e.X)) {
                                if (e.Clicks == 2) {
                                        AutoResizeColumn (hitTest.ColumnIndex);
                                        return;
@@ -4215,8 +4409,6 @@ namespace System.Windows.Forms {
                        }
 
                        if (hitTest.Type == DataGridViewHitTestType.RowHeader && MouseOverRowResize (hitTest.RowIndex, e.Y)) {
-                               if (!EndEdit())
-                                       return;
                                if (e.Clicks == 2) {
                                        AutoResizeRow (hitTest.RowIndex);
                                        return;
@@ -4256,11 +4448,8 @@ namespace System.Windows.Forms {
 
                private void UpdateBindingPosition (int position)
                {
-                       if (DataSource != null && BindingContext != null) {
-                               CurrencyManager currencyManager = this.BindingContext[DataSource] as CurrencyManager;
-                               if (currencyManager != null)
-                                       currencyManager.Position = position;
-                       }
+                       if (DataManager != null)
+                               DataManager.Position = position;
                }
 
                protected override void OnMouseEnter (EventArgs e)
@@ -4309,7 +4498,12 @@ namespace System.Windows.Forms {
                        Cursor new_cursor = Cursors.Default;
                        HitTestInfo hit = this.HitTest (e.X, e.Y);
                        
-                       if (hit.Type == DataGridViewHitTestType.Cell) {
+                       if (hit.Type == DataGridViewHitTestType.ColumnHeader || 
+                           (!ColumnHeadersVisible && hit.Type == DataGridViewHitTestType.Cell && MouseOverColumnResize (hit.ColumnIndex, e.X))) {
+                               EnteredHeaderCell = Columns [hit.ColumnIndex].HeaderCell;
+                               if (MouseOverColumnResize (hit.ColumnIndex, e.X))
+                                       new_cursor = Cursors.VSplit;
+                       } else if (hit.Type == DataGridViewHitTestType.Cell) {
                                EnteredHeaderCell = null;
 
                                DataGridViewCell new_cell = GetCellInternal (hit.ColumnIndex, hit.RowIndex);
@@ -4330,6 +4524,8 @@ namespace System.Windows.Forms {
                                                MouseLeftErrorIcon (new_cell);
                                }
                                
+                               Cursor = new_cursor;
+
                                // We have never been in a cell before
                                if (hover_cell == null) {
                                        hover_cell = new_cell;
@@ -4405,13 +4601,7 @@ namespace System.Windows.Forms {
                                }
                        
                        } else {
-                               if (hit.Type == DataGridViewHitTestType.ColumnHeader) {
-                                       EnteredHeaderCell = Columns [hit.ColumnIndex].HeaderCell;
-                                       
-                                       if (MouseOverColumnResize (hit.ColumnIndex, e.X))
-                                               new_cursor = Cursors.VSplit;
-                               } else
-                                       EnteredHeaderCell = null;
+                               EnteredHeaderCell = null;
 
                                // We have left the cell area
                                if (hover_cell != null) {
@@ -4467,6 +4657,14 @@ namespace System.Windows.Forms {
                protected override void OnMouseWheel (MouseEventArgs e)
                {
                        base.OnMouseWheel(e);
+
+                       int delta = SystemInformation.MouseWheelScrollLines * verticalScrollBar.SmallChange;
+                       if (e.Delta < 0)
+                               verticalScrollBar.SafeValueSet (verticalScrollBar.Value + delta);
+                       else
+                               verticalScrollBar.SafeValueSet (verticalScrollBar.Value - delta);
+
+                       OnVScrollBarScroll (this, new ScrollEventArgs (ScrollEventType.ThumbPosition, verticalScrollBar.Value));
                }
 
                protected virtual void OnMultiSelectChanged (EventArgs e)
@@ -4485,8 +4683,6 @@ namespace System.Windows.Forms {
 
                protected override void OnPaint (PaintEventArgs e)
                {
-                       base.OnPaint(e);
-
                        Graphics g = e.Graphics;
                        Rectangle bounds = ClientRectangle;
                        
@@ -4533,16 +4729,12 @@ namespace System.Windows.Forms {
                                bounds.Y += columnHeadersHeight;
                        }
                        
-                       gridWidth = rowHeadersVisible ? rowHeadersWidth : 0;
-                       gridHeight = 0;
-                       
-                       int first_row_height = Rows.Count > 0 ? Rows[Math.Min (Rows.Count - 1, first_row_index)].Height : 0;
-//                     int room_left = this.Height;
-                       
-                       // Reset all columns to !Displayed
-                       for (int i = 0; i < Columns.Count; i++)
+                       // Reset not displayed columns to !Displayed
+                       for (int i = 0; i < first_col_index; i++)
                                Columns[i].DisplayedInternal = false;
                        
+                       int gridWidth = rowHeadersVisible ? rowHeadersWidth : 0;
+
                        // Set Displayed columns
                        for (int i = first_col_index; i < Columns.Count; i++) {
                                DataGridViewColumn col = Columns.ColumnDisplayIndexSortedArrayList[i];
@@ -4552,18 +4744,19 @@ namespace System.Windows.Forms {
                        
                                col.DisplayedInternal = true;
                                gridWidth += col.Width;
-                               
                                if (gridWidth >= Width)
                                        break;
                        }
                        
-                       // Reset all rows to !Displayed
-                       for (int i = 0; i < Rows.Count; i++)
+                       // Reset all not displayed rows to !Displayed
+                       for (int i = 0; i < first_row_index; i++)
                                GetRowInternal (i).DisplayedInternal = false;
                        
                        // Draw rows
                        for (int index = first_row_index; index < Rows.Count; index++) {
                                DataGridViewRow row = Rows[index];
+                               if (!row.Visible)
+                                       continue;
                                GetRowInternal (index).DisplayedInternal = true;
        
                                bounds.Height = row.Height;
@@ -4577,80 +4770,99 @@ namespace System.Windows.Forms {
                                
                                if (bounds.Y >= ClientSize.Height - (horizontalScrollBar.Visible ? horizontalScrollBar.Height : 0))
                                        break;
-                                       
-                               gridHeight += row.Height;
                        }
 
-                       gridWidth = 0;
+                       RefreshScrollBars ();
                        
-                       foreach (DataGridViewColumn col in sortedColumns)
+                       // Paint the bottom right square if both scrollbars are displayed
+                       if (horizontalScrollBar.Visible && verticalScrollBar.Visible)
+                               g.FillRectangle (SystemBrushes.Control, new Rectangle (horizontalScrollBar.Right, verticalScrollBar.Bottom, verticalScrollBar.Width, horizontalScrollBar.Height));
+
+                       // Paint the border
+                       bounds = ClientRectangle;
+                       
+                       switch (BorderStyle) {
+                               case BorderStyle.FixedSingle:
+                                       g.DrawRectangle (Pens.Black, new Rectangle (bounds.Left, bounds.Top, bounds.Width - 1, bounds.Height - 1));
+                                       break;
+                               case BorderStyle.Fixed3D:
+                                       ControlPaint.DrawBorder3D (g, bounds, Border3DStyle.Sunken);
+                                       break;
+                       }
+
+                       // Call the base impl at the end.
+                       base.OnPaint(e);
+               }
+
+               private void RefreshScrollBars ()
+               {
+                       int gridWidth = 0;
+                       int gridHeight = 0;
+
+                       foreach (DataGridViewColumn col in columns.ColumnDisplayIndexSortedArrayList)
                                if (col.Visible)
                                        gridWidth += col.Width;
-
-                       gridHeight = 0;
                        
                        foreach (DataGridViewRow row in Rows)
-                               gridHeight += row.Height;
+                               if (row.Visible)
+                                       gridHeight += row.Height;
 
                        if (rowHeadersVisible)
                                gridWidth += rowHeadersWidth;
-
                        if (columnHeadersVisible)
                                gridHeight += columnHeadersHeight;
-                       
+
                        bool horizontalVisible = false;
                        bool verticalVisible = false;
                        
                        if (AutoSize) {
-                               if (gridWidth > Size.Width || gridHeight > Size.Height) {
+                               if (gridWidth > Size.Width || gridHeight > Size.Height)
                                        Size = new Size(gridWidth, gridHeight);
-                               }
                        }
                        else {
-                               if (gridWidth > Size.Width) {
+                               if (gridWidth > Size.Width)
                                        horizontalVisible = true;
-                               }
-                               if (gridHeight > Size.Height) {
+                               if (gridHeight > Size.Height)
                                        verticalVisible = true;
-                               }
-                               if (horizontalScrollBar.Visible && (gridHeight + horizontalScrollBar.Height) > Size.Height) {
+
+                               if (horizontalScrollBar.Visible && (gridHeight + horizontalScrollBar.Height) > Size.Height)
                                        verticalVisible = true;
-                               }
-                               if (verticalScrollBar.Visible && (gridWidth + verticalScrollBar.Width) > Size.Width) {
+                               if (verticalScrollBar.Visible && (gridWidth + verticalScrollBar.Width) > Size.Width) 
                                        horizontalVisible = true;
-                               }
+
+                               if (scrollBars != ScrollBars.Vertical && scrollBars != ScrollBars.Both)
+                                       verticalVisible = false;
+                               if (scrollBars != ScrollBars.Horizontal && scrollBars != ScrollBars.Both)
+                                       horizontalVisible = false;
+
+                               // MSNET compatibility here
+                               if (RowCount <= 1)
+                                       verticalVisible = false;
+
                                if (horizontalVisible) {
                                        horizontalScrollBar.Minimum = 0;
                                        horizontalScrollBar.Maximum = gridWidth;
                                        horizontalScrollBar.SmallChange = Columns[first_col_index].Width;
-                                       horizontalScrollBar.LargeChange = ClientSize.Width - rowHeadersWidth;
+                                       int largeChange = ClientSize.Width - rowHeadersWidth - horizontalScrollBar.Height;
+                                       if (largeChange <= 0)
+                                               largeChange = ClientSize.Width;
+                                       horizontalScrollBar.LargeChange = largeChange;
                                }
+
                                if (verticalVisible) {
                                        verticalScrollBar.Minimum = 0;
                                        verticalScrollBar.Maximum = gridHeight;
+                                       int first_row_height = Rows.Count > 0 ? Rows[Math.Min (Rows.Count - 1, first_row_index)].Height : 0;
                                        verticalScrollBar.SmallChange = first_row_height + 1;
-                                       verticalScrollBar.LargeChange = ClientSize.Height - columnHeadersHeight;
+                                       int largeChange = ClientSize.Height - columnHeadersHeight - verticalScrollBar.Width;
+                                       if (largeChange <= 0)
+                                               largeChange = ClientSize.Height;
+                                       verticalScrollBar.LargeChange = largeChange;
                                }
                        }
 
                        horizontalScrollBar.Visible = horizontalVisible;
                        verticalScrollBar.Visible = verticalVisible;
-                       
-                       // Paint the bottom right square if both scrollbars are displayed
-                       if (horizontalScrollBar.Visible && verticalScrollBar.Visible)
-                               g.FillRectangle (SystemBrushes.Control, new Rectangle (horizontalScrollBar.Right, verticalScrollBar.Bottom, verticalScrollBar.Width, horizontalScrollBar.Height));
-
-                       // Paint the border
-                       bounds = ClientRectangle;
-                       
-                       switch (BorderStyle) {
-                               case BorderStyle.FixedSingle:
-                                       g.DrawRectangle (Pens.Black, new Rectangle (bounds.Left, bounds.Top, bounds.Width - 1, bounds.Height - 1));
-                                       break;
-                               case BorderStyle.Fixed3D:
-                                       ControlPaint.DrawBorder3D (g, bounds, Border3DStyle.Sunken);
-                                       break;
-                       }
                }
 
                protected virtual void OnReadOnlyChanged (EventArgs e) {
@@ -4770,6 +4982,7 @@ namespace System.Windows.Forms {
 
                protected internal virtual void OnRowHeightChanged (DataGridViewRowEventArgs e)
                {
+                       UpdateRowHeightInfo (e.Row.Index, false);
                        DataGridViewRowEventHandler eh = (DataGridViewRowEventHandler)(Events [RowHeightChangedEvent]);
                        if (eh != null) eh (this, e);
                }
@@ -4812,11 +5025,20 @@ namespace System.Windows.Forms {
 
                internal void OnRowsAddedInternal (DataGridViewRowsAddedEventArgs e)
                {
+                       if (hover_cell != null && hover_cell.RowIndex >= e.RowIndex)
+                               hover_cell = null;
+
+                       // Select the first row if we are not databound. 
+                       // If we are databound selection is managed by the data manager.
+                       if (IsHandleCreated && DataManager == null && CurrentCell == null && Rows.Count > 0 && Columns.Count > 0)
+                               MoveCurrentCell (ColumnDisplayIndexToIndex (0), 0, true, false, false, true);
+
+                       AutoResizeColumnsInternal ();
                        Invalidate ();
                        OnRowsAdded (e);
                }
 
-               protected internal virtual void OnRowsAdded (DataGridViewRowsAddedEventArgs e)
+               protected virtual void OnRowsAdded (DataGridViewRowsAddedEventArgs e)
                {
                        DataGridViewRowsAddedEventHandler eh = (DataGridViewRowsAddedEventHandler)(Events [RowsAddedEvent]);
                        if (eh != null) eh (this, e);
@@ -4828,16 +5050,32 @@ namespace System.Windows.Forms {
                        if (eh != null) eh (this, e);
                }
 
-               internal void OnRowsRemovedInternal (DataGridViewRowsRemovedEventArgs e)
+               internal void OnRowsPreRemovedInternal (DataGridViewRowsRemovedEventArgs e)
                {
                        if (selected_rows != null)
                                selected_rows.InternalClear ();
                        if (selected_columns != null)
                                selected_columns.InternalClear ();
 
-                       if (Rows.Count > 0 && Columns.Count > 0 && currentCell != null && 
-                           currentCell.RowIndex >= e.RowIndex)
-                               MoveCurrentCell (0, Math.Min (e.RowIndex, Rows.Count - 2), true, false, false, true);
+                       if (Rows.Count - e.RowCount <= 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 if (currentCell != null && currentCell.RowIndex == e.RowIndex) {
+                               int nextRowIndex = e.RowIndex;
+                               if (nextRowIndex >= Rows.Count - e.RowCount)
+                                       nextRowIndex = Rows.Count - 1 - e.RowCount;
+                               MoveCurrentCell (currentCell != null ? currentCell.ColumnIndex : 0, nextRowIndex, 
+                                                true, false, false, true);
+                               if (hover_cell != null && hover_cell.RowIndex >= e.RowIndex)
+                                       hover_cell = null;
+                       }
+               }
+
+               internal void OnRowsPostRemovedInternal (DataGridViewRowsRemovedEventArgs e)
+               {
                        Invalidate ();
                        OnRowsRemoved (e);
                }
@@ -4897,11 +5135,19 @@ namespace System.Windows.Forms {
 
                protected virtual void OnUserAddedRow (DataGridViewRowEventArgs e)
                {
-                       editing_row = null;
                        PrepareEditingRow (false, false);
 
-                       e = new DataGridViewRowEventArgs (editing_row);
-                       
+                       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);
                }
@@ -4910,7 +5156,6 @@ namespace System.Windows.Forms {
                {
                        DataGridViewRowEventHandler eh = (DataGridViewRowEventHandler)(Events [UserDeletedRowEvent]);
                        if (eh != null) eh (this, e);
-
                }
 
                protected virtual void OnUserDeletingRow (DataGridViewRowCancelEventArgs e)
@@ -4990,7 +5235,7 @@ namespace System.Windows.Forms {
 
                protected bool ProcessDeleteKey (Keys keyData)
                {
-                       if (!allowUserToDeleteRows || SelectedRows.Count == 0)
+                       if (!AllowUserToDeleteRows || SelectedRows.Count == 0)
                                return false;
 
                        int index = Math.Max (selected_row - SelectedRows.Count + 1, 0);
@@ -5004,8 +5249,8 @@ namespace System.Windows.Forms {
                                if (hover_cell != null && hover_cell.OwningRow == row)
                                        hover_cell = null;
                                        
-                               if (DataSource != null && DataSource is DataSet)
-                                       (DataSource as DataSet).Tables[dataMember].Rows.RemoveAt (row.Index);
+                               if (DataManager != null)
+                                       DataManager.RemoveAt (row.Index);
                                else
                                        Rows.RemoveAt (row.Index);
                        }
@@ -5131,7 +5376,7 @@ namespace System.Windows.Forms {
                        return false;
                }
 
-               [MonoTODO ("What does insert do?")]
+               [MonoInternalNote ("What does insert do?")]
                protected bool ProcessInsertKey (Keys keyData)
                {
                        return false;
@@ -5141,9 +5386,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);
                }
@@ -5368,28 +5616,57 @@ 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)
-                                               EndEdit ();
+                                       if (currentCell.IsInEditMode) {
+                                               if (!EndEdit ())
+                                                       return false;
+                                               else if (currentCell.RowIndex == NewRowIndex && new_row_editing)
+                                                       CancelEdit ();
+                                       } else {
+                                               // CancelEdit will replace the uncommited real editing row with a place holder row
+                                               if (new_row_editing && currentCell.RowIndex == NewRowIndex)
+                                                       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);
 
-                               UpdateBindingPosition (currentCell.RowIndex);
-                               OnRowEnter (new DataGridViewCellEventArgs (cell.ColumnIndex, cell.RowIndex));
-                               OnCellEnter (new DataGridViewCellEventArgs(cell.ColumnIndex, cell.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 (throughMouseClick || editMode == DataGridViewEditMode.EditOnEnter)
-                                       BeginEdit (true);
+
+                               if (cell != null) {
+                                       // If the user begins an edit in the NewRow, add a new real 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 (throughMouseClick)
+                               if (cell != null && throughMouseClick)
                                        BeginEdit (true);
                        }
 
@@ -5427,7 +5704,8 @@ namespace System.Windows.Forms {
                }
 
                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) {
@@ -5485,13 +5763,18 @@ namespace System.Windows.Forms {
 
                internal void OnHScrollBarScroll (object sender, ScrollEventArgs e)
                {
+                       int lastRightVisibleColumntIndex = Columns.Count - DisplayedColumnCount (false);
                        horizontalScrollingOffset = e.NewValue;
                        int left = 0;
 
                        for (int index = 0; index < Columns.Count; index++) {
                                DataGridViewColumn col = Columns[index];
 
-                               if (e.NewValue < left + col.Width) {
+                               if (col.Index >= lastRightVisibleColumntIndex) {
+                                       first_col_index = lastRightVisibleColumntIndex;
+                                       Invalidate ();
+                                       OnScroll (e);
+                               } else if (e.NewValue < left + col.Width) {
                                        if (first_col_index != index) {
                                                first_col_index = index;
                                                Invalidate ();
@@ -5512,10 +5795,18 @@ namespace System.Windows.Forms {
                                return;
 
                        int top = 0;
-                       
+                       int lastTopVisibleRowIndex = Rows.Count - DisplayedRowCount (false);
+
                        for (int index = 0; index < Rows.Count; index++) {
                                DataGridViewRow row = Rows[index];
-                               if (e.NewValue < top + row.Height) {
+                               if (!row.Visible)
+                                       continue;
+
+                               if (row.Index >= lastTopVisibleRowIndex) {
+                                       first_row_index = lastTopVisibleRowIndex;
+                                       Invalidate ();
+                                       OnScroll (e);
+                               } else if (e.NewValue < top + row.Height) {
                                        if (first_row_index != index) {
                                                first_row_index = index;
                                                Invalidate ();
@@ -5528,7 +5819,7 @@ namespace System.Windows.Forms {
                                top += row.Height;
                        }
                        
-                       first_row_index = Rows.Count - DisplayedRowCount (false);
+                       first_row_index = lastTopVisibleRowIndex;
                        Invalidate ();
                        OnScroll (e);
                }
@@ -5543,9 +5834,11 @@ namespace System.Windows.Forms {
                                        OnColumnAddedInternal(new DataGridViewColumnEventArgs(e.Element as DataGridViewColumn));
                                        break;
                                case CollectionChangeAction.Remove:
-                                       OnColumnRemovedInternal(new DataGridViewColumnEventArgs(e.Element as DataGridViewColumn));
+                                       OnColumnPostRemovedInternal(new DataGridViewColumnEventArgs(e.Element as DataGridViewColumn));
                                        break;
                                case CollectionChangeAction.Refresh:
+                                       hover_cell = null;
+                                       MoveCurrentCell (-1, -1, true, false, false, true);
                                        break;
                        }
                }
@@ -5578,6 +5871,9 @@ namespace System.Windows.Forms {
                        for (int i = 0; i < Columns.Count; i++) {
                                DataGridViewColumn col = Columns [i];
 
+                               if (!col.Visible)
+                                       continue;
+
                                switch (col.InheritedAutoSizeMode) {
                                case DataGridViewAutoSizeColumnMode.Fill:
                                        FillCount++;
@@ -5604,6 +5900,9 @@ namespace System.Windows.Forms {
                                        
                                        if (col.InheritedAutoSizeMode != DataGridViewAutoSizeColumnMode.Fill)
                                                continue;
+                               
+                                       if (!col.Visible)
+                                               continue;
                                                
                                        if (fixed_widths [i] != 0)
                                                continue;
@@ -5628,7 +5927,10 @@ namespace System.Windows.Forms {
                        for (int i = 0; i < columns.Count; i++) {
                                if (Columns [i].InheritedAutoSizeMode != DataGridViewAutoSizeColumnMode.Fill)
                                        continue;
-                                       
+
+                               if (!Columns[i].Visible)
+                                       continue;
+
                                Columns [i].Width = new_widths [i];
                        }
                }
@@ -5669,24 +5971,20 @@ namespace System.Windows.Forms {
                internal int CalculateColumnCellWidth (int index, DataGridViewAutoSizeColumnMode mode)
                {
                        int first_row = 0;
+                       int last_row = Rows.Count;
                        int result = 0;
-                       bool only_visible = false;
-                       
-                       if (mode == DataGridViewAutoSizeColumnMode.DisplayedCellsExceptHeader || 
-                               mode == DataGridViewAutoSizeColumnMode.AllCellsExceptHeader)
-                               first_row++;
-                       
-                       only_visible = (mode == DataGridViewAutoSizeColumnMode.DisplayedCells || mode == DataGridViewAutoSizeColumnMode.DisplayedCellsExceptHeader);
+
+                       if (mode == DataGridViewAutoSizeColumnMode.DisplayedCells || 
+                           mode == DataGridViewAutoSizeColumnMode.DisplayedCellsExceptHeader) {
+                               first_row = first_row_index;
+                               last_row = DisplayedRowCount (true);;
+                       }
                        
-                       for (int i = first_row; i < Rows.Count; i++) {
-                               if (only_visible) {
-                                       Rectangle row_rect = this.GetRowDisplayRectangle (i, false);
-                                       if (!ClientRectangle.IntersectsWith (row_rect))
-                                               continue;
-                               }
+                       for (int i = first_row; i < last_row; i++) {
+                               if (!Rows[i].Visible)
+                                       continue;
                                
                                int cell_width = Rows[i].Cells[index].PreferredSize.Width;
-
                                result = Math.Max (result, cell_width);
                        }
                        
@@ -5719,95 +6017,42 @@ namespace System.Windows.Forms {
                        return bounds;
                }
 
-               internal void PrepareEditingRow (bool cell_changed, bool column_changed)
+               private 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.RemoveInternal (editing_row);
-                               editing_row = null;
+                       if (!show) {
+                               RemoveEditingRow ();
                        } 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.RemoveInternal (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.
+                                       RemoveEditingRow ();
                                }
                                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 ());
-                               } else if (list is BindingSource && (list as BindingSource).item_type != null) {
-                                       foreach (PropertyDescriptor property in TypeDescriptor.GetProperties ((list as BindingSource).item_type)) {
-                                               DataGridViewColumn col = CreateColumnByType (property.PropertyType);
-                                               col.Name = property.DisplayName;
-                                               col.ReadOnly = property.IsReadOnly;
-                                               col.AutoGenerated = true;
-                                               columns.Add (col);
-                                       }
-
-                                       AllowUserToAddRows = (list as BindingSource).AllowNew;
-                               }
-                       }
-               
-                       // Subscribe to the dataset's change notification
-                       if (list is DataView) {
-                               (list as DataView).ListChanged += OnListChanged;
-                               (list as DataView).Table.ColumnChanged += OnTableColumnChanged;
-                               (list as DataView).Table.TableCleared += OnTableCleared;
+               internal void RemoveEditingRow ()
+               {
+                       if (editing_row != null) {
+                               if (Rows.Contains (editing_row))
+                                   Rows.RemoveInternal (editing_row);
+                               editing_row = null;
                        }
-
-                       // Add the rows
-                       foreach (object element in list)
-                               AddBoundRow (element);
                }
 
-               private void OnBindingSourceDataSourceChanged (object sender, EventArgs args)
-               {
-                       ClearBinding();
-                       DoBinding();
+               internal DataGridViewRow EditingRow {
+                       get { return editing_row; }
                }
 
                private void AddBoundRow (object element)
@@ -5817,83 +6062,53 @@ namespace System.Windows.Forms {
                                return;
                                
                        DataGridViewRow row = (DataGridViewRow)RowTemplateFull;
-                       rows.InternalAdd (row);
-
-                       PropertyDescriptorCollection properties = TypeDescriptor.GetProperties (element);
-                       
-                       foreach (PropertyDescriptor property in properties) {
-                               if (property.PropertyType == typeof (IBindingList))
-                                       continue;
-                               
-                               // We do it this way because there may not be a column
-                               // for every cell, ignore cells with no column  
-                               DataGridViewCell cell = row.Cells.GetBoundCell (property.Name);
-                               
-                               if (cell == null)
-                                       continue;
-                                       
-                               cell.valuex = property.GetValue (element);
-                               cell.valueType = property.PropertyType;
-                       }
+                       rows.AddInternal (row, false);
                }
                
-               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 (String.Compare (col.DataPropertyName, name, true) == 0)
+                                       return true;
+
+                       return false;
                }
-               
+
                private DataGridViewColumn CreateColumnByType (Type type)
                {
                        if (type == typeof (bool))
                                return new DataGridViewCheckBoxColumn ();
+                       else if (typeof(Bitmap).IsAssignableFrom (type))
+                               return new DataGridViewImageColumn ();
                                
                        return new DataGridViewTextBoxColumn ();
                }
                
                private void ClearBinding ()
                {
-                       columns.ClearAutoGeneratedColumns ();
-                       rows.Clear ();
-                       PrepareEditingRow (false, true);
+                       if (IsCurrentCellInEditMode && !EndEdit ())
+                               CancelEdit ();
+                       MoveCurrentCell (-1, -1, false, false, 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) {
+                               DataManager.ListChanged -= OnListChanged;
+                               DataManager.PositionChanged -= OnListPositionChanged;
+                               columns.ClearAutoGeneratedColumns ();
+                               rows.Clear ();
+                               RemoveEditingRow ();
+                       }
+               }
 
-                               if (dataSource is IBindingList)
-                                       (dataSource as IBindingList).ListChanged -= OnListChanged;
-                               if (dataSource is BindingSource)
-                                       (dataSource as BindingSource).DataSourceChanged -= OnBindingSourceDataSourceChanged;
+               private void ResetRows ()
+               {
+                       rows.Clear ();
+                       RemoveEditingRow ();
+                       if (DataManager != null) {
+                               foreach (object element in DataManager.List)
+                                       AddBoundRow (element);
                        }
+                       PrepareEditingRow (false, true);
+                       OnListPositionChanged (this, EventArgs.Empty);
                }
                
                private void DoBinding ()
@@ -5905,62 +6120,96 @@ 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 (!property.IsBrowsable)
+                                                       continue;
+
+                                               if (IsColumnAlreadyBound (property.Name))
+                                                       continue;
+
+                                               DataGridViewColumn col = CreateColumnByType (property.PropertyType);
+                                               col.Name = property.DisplayName;
+                                               col.DataPropertyName = property.Name;
+                                               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 (DataGridViewColumn column in columns) {
+                                       column.DataColumnIndex = FindDataColumnIndex (column);
+                                       if (column.DataColumnIndex != -1)
+                                               column.SetIsDataBound (true);
                                }
-                               
-                               if (value is BindingSource)
-                                       BindBindingSource (value as BindingSource);
-                               else if (value is IBindingListView)
-                                       BindIBindingListView (value as IBindingListView);
-                               else if (value is IBindingList)
-                                       BindIBindingList (value as IBindingList);
-                               else if (value is IList)
-                                       BindIList (value as IList);
-                               else if (value is IListSource)
-                                       BindIListSource (value as IListSource);
 
+                               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);
                        }
 
-                       if (Rows.Count > 0 && Columns.Count > 0)
-                               MoveCurrentCell (0, 0, true, false, false, false);
-                       PerformLayout();
-                       Invalidate ();
+                       PrepareEditingRow (false, true);
                }
                
-               private void BindBindingSource (BindingSource bindingSource)
+               private void MoveCurrentCell (int x, int y, bool select, bool isControl, bool isShift, bool scroll)
                {
-                       BindIList (bindingSource.List);
-                       bindingSource.ListChanged += OnBindingSourceDataSourceChanged;
-                       bindingSource.DataSourceChanged += OnBindingSourceDataSourceChanged;
-               }
-
-               private void BindIListSource (IListSource list) {
-                       BindIList (list.GetList());
-               }
+                       if (x == -1 || y == -1)
+                               x = y = -1;
+                       else {
+                               if (x < 0 || x > Columns.Count - 1)
+                                       throw new ArgumentOutOfRangeException ("x");
+                               if (y < 0 || y > Rows.Count - 1)
+                                       throw new ArgumentOutOfRangeException ("y");
+
+                               if (!Rows[y].Visible) {
+                                       for (int i = y; i < Rows.Count; i++) {
+                                               if (Rows[i].Visible) {
+                                                       y = i;
+                                                       break;
+                                               }
+                                       }
+                               }
 
-               private void BindIBindingList (IBindingList list) {
-                       BindIList (list);
-                       list.ListChanged += OnListChanged;
-               }
+                               if (!Columns[x].Visible) {
+                                       for (int i = x; i < Columns.Count; i++) {
+                                               if (Columns[i].Visible) {
+                                                       x = i;
+                                                       break;
+                                               }
+                                       }
+                               }
 
-               private void BindIBindingListView (IBindingListView list) {
-                       BindIList(list);
-               }
+                               // in case either no visible columns or rows
+                               if (!Rows[y].Visible || !Columns[x].Visible)
+                                       x = y = -1;
+                       }
 
-               private void MoveCurrentCell (int x, int y, bool select, bool isControl, bool isShift, bool scroll)
-               {
-                       SetCurrentCellAddressCore (x, y, true, false, false);
+                       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;
@@ -5983,18 +6232,40 @@ namespace System.Windows.Forms {
                        // If the current cell isn't visible, scroll to it
                        if (scroll) {
                                int disp_x = ColumnIndexToDisplayIndex (x);
+                               bool scrollbarsRefreshed = false;
+                               int displayedColumnsCount = DisplayedColumnCount (false);
+                               int delta_x = 0;
 
+                               // The trick here is that in order to avoid unnecessary calculations each time a row/column 
+                               // is added/removed we recalculate the whole grid size just before the scroll to selection.
                                if (disp_x < first_col_index) {
-                                       int delta_x = 0;
+                                       RefreshScrollBars ();
+                                       scrollbarsRefreshed = true;
 
                                        if (disp_x == 0)
                                                delta_x = horizontalScrollBar.Value;
-                                       else
+                                       else {
+                                               // in case the column got removed
+                                               if (first_col_index >= ColumnCount)
+                                                       first_col_index = ColumnCount - 1;
                                                for (int i = disp_x; i < first_col_index; i++)
                                                        delta_x += Columns[ColumnDisplayIndexToIndex (i)].Width;
+                                       }
                                
                                        horizontalScrollBar.SafeValueSet (horizontalScrollBar.Value - delta_x);
                                        OnHScrollBarScroll (this, new ScrollEventArgs (ScrollEventType.ThumbPosition, horizontalScrollBar.Value));
+                               } else if (disp_x > first_col_index + displayedColumnsCount - 1) {
+                                       RefreshScrollBars ();
+                                       scrollbarsRefreshed = true;
+                                       
+                                       if (disp_x == Columns.Count - 1)
+                                               delta_x = horizontalScrollBar.Maximum - horizontalScrollBar.Value;
+                                       else
+                                               for (int i = first_col_index + displayedColumnsCount - 1; i < disp_x; i++)
+                                                       delta_x += Columns[ColumnDisplayIndexToIndex (i)].Width;
+
+                                       horizontalScrollBar.SafeValueSet (horizontalScrollBar.Value + delta_x);
+                                       OnHScrollBarScroll (this, new ScrollEventArgs (ScrollEventType.ThumbPosition, horizontalScrollBar.Value));
                                }
 
                                int disp_y = y;
@@ -6002,15 +6273,25 @@ namespace System.Windows.Forms {
                                int delta_y = 0;
 
                                if (disp_y < first_row_index) {
+                                       if (!scrollbarsRefreshed)
+                                               RefreshScrollBars ();
+
                                        if (disp_y == 0)
                                                delta_y = verticalScrollBar.Value;
-                                       else
+                                       else {
+                                               // in case the row got removed
+                                               if (first_row_index >= RowCount)
+                                                       first_row_index = RowCount - 1;
                                                for (int i = disp_y; i < first_row_index; i++)
                                                        delta_y += GetRowInternal (i).Height;
+                                       }
 
                                        verticalScrollBar.SafeValueSet (verticalScrollBar.Value - delta_y);
                                        OnVScrollBarScroll (this, new ScrollEventArgs (ScrollEventType.ThumbPosition, verticalScrollBar.Value));
                                } else if (disp_y > first_row_index + displayedRowsCount - 1) {
+                                       if (!scrollbarsRefreshed)
+                                               RefreshScrollBars ();
+
                                        if (disp_y == Rows.Count - 1)
                                                delta_y = verticalScrollBar.Maximum - verticalScrollBar.Value;
                                        else
@@ -6046,6 +6327,8 @@ namespace System.Windows.Forms {
                
                private int ColumnIndexToDisplayIndex (int index)
                {
+                       if (index == -1)
+                               return index;
                        return Columns[index].DisplayIndex;
                }
                
@@ -6058,38 +6341,45 @@ namespace System.Windows.Forms {
                {
                        switch (args.ListChangedType) {
                                case ListChangedType.ItemAdded:
-                                       AddBoundRow ((sender as IBindingList)[args.NewIndex]);
+                                       AddBoundRow (DataManager[args.NewIndex]);
                                        break;
                                case ListChangedType.ItemDeleted:
-                                       Rows.RemoveAt (args.NewIndex);
+                                       Rows.RemoveAtInternal (args.NewIndex);
+                                       break;
+                               case ListChangedType.ItemChanged:
                                        break;
                                default:
-                                       ClearBinding ();
-                                       DoBinding ();
+                                       ResetRows ();
                                        break;
                        }
                        
                        Invalidate ();
                }
                
-               private void OnTableColumnChanged (object sender, DataColumnChangeEventArgs e)
+               private void OnListPositionChanged (object sender, EventArgs args)
                {
-                       ClearBinding ();
-                       DoBinding ();
+                       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 OnDataSetTableChanged (object sender, CollectionChangeEventArgs e)
+               private void ReBind ()
                {
-                       ClearBinding ();
-                       DoBinding ();
-               }
+                       if (!is_binding) {
+                               SuspendLayout ();
 
-               private void OnTableCleared (object sender, DataTableClearEventArgs e)
-               {
-                       ClearBinding ();
-                       DoBinding ();
-               }
+                               is_binding = true;
+                               ClearBinding ();
+                               DoBinding ();
+                               is_binding = false;
 
+                               ResumeLayout (true);
+                               Invalidate ();
+                       }
+               }
+               
                private bool MouseOverColumnResize (int col, int mousex)
                {
                        if (!allowUserToResizeColumns)
@@ -6197,16 +6487,18 @@ namespace System.Windows.Forms {
                                DataGridViewRow row2 = (DataGridViewRow)y;
 
                                if (row1.Cells[column].ValueType == typeof (DateTime) && row2.Cells[column].ValueType == typeof (DateTime))
-                                       return DateTime.Compare ((DateTime)row1.Cells[column].valuex, (DateTime)row2.Cells[column].valuex) * direction;
+                                       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)