2009-03-19 Ivan N. Zlatev <contact@i-nz.net>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / DataGridView.cs
index f7df270ee7d56bc6f396fcf997856693d2c0d005..ffc8bd7c59bb40ab80fcce63b852beef786d78b8 100644 (file)
@@ -135,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;
 
@@ -215,6 +212,7 @@ namespace System.Windows.Forms {
                        selectionMode = DataGridViewSelectionMode.RowHeaderSelect;
                        showCellErrors = true;
                        showEditingIcon = true;
+                       scrollBars = ScrollBars.Both;
                        userSetCursor = Cursor.Current;
                        virtualMode = false;
 
@@ -274,8 +272,14 @@ namespace System.Windows.Forms {
                        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 ();
                                }
                        }
@@ -578,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);
                                        }
@@ -680,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);
                        }
                }
 
@@ -711,7 +714,8 @@ namespace System.Windows.Forms {
                        set {
                                if (dataMember != value) {
                                        dataMember = value;
-                                       ReBind ();
+                                       if (BindingContext != null)
+                                               ReBind ();
                                        OnDataMemberChanged(EventArgs.Empty);
                                }
                        }
@@ -732,8 +736,10 @@ 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;
-                               ReBind ();
+                               if (BindingContext != null)
+                                       ReBind ();
                                OnDataSourceChanged (EventArgs.Empty);
                        }
                }
@@ -1004,12 +1010,19 @@ namespace System.Windows.Forms {
                                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)
@@ -1166,6 +1179,8 @@ namespace System.Windows.Forms {
                                /// or canceled.
                                ///////////////////////////////////////////////////////////
                                scrollBars = value;
+                               PerformLayout ();
+                               Invalidate ();
                        }
                }
 
@@ -1290,8 +1305,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);
                        }
                }
 
@@ -2389,9 +2412,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 {
@@ -2489,7 +2518,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;
                                }
@@ -2749,13 +2781,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);
@@ -2791,6 +2827,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;
@@ -3144,6 +3182,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);
 
@@ -3451,6 +3491,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);
@@ -3484,6 +3527,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);
@@ -3666,7 +3712,6 @@ namespace System.Windows.Forms {
                                //
                                if (!is_autogenerating_columns && columns.Count == 1)
                                        ReBind ();
-
                                foreach (DataGridViewRow row in Rows)
                                        row.Cells.Add ((DataGridViewCell)e.Column.CellTemplate.Clone ());
                        }
@@ -3803,7 +3848,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;
@@ -3813,8 +3873,9 @@ namespace System.Windows.Forms {
                        }
 
                        AutoResizeColumnsInternal ();
-                       OnColumnRemoved (e);
                        PrepareEditingRow (false, true);
+
+                       OnColumnRemoved (e);
                }
 
                protected virtual void OnColumnRemoved (DataGridViewColumnEventArgs e)
@@ -3967,6 +4028,7 @@ namespace System.Windows.Forms {
                protected override void OnHandleCreated (EventArgs e)
                {
                        base.OnHandleCreated(e);
+                       ReBind ();
                        
                        if (CurrentCell == null && Rows.Count > 0 && Columns.Count > 0)
                                MoveCurrentCell (ColumnDisplayIndexToIndex (0), 0, true, false, false, false);
@@ -4062,6 +4124,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)
@@ -4478,6 +4545,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)
@@ -4544,16 +4619,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];
@@ -4563,18 +4634,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;
@@ -4588,62 +4660,84 @@ 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;
+                       }
+               }
+
+               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;
+
                                if (horizontalVisible) {
                                        horizontalScrollBar.Minimum = 0;
                                        horizontalScrollBar.Maximum = gridWidth;
                                        horizontalScrollBar.SmallChange = Columns[first_col_index].Width;
-                                       int 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;
-                                       int largeChange = ClientSize.Height - columnHeadersHeight;
+                                       int largeChange = ClientSize.Height - columnHeadersHeight - verticalScrollBar.Width;
                                        if (largeChange <= 0)
                                                largeChange = ClientSize.Height;
                                        verticalScrollBar.LargeChange = largeChange;
@@ -4652,22 +4746,6 @@ namespace System.Windows.Forms {
 
                        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) {
@@ -4829,15 +4907,15 @@ namespace System.Windows.Forms {
 
                internal void OnRowsAddedInternal (DataGridViewRowsAddedEventArgs e)
                {
-                       // if the very first row has just been added
-                       if (Rows.Count == 1 && Columns.Count > 0)
-                               MoveCurrentCell (0, 0, true, false, false, true);
+                       if (hover_cell != null && hover_cell.RowIndex >= e.RowIndex)
+                               hover_cell = null;
+
                        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);
@@ -4849,25 +4927,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) {
+                       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);
-                       } else {
+                               hover_cell = null;
+                       } else if (currentCell != null && currentCell.RowIndex == e.RowIndex) {
                                int nextRowIndex = e.RowIndex;
-                               if (nextRowIndex >= Rows.Count)
-                                       nextRowIndex = Rows.Count - 1;
+                               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);
                }
@@ -5027,7 +5112,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);
@@ -5041,8 +5126,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);
                        }
@@ -5578,10 +5663,16 @@ 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;
+                               } else if (e.NewValue < top + row.Height) {
                                        if (first_row_index != index) {
                                                first_row_index = index;
                                                Invalidate ();
@@ -5594,7 +5685,7 @@ namespace System.Windows.Forms {
                                top += row.Height;
                        }
                        
-                       first_row_index = Rows.Count - DisplayedRowCount (false);
+                       first_row_index = lastTopVisibleRowIndex;
                        Invalidate ();
                        OnScroll (e);
                }
@@ -5609,7 +5700,7 @@ 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:
                                        break;
@@ -5745,6 +5836,8 @@ namespace System.Windows.Forms {
                        only_visible = (mode == DataGridViewAutoSizeColumnMode.DisplayedCells || mode == DataGridViewAutoSizeColumnMode.DisplayedCellsExceptHeader);
                        
                        for (int i = first_row; i < Rows.Count; i++) {
+                               if (!Rows[i].Visible)
+                                       continue;
                                if (only_visible) {
                                        Rectangle row_rect = this.GetRowDisplayRectangle (i, false);
                                        if (!ClientRectangle.IntersectsWith (row_rect))
@@ -5785,7 +5878,7 @@ 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;
@@ -5794,16 +5887,14 @@ namespace System.Windows.Forms {
                        
                        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 && (cell_changed || column_changed)) {
                                        // The row changed, it's no longer an editing row.
                                        //    or
                                        // The number of columns has changed, we need a new editing row.
-                                       Rows.RemoveInternal (editing_row);
-                                       editing_row = null;
+                                       RemoveEditingRow ();
                                }
                                if (editing_row == null) {
                                        editing_row = RowTemplateFull;
@@ -5812,6 +5903,15 @@ namespace System.Windows.Forms {
                        }
                }
                
+               internal void RemoveEditingRow ()
+               {
+                       if (editing_row != null) {
+                               if (Rows.Contains (editing_row))
+                                   Rows.RemoveInternal (editing_row);
+                               editing_row = null;
+                       }
+               }
+
                internal DataGridViewRow EditingRow {
                        get { return editing_row; }
                }
@@ -5856,20 +5956,38 @@ namespace System.Windows.Forms {
                {
                        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 (DataManager != null) {
                                DataManager.ListChanged -= OnListChanged;
                                DataManager.PositionChanged -= OnListPositionChanged;
+                               columns.ClearAutoGeneratedColumns ();
+                               rows.Clear ();
+                               RemoveEditingRow ();
                        }
                }
+
+               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 ()
                {
@@ -5888,6 +6006,8 @@ namespace System.Windows.Forms {
                                                // This keeps out things like arrays
                                                if ((typeof(ICollection).IsAssignableFrom (property.PropertyType)))
                                                        continue;
+                                               if (!property.IsBrowsable)
+                                                       continue;
 
                                                if (IsColumnAlreadyBound (property.DisplayName))
                                                        continue;
@@ -5925,6 +6045,7 @@ namespace System.Windows.Forms {
                                        MoveCurrentCell (0, 0, true, false, false, false);
                        }
 
+                       PrepareEditingRow (false, true);
                        PerformLayout();
                        Invalidate ();
                }
@@ -5933,6 +6054,34 @@ namespace System.Windows.Forms {
                {
                        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;
+                                               }
+                                       }
+                               }
+
+                               if (!Columns[x].Visible) {
+                                       for (int i = x; i < Columns.Count; i++) {
+                                               if (Columns[i].Visible) {
+                                                       x = i;
+                                                       break;
+                                               }
+                                       }
+                               }
+
+                               // in case either no visible columns or rows
+                               if (!Rows[y].Visible || !Columns[x].Visible)
+                                       x = y = -1;
+                       }
 
                        if (!SetCurrentCellAddressCore (x, y, true, false, false)) {
                                ClearSelection ();
@@ -5964,15 +6113,25 @@ namespace System.Windows.Forms {
                        // If the current cell isn't visible, scroll to it
                        if (scroll) {
                                int disp_x = ColumnIndexToDisplayIndex (x);
+                               bool scrollbarsRefreshed = false;
 
                                if (disp_x < first_col_index) {
+                                       // 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 just before the scroll 
+                                       // to selection.
+                                       RefreshScrollBars ();
+                                       scrollbarsRefreshed = true;
                                        int delta_x = 0;
 
                                        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));
@@ -5983,15 +6142,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
@@ -6049,7 +6218,7 @@ namespace System.Windows.Forms {
                                case ListChangedType.ItemChanged:
                                        break;
                                default:
-                                       ReBind ();
+                                       ResetRows ();
                                        break;
                        }