Warnings cleanup
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / DataGridView.cs
index e8573d58b8bb855532bbecfc2b4a383058c638c5..675575fb677f9663a756af1aabf345e330242c3e 100644 (file)
@@ -23,7 +23,6 @@
 //     Pedro Martínez Juliá <pedromj@gmail.com>
 //
 
-
 #if NET_2_0
 
 using System;
@@ -57,6 +56,7 @@ namespace System.Windows.Forms {
                private bool allowUserToResizeColumns;
                private bool allowUserToResizeRows;
                private DataGridViewCellStyle alternatingRowsDefaultCellStyle;
+               private Point anchor_cell;
                private bool autoGenerateColumns;
                private bool autoSize;
                private DataGridViewAutoSizeColumnsMode autoSizeColumnsMode;
@@ -81,13 +81,14 @@ namespace System.Windows.Forms {
                private DataGridViewCellStyle defaultCellStyle;
                //private Control editingControl;
                private DataGridViewEditMode editMode;
-               private bool enableHeadersVisualStyles;
+               private bool enableHeadersVisualStyles = true;
                private DataGridViewCell firstDisplayedCell;
                private int firstDisplayedScrollingColumnHiddenWidth;
                private int firstDisplayedScrollingColumnIndex;
                private int firstDisplayedScrollingRowIndex;
                private Color gridColor = Color.FromKnownColor(KnownColor.ControlDark);
                private int horizontalScrollingOffset;
+               private DataGridViewCell hover_cell = null;
                private bool isCurrentCellDirty;
                //private bool isCurrentRowDirty;
                private bool multiSelect;
@@ -121,17 +122,26 @@ namespace System.Windows.Forms {
                private int selected_row = -1;
                private int selected_column = -1;
                
+               // Stuff for error Tooltips
+               private Timer tooltip_timer;
+               private ToolTip tooltip_window;
+               private DataGridViewCell tooltip_currently_showing;
+
                private DataGridViewSelectedRowCollection selected_rows;
                private DataGridViewSelectedColumnCollection selected_columns;
                private DataGridViewRow editing_row;
                
-               internal int gridWidth;
-               internal int gridHeight;
+               private int gridWidth;
+               private int gridHeight;
+
+               DataGridViewHeaderCell pressed_header_cell;
+               DataGridViewHeaderCell entered_header_cell;
 
                public DataGridView ()
                {
                        SetStyle (ControlStyles.Opaque, true);
-                       SetStyle (ControlStyles.UserMouse, true);
+                       //SetStyle (ControlStyles.UserMouse, true);
+                       SetStyle (ControlStyles.OptimizedDoubleBuffer, true);
                        
                        adjustedTopLeftHeaderBorderStyle = new DataGridViewAdvancedBorderStyle();
                        adjustedTopLeftHeaderBorderStyle.All = DataGridViewAdvancedCellBorderStyle.Single;
@@ -247,6 +257,8 @@ namespace System.Windows.Forms {
                                if (allowUserToAddRows != value) {
                                        allowUserToAddRows = value;
                                        OnAllowUserToAddRowsChanged(EventArgs.Empty);
+                                       PrepareEditingRow (false, false);
+                                       Invalidate ();
                                }
                        }
                }
@@ -352,7 +364,10 @@ namespace System.Windows.Forms {
                                                }
                                        }
                                }
+                               
                                autoSizeColumnsMode = value;
+                               AutoResizeColumns (value);
+                               Invalidate ();
                        }
                }
 
@@ -368,7 +383,9 @@ namespace System.Windows.Forms {
                                                throw new InvalidOperationException("Cant set this property to AllHeaders or DisplayedHeaders in this DataGridView.");
                                        }
                                        autoSizeRowsMode = value;
+                                       AutoResizeRows (value);
                                        OnAutoSizeRowsModeChanged(new DataGridViewAutoSizeModeEventArgs(false));
+                                       Invalidate ();
                                        ////////////////////////////////////////////////////////////////
                                }
                        }
@@ -487,7 +504,7 @@ namespace System.Windows.Forms {
                                }
                                else if (value > columns.Count) {
                                        for (int i = 0; i < value; i++) {
-                                               DataGridViewColumn col = new DataGridViewColumn();
+                                               DataGridViewTextBoxColumn col = new DataGridViewTextBoxColumn ();
                                                columns.Add(col);
                                        }
                                }
@@ -607,8 +624,12 @@ namespace System.Windows.Forms {
                        get { return dataMember; }
                        set {
                                if (dataMember != value) {
+                                       ClearBinding ();
+                                       
                                        dataMember = value;
                                        OnDataMemberChanged(EventArgs.Empty);
+                                       
+                                       DoBinding ();
                                }
                        }
                }
@@ -616,7 +637,6 @@ namespace System.Windows.Forms {
                [RefreshProperties (RefreshProperties.Repaint)]
                [DefaultValue (null)]
                [AttributeProvider (typeof (IListSource))]
-               // XXX AttributeProviderAtribute
                public object DataSource {
                        get { return dataSource; }
                        set {
@@ -630,36 +650,13 @@ namespace System.Windows.Forms {
                                        if (!(value == null || value is IList || value is IListSource || value is IBindingList || value is IBindingListView)) {
                                                throw new NotSupportedException("Type cant be binded.");
                                        }
-                                       if (dataSource != null) {
-                                               columns.Clear();
-                                               rows.Clear();
-                                               if (dataSource is DataView) {
-                                                       (dataSource as DataView).ListChanged -= OnListChanged;
-                                               }
-                                               if (dataSource is DataTable) {
-                                                       ((dataSource as IListSource).GetList() as DataView).ListChanged -= OnListChanged;
-                                               }
-                                       }
+                                               
+                                       ClearBinding ();
+                                       
                                        dataSource = value;
-                                       OnDataSourceChanged(EventArgs.Empty);
-                                       if (dataSource != null) {
-                                               // DataBinding
-                                               if (value is IList) {
-                                                       BindIList(value as IList);
-                                               }
-                                               else if (value is IListSource) {
-                                                       BindIListSource(value as IListSource);
-                                               }
-                                               else if (value is IBindingList) {
-                                                       BindIBindingList(value as IBindingList);
-                                               }
-                                               else if (value is IBindingListView) {
-                                                       BindIBindingListView(value as IBindingListView);
-                                                       //bool cosa = ((value as IBindingListView).SortDescriptions as IList).IsFixedSize;
-                                               }
-                                               OnDataBindingComplete(new DataGridViewBindingCompleteEventArgs(ListChangedType.Reset));
-                                       }
-                                       Invalidate();
+                                       OnDataSourceChanged (EventArgs.Empty);
+                                       
+                                       DoBinding ();
                                }
                        }
                }
@@ -710,6 +707,26 @@ namespace System.Windows.Forms {
                        set { enableHeadersVisualStyles = value; }
                }
 
+               internal DataGridViewHeaderCell EnteredHeaderCell {
+                       get { return entered_header_cell; }
+                       set {
+                               if (entered_header_cell == value)
+                                       return;
+                               if (ThemeEngine.Current.DataGridViewHeaderCellHasHotStyle (this)) {
+                                       Region area_to_invalidate = new Region ();
+                                       area_to_invalidate.MakeEmpty ();
+                                       if (entered_header_cell != null)
+                                               area_to_invalidate.Union (GetHeaderCellBounds (entered_header_cell));
+                                       entered_header_cell = value;
+                                       if (entered_header_cell != null)
+                                               area_to_invalidate.Union (GetHeaderCellBounds (entered_header_cell));
+                                       Invalidate (area_to_invalidate);
+                                       area_to_invalidate.Dispose ();
+                               } else
+                                       entered_header_cell = value;
+                       }
+               }
+
                [Browsable (false)]
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                public DataGridViewCell FirstDisplayedCell {
@@ -866,6 +883,10 @@ namespace System.Windows.Forms {
                        set { }
                }
 
+               internal DataGridViewHeaderCell PressedHeaderCell {
+                       get { return pressed_header_cell; }
+               }
+
                [Browsable (true)]
                [DefaultValue (false)]
                public bool ReadOnly {
@@ -900,20 +921,19 @@ namespace System.Windows.Forms {
                                        }
                                }
                                else if (value > rows.Count) {
-                                       for (int i = 0; i < value; i++) {
-                                               // DataGridViewRow row = new DataGridViewRow(); //(DataGridViewRow) rowTemplate.Clone();
-                                               DataGridViewRow row = (DataGridViewRow) rowTemplate.Clone();
-                                               rows.Add(row);
-                                               foreach (DataGridViewColumn col in columns) {
-                                                       row.Cells.Add(col.CellTemplate.Clone() as DataGridViewCell);
-                                               }
+                                       // 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) RowTemplate.Clone ();
+                                               rows.AddInternal (row, false);
+                                               
+                                               foreach (DataGridViewColumn col in columns)
+                                                       row.Cells.Add (col.CellTemplate.Clone () as DataGridViewCell);
                                        }
                                }
-                               if (ColumnCount == 0) {
-                                       ///////////////////////////////////////////////////////////////
-                                       //columns.Add(new DataGridViewTextBoxColumn());
-                                       throw new NotImplementedException();
-                               }
                        }
                }
 
@@ -1007,9 +1027,9 @@ namespace System.Windows.Forms {
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
                public DataGridViewRow RowTemplate {
                        get {
-                               if (rowTemplate == null) {
-                                       return new DataGridViewRow();
-                               }
+                               if (rowTemplate == null)
+                                       rowTemplate = new DataGridViewRow ();
+
                                return rowTemplate;
                        }
                        set {
@@ -1106,9 +1126,14 @@ namespace System.Windows.Forms {
                public DataGridViewSelectionMode SelectionMode {
                        get { return selectionMode; }
                        set {
-                               if (!Enum.IsDefined(typeof(DataGridViewSelectionMode), value)) {
-                                       throw new InvalidEnumArgumentException("Value is not valid DataGridViewSelectionMode.");
-                               }
+                               if (!Enum.IsDefined (typeof(DataGridViewSelectionMode), value))
+                                       throw new InvalidEnumArgumentException ("Value is not valid DataGridViewSelectionMode.");
+
+                               if (value == DataGridViewSelectionMode.ColumnHeaderSelect || value == DataGridViewSelectionMode.FullColumnSelect)
+                                       foreach (DataGridViewColumn col in Columns)
+                                               if (col.SortMode == DataGridViewColumnSortMode.Automatic)
+                                                       throw new InvalidOperationException (string.Format ("Cannot set SelectionMode to {0} because there are Automatic sort columns.", value));
+                               
                                selectionMode = value;
                        }
                }
@@ -1190,6 +1215,7 @@ namespace System.Windows.Forms {
                        get { return verticalScrollingOffset; }
                }
 
+               [MonoTODO ("VirtualMode is not supported.")]
                [EditorBrowsable (EditorBrowsableState.Advanced)]
                [DefaultValue (false)]
                public bool VirtualMode {
@@ -1216,8 +1242,11 @@ namespace System.Windows.Forms {
                                        }
                                }
                                
-                               if (value != null)
+                               
+                               if (value != null) {
+                                       value.Visible = false;
                                        Controls.Add (value);
+                               }
 
                                editingControl = value;
                        }
@@ -2032,16 +2061,26 @@ namespace System.Windows.Forms {
                        AutoResizeColumn (columnIndex, DataGridViewAutoSizeColumnMode.AllCells);
                }
 
-               public void AutoResizeColumn (int columnIndex, DataGridViewAutoSizeColumnMode autoSizeColumnMode) {
-                       AutoResizeColumn (columnIndex, autoSizeColumnMode, true);
+               public void AutoResizeColumn (int columnIndex, DataGridViewAutoSizeColumnMode autoSizeColumnMode)
+               {
+                       AutoResizeColumnInternal (columnIndex, autoSizeColumnMode);
                }
 
-               public void AutoResizeColumnHeadersHeight () {
-                       throw new NotImplementedException();
+               public void AutoResizeColumnHeadersHeight ()
+               {
+                       int new_height = 0;
+                       
+                       foreach (DataGridViewColumn col in Columns)
+                               new_height = Math.Max (new_height, col.HeaderCell.PreferredSize.Height);
+                       
+                       if (ColumnHeadersHeight != new_height)
+                               ColumnHeadersHeight = new_height;
                }
 
-               public void AutoResizeColumnHeadersHeight (int columnIndex) {
-                       throw new NotImplementedException();
+               [MonoTODO ("columnIndex parameter is not used")]
+               public void AutoResizeColumnHeadersHeight (int columnIndex)
+               {
+                       AutoResizeColumnHeadersHeight ();
                }
 
                public void AutoResizeColumns () {
@@ -2052,36 +2091,88 @@ namespace System.Windows.Forms {
                        AutoResizeColumns (autoSizeColumnsMode, true);
                }
 
-               public void AutoResizeRow (int rowIndex) {
-                       throw new NotImplementedException();
+               public void AutoResizeRow (int rowIndex)
+               {
+                       AutoResizeRow (rowIndex, DataGridViewAutoSizeRowMode.AllCells);
                }
 
-               public void AutoResizeRow (int rowIndex, DataGridViewAutoSizeRowMode autoSizeRowMode) {
-                       throw new NotImplementedException();
+               public void AutoResizeRow (int rowIndex, DataGridViewAutoSizeRowMode autoSizeRowMode)
+               {
+                       if (autoSizeRowMode == DataGridViewAutoSizeRowMode.RowHeader && !rowHeadersVisible)
+                               throw new InvalidOperationException ("row headers are not visible");
+                       if (rowIndex < 0 || rowIndex > Rows.Count - 1)
+                               throw new ArgumentOutOfRangeException ("rowIndex");
+                       
+                       DataGridViewRow row = GetRowInternal (rowIndex);
+                       
+                       if (autoSizeRowMode == DataGridViewAutoSizeRowMode.RowHeader) {
+                               row.Height = row.HeaderCell.PreferredSize.Height;
+                               return;
+                       }
+                       
+                       int row_height = 0;
+                       
+                       foreach (DataGridViewCell cell in row.Cells)
+                               row_height = Math.Max (row_height, cell.PreferredSize.Height);
+                               
+                       if (autoSizeRowMode == DataGridViewAutoSizeRowMode.AllCellsExceptHeader)
+                               row.Height = row_height;
+                       else
+                               row.Height = Math.Max (row_height, row.HeaderCell.PreferredSize.Height);
                }
 
-               public void AutoResizeRowHeadersWidth (DataGridViewRowHeadersWidthSizeMode rowHeadersWidthSizeMode) {
-                       throw new NotImplementedException();
+               public void AutoResizeRowHeadersWidth (DataGridViewRowHeadersWidthSizeMode rowHeadersWidthSizeMode)
+               {
+                       if (rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.AutoSizeToFirstHeader) {
+                               RowHeadersWidth = GetRowInternal (0).HeaderCell.PreferredSize.Width;
+                               return;
+                       }
+                       
+                       int new_width = 0;
+                       
+                       if (rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders) {
+                               foreach (DataGridViewRow row in Rows)
+                                       if (row.Displayed)
+                                               new_width = Math.Max (new_width, row.HeaderCell.PreferredSize.Width);
+                                               
+                               if (RowHeadersWidth != new_width)
+                                       RowHeadersWidth = new_width;
+                                       
+                               return;
+                       }
+
+                       if (rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders) {
+                               foreach (DataGridViewRow row in Rows)
+                                       new_width = Math.Max (new_width, row.HeaderCell.PreferredSize.Width);
+
+                               if (RowHeadersWidth != new_width)
+                                       RowHeadersWidth = new_width;
+
+                               return;
+                       }
                }
 
-               public void AutoResizeRowHeadersWidth (int rowIndex, DataGridViewRowHeadersWidthSizeMode rowHeadersWidthSizeMode) {
-                       throw new NotImplementedException();
+               [MonoTODO ("Does not use rowIndex parameter.")]
+               public void AutoResizeRowHeadersWidth (int rowIndex, DataGridViewRowHeadersWidthSizeMode rowHeadersWidthSizeMode)
+               {
+                       AutoResizeRowHeadersWidth (rowHeadersWidthSizeMode);
                }
 
-               public void AutoResizeRows () {
-                       throw new NotImplementedException();
+               public void AutoResizeRows ()
+               {
+                       AutoResizeRows (0, Rows.Count, DataGridViewAutoSizeRowMode.AllCells, false);
                }
 
-               public void AutoResizeRows (DataGridViewAutoSizeRowsMode autoSizeRowsMode) {
-                       if (!Enum.IsDefined(typeof(DataGridViewAutoSizeRowsMode), autoSizeRowsMode)) {
-                               throw new InvalidEnumArgumentException("Parameter AutoSizeRowsMode is not valid DataGridViewRowsMode.");
-                       }
-                       if ((autoSizeRowsMode == DataGridViewAutoSizeRowsMode.AllHeaders || autoSizeRowsMode == DataGridViewAutoSizeRowsMode.DisplayedHeaders) && rowHeadersVisible == false) {
-                               throw new InvalidOperationException("Parameter AutoSizeRowsMode cant be AllHeaders or DisplayedHeaders in this DataGridView.");
-                       }
-                       if (autoSizeRowsMode == DataGridViewAutoSizeRowsMode.None) {
-                               throw new ArgumentException("Parameter AutoSieRowsMode cant be None.");
-                       }
+               public void AutoResizeRows (DataGridViewAutoSizeRowsMode autoSizeRowsMode)
+               {
+                       if (!Enum.IsDefined(typeof(DataGridViewAutoSizeRowsMode), autoSizeRowsMode))
+                               throw new InvalidEnumArgumentException ("Parameter AutoSizeRowsMode is not valid DataGridViewRowsMode.");
+                       if ((autoSizeRowsMode == DataGridViewAutoSizeRowsMode.AllHeaders || autoSizeRowsMode == DataGridViewAutoSizeRowsMode.DisplayedHeaders) && rowHeadersVisible == false)
+                               throw new InvalidOperationException ("Parameter AutoSizeRowsMode cant be AllHeaders or DisplayedHeaders in this DataGridView.");
+                       if (autoSizeRowsMode == DataGridViewAutoSizeRowsMode.None)
+                               throw new ArgumentException ("Parameter AutoSieRowsMode cant be None.");
+                       
+                       AutoResizeRows (autoSizeRowsMode, false);
                }
 
                public virtual bool BeginEdit (bool selectAll) {
@@ -2098,7 +2189,14 @@ namespace System.Windows.Forms {
                        Type editType = cell.EditType;
                        if (editType == null)
                                return false;
+                               
+                       // Give user a chance to cancel the edit
+                       DataGridViewCellCancelEventArgs e = new DataGridViewCellCancelEventArgs (cell.ColumnIndex, cell.RowIndex);
+                       OnCellBeginEdit (e);
 
+                       if (e.Cancel)
+                               return false;
+                               
                        cell.SetIsInEditMode (true);
                        Control ctrl = EditingControlInternal;
                        bool isCorrectType = ctrl != null && ctrl.GetType () == editType;
@@ -2113,62 +2211,96 @@ namespace System.Windows.Forms {
                        IDataGridViewEditingControl edControl = ctrl as IDataGridViewEditingControl;
                        DataGridViewCellStyle style = cell.RowIndex == -1 ? DefaultCellStyle : cell.InheritedStyle;
                        cell.InitializeEditingControl (cell.RowIndex, cell.FormattedValue, style);
+                       
                        cell.PositionEditingControl (true, true, this.GetCellDisplayRectangle (cell.ColumnIndex, cell.RowIndex, false), bounds, style, false, false, (columns [cell.ColumnIndex].DisplayIndex == 0), (cell.RowIndex == 0));
+                       EditingControlInternal.Visible = true;
+                       
                        if (edControl != null)
-                               edControl.PrepareEditingControlForEdit (selectAll);
-                       ctrl.Visible = true;
+                               (EditingControlInternal as IDataGridViewEditingControl).PrepareEditingControlForEdit (selectAll);
 
-                       OnCellBeginEdit (new DataGridViewCellCancelEventArgs (cell.ColumnIndex, cell.RowIndex));
                        return true;
                }
 
-               public bool CancelEdit () {
-                       throw new NotImplementedException();
+               public bool CancelEdit ()
+               {
+                       if (currentCell != null && currentCell.IsInEditMode) {
+                               currentCell.SetIsInEditMode (false);
+                               currentCell.DetachEditingControl ();
+                               OnCellEndEdit (new DataGridViewCellEventArgs (currentCell.ColumnIndex, currentCell.RowIndex));
+                       }
+
+                       return true;
                }
 
-               public void ClearSelection () {
-                       foreach (DataGridViewCell cell in SelectedCells) {
+               public void ClearSelection ()
+               {
+                       foreach (DataGridViewColumn col in SelectedColumns)
+                               col.Selected = false;
+                       foreach (DataGridViewRow row in SelectedRows)
+                               row.Selected = false;
+                       foreach (DataGridViewCell cell in SelectedCells)
                                cell.Selected = false;
-                       }
                }
 
-               public bool CommitEdit (DataGridViewDataErrorContexts context) {
-                       throw new NotImplementedException();
+               public bool CommitEdit (DataGridViewDataErrorContexts context)
+               {
+                       if (currentCell != null && currentCell.IsInEditMode) {
+                               IDataGridViewEditingControl ctrl = EditingControl as IDataGridViewEditingControl;
+                               ctrl.GetEditingControlFormattedValue (DataGridViewDataErrorContexts.Commit);
+                               currentCell.Value = ctrl.GetEditingControlFormattedValue (DataGridViewDataErrorContexts.Commit);
+                               return true;
+                       }
+                       
+                       return false;
                }
 
-               public int DisplayedColumnCount (bool includePartialColumns) {
-                       /////////////////////// PartialColumns?
+               [MonoTODO ("Always includes partial columns")]
+               public int DisplayedColumnCount (bool includePartialColumns)
+               {
                        int result = 0;
-                       foreach (DataGridViewColumn col in columns) {
-                               if (col.Visible) {
+                       
+                       for (int i = first_col_index; i < Columns.Count; i++)
+                               if (Columns.ColumnDisplayIndexSortedArrayList[i].Displayed)
                                        result++;
-                               }
-                       }
+                               else
+                                       break;
+
                        return result;
                }
 
-               public int DisplayedRowCount (bool includePartialRow) {
-                       /////////////////////// PartialRows?
+               [MonoTODO ("Always includes partial rows")]
+               public int DisplayedRowCount (bool includePartialRow)
+               {
                        int result = 0;
-                       foreach (DataGridViewRow row in rows) {
-                               if (row.Visible) {
+                       
+                       for (int i = first_row_index; i < Rows.Count; i++)
+                               if (Rows[i].Displayed)
                                        result++;
-                               }
-                       }
+                               else
+                                       break;
+                                       
                        return result;
                }
 
-               public bool EndEdit () {
+               public bool EndEdit ()
+               {
                        if (currentCell != null && currentCell.IsInEditMode) {
+                               IDataGridViewEditingControl ctrl = EditingControl as IDataGridViewEditingControl;
+                               ctrl.GetEditingControlFormattedValue (DataGridViewDataErrorContexts.Commit);
+                               currentCell.Value = ctrl.GetEditingControlFormattedValue (DataGridViewDataErrorContexts.Commit);
+                               
                                currentCell.SetIsInEditMode (false);
                                currentCell.DetachEditingControl ();
                                OnCellEndEdit (new DataGridViewCellEventArgs (currentCell.ColumnIndex, currentCell.RowIndex));
                        }
+                       
                        return true;
                }
 
-               public bool EndEdit (DataGridViewDataErrorContexts context) {
-                       throw new NotImplementedException();
+               [MonoTODO ("Does not use context parameter")]
+               public bool EndEdit (DataGridViewDataErrorContexts context)
+               {
+                       return EndEdit ();
                }
 
                public int GetCellCount (DataGridViewElementStates includeFilter) {
@@ -2200,22 +2332,30 @@ namespace System.Windows.Forms {
                        
                        int x = 0, y = 0, w = 0, h = 0;
                        
+                       x = BorderWidth;
+                       y = BorderWidth;
+                       
                        if (ColumnHeadersVisible)
-                               y = ColumnHeadersHeight;
+                               y += ColumnHeadersHeight;
                        
                        if (RowHeadersVisible)
-                               x = RowHeadersWidth;
-                               
-                       for (int i = 0; i < Columns.Count; i++) {
-                               if (i == columnIndex) {
-                                       w = columns [i].Width;
+                               x += RowHeadersWidth;
+
+                       List<DataGridViewColumn> cols = columns.ColumnDisplayIndexSortedArrayList;
+
+                       for (int i = first_col_index; i < cols.Count; i++) {
+                               if (!cols[i].Visible)
+                                       continue;
+                                       
+                               if (cols[i].Index == columnIndex) {
+                                       w = cols[i].Width;
                                        break;
                                }
-                                       
-                               x += columns [i].Width;
+
+                               x += cols[i].Width;
                        }
                        
-                       for (int i = 0; i < Rows.Count; i++) {
+                       for (int i = first_row_index; i < Rows.Count; i++) {
                                if (i == rowIndex) {
                                        h = rows [i].Height;
                                        break;
@@ -2431,12 +2571,61 @@ namespace System.Windows.Forms {
                        return result;
                }
 
-               public Rectangle GetColumnDisplayRectangle (int columnIndex, bool cutOverflow) {
-                       throw new NotImplementedException();
+               [MonoTODO ("Does not use cutOverflow parameter")]
+               public Rectangle GetColumnDisplayRectangle (int columnIndex, bool cutOverflow)
+               {
+                       if (columnIndex < 0 || columnIndex > Columns.Count - 1)
+                               throw new ArgumentOutOfRangeException ("columnIndex");
+                               
+                       int x = 0;
+                       int w = 0;
+
+                       x = BorderWidth;
+
+                       if (RowHeadersVisible)
+                               x += RowHeadersWidth;
+
+                       List<DataGridViewColumn> cols = columns.ColumnDisplayIndexSortedArrayList;
+
+                       for (int i = first_col_index; i < cols.Count; i++) {
+                               if (!cols[i].Visible)
+                                       continue;
+                                       
+                               if (cols[i].Index == columnIndex) {
+                                       w = cols[i].Width;
+                                       break;
+                               }
+
+                               x += cols[i].Width;
+                       }
+
+                       return new Rectangle (x, 0, w, Height);
                }
 
-               public Rectangle GetRowDisplayRectangle (int rowIndex, bool cutOverflow) {
-                       throw new NotImplementedException();
+               [MonoTODO ("Does not use cutOverflow parameter")]
+               public Rectangle GetRowDisplayRectangle (int rowIndex, bool cutOverflow)
+               {
+                       if (rowIndex < 0 || rowIndex > Rows.Count - 1)
+                               throw new ArgumentOutOfRangeException ("rowIndex");
+
+                       int y = 0;
+                       int h = 0;
+
+                       y = BorderWidth;
+
+                       if (ColumnHeadersVisible)
+                               y += ColumnHeadersHeight;
+
+                       for (int i = first_row_index; i < Rows.Count; i++) {
+                               if (i == rowIndex) {
+                                       h = rows[i].Height;
+                                       break;
+                               }
+
+                               y += rows[i].Height;
+                       }
+
+                       return new Rectangle (0, y, Width, h);
                }
 
                public HitTestInfo HitTest (int x, int y) {
@@ -2445,56 +2634,65 @@ namespace System.Windows.Forms {
                        bool isInColHeader = columnHeadersVisible && y >= 0 && y <= ColumnHeadersHeight;
                        bool isInRowHeader = rowHeadersVisible && x >= 0 && x <= RowHeadersWidth;
                        
-                       x += horizontalScrollingOffset;
-                       y += verticalScrollingOffset;
-                       int rowIndex = -1;
-                       int totalHeight = (columnHeadersVisible)? 1 + columnHeadersHeight : 1;
-                       if (columnHeadersVisible && y <= totalHeight) {
-                               rowIndex = -1;
-                       }
-                       else {
-                               foreach (DataGridViewRow row in rows.RowIndexSortedArrayList) {
-                                       totalHeight += row.Height;
-                                       if (y <= totalHeight) {
-                                               rowIndex = row.Index;
-                                               if (rowIndex == -1) {
-                                                       rowIndex = rows.SharedRowIndexOf (row);
-                                               }
-                                               break;
-                                       }
-                                       totalHeight++; // sumar el ancho de las lineas...
-                               }
-                       }
-                       int colIndex = -1;
-                       int totalWidth = (rowHeadersVisible)? 1 + rowHeadersWidth : 1;
-                       if (rowHeadersVisible && x <= totalWidth) {
-                               colIndex = -1;
-                       }
-                       else {
-                               foreach (DataGridViewColumn col in columns.ColumnDisplayIndexSortedArrayList) {
-                                       totalWidth += col.Width;
-                                       if (x <= totalWidth) {
-                                               colIndex = col.Index;
-                                               break;
-                                       }
-                                       totalWidth++;
+                       // TopLeftHeader
+                       if (isInColHeader && isInRowHeader)
+                               return new HitTestInfo (-1, x, -1, y, DataGridViewHitTestType.TopLeftHeader);
+                       
+                       // HorizontalScrollBar
+                       if (horizontalScrollBar.Visible && horizontalScrollBar.Bounds.Contains (x, y))
+                               return new HitTestInfo (-1, x, -1, y, DataGridViewHitTestType.HorizontalScrollBar);
+
+                       // VerticalScrollBar
+                       if (verticalScrollBar.Visible && verticalScrollBar.Bounds.Contains (x, y))
+                               return new HitTestInfo (-1, x, -1, y, DataGridViewHitTestType.VerticalScrollBar);
+                       
+                       // The little box in the bottom right if both scrollbars are shown is None
+                       if (verticalScrollBar.Visible && horizontalScrollBar.Visible)
+                               if (new Rectangle (verticalScrollBar.Left, horizontalScrollBar.Top, verticalScrollBar.Width, horizontalScrollBar.Height).Contains (x, y))
+                                       return new HitTestInfo (-1, x, -1, y, DataGridViewHitTestType.None);
+                       
+                       int rowindex = -1;
+                       int colindex = -1;
+                       
+                       int top = columnHeadersVisible ? columnHeadersHeight : 0;
+                       
+                       for (int i = first_row_index; i < Rows.Count; i++) {
+                               DataGridViewRow row = Rows[i];
+                               
+                               if (y > top && y <= (top + row.Height)) {
+                                       rowindex = i;
+                                       break;
                                }
+                               
+                               top += row.Height;
                        }
-                       HitTestInfo result;
                        
-                       if (colIndex >= 0 && rowIndex >= 0) {
-                               result = new HitTestInfo (colIndex, x, rowIndex, y, DataGridViewHitTestType.Cell);
-                       } else if (isInColHeader && isInRowHeader) {
-                               result = new HitTestInfo (colIndex, x, rowIndex, y, DataGridViewHitTestType.TopLeftHeader);
-                       } else if (isInColHeader) {
-                               result = new HitTestInfo (colIndex, x, rowIndex, y, DataGridViewHitTestType.ColumnHeader);
-                       } else if (isInRowHeader) {
-                               result = new HitTestInfo (colIndex, x, rowIndex, y, DataGridViewHitTestType.RowHeader);
-                       } else {
-                               result = new HitTestInfo (colIndex, x, rowIndex, y, DataGridViewHitTestType.None);
+                       int left = rowHeadersVisible ? RowHeadersWidth : 0;
+
+                       List<DataGridViewColumn> cols = columns.ColumnDisplayIndexSortedArrayList;
+                       
+                       for (int i = first_col_index; i < cols.Count; i++) {
+                               if (!cols[i].Visible)
+                                       continue;
+                                       
+                               if (x > left && x <= (left + cols[i].Width)) {
+                                       colindex = cols[i].Index;
+                                       break;
+                               }
+
+                               left += cols[i].Width;
                        }
 
-                       return result;
+                       if (colindex >= 0 && rowindex >= 0)
+                               return new HitTestInfo (colindex, x, rowindex, y, DataGridViewHitTestType.Cell);
+                       
+                       if (isInColHeader && colindex > -1)
+                               return new HitTestInfo (colindex, x, rowindex, y, DataGridViewHitTestType.ColumnHeader);
+                       
+                       if (isInRowHeader && rowindex > -1)
+                               return new HitTestInfo (colindex, x, rowindex, y, DataGridViewHitTestType.RowHeader);
+                               
+                       return new HitTestInfo (-1, x, -1, y, DataGridViewHitTestType.None);
                }
 
                [MonoTODO ("Invalidates whole grid")]
@@ -2506,7 +2704,7 @@ namespace System.Windows.Forms {
                        if (dataGridViewCell.DataGridView != this)
                                throw new ArgumentException ("The specified cell does not belong to this DataGridView.");
 
-                       Invalidate ();
+                       InvalidateCell (dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex);
                }
 
                [MonoTODO ("Invalidates whole grid")]
@@ -2518,14 +2716,7 @@ namespace System.Windows.Forms {
                        if (rowIndex < 0 || rowIndex >= rows.Count)
                                throw new ArgumentOutOfRangeException ("Row index is out of range.");
 
-                       foreach (DataGridViewRow row in rows) {
-                               foreach (DataGridViewCell cell in row.Cells) {
-                                       if (cell.RowIndex == rowIndex && cell.ColumnIndex == columnIndex) {
-                                               InvalidateCell (cell);
-                                               return;
-                                       }
-                               }
-                       }
+                       Invalidate (GetCellDisplayRectangle (columnIndex, rowIndex, true));
                }
 
                [MonoTODO ("Invalidates whole grid")]
@@ -2534,7 +2725,7 @@ namespace System.Windows.Forms {
                        if (columnIndex < 0 || columnIndex >= columns.Count)
                                throw new ArgumentOutOfRangeException ("Column index is out of range.");
 
-                       Invalidate ();
+                       Invalidate (GetColumnDisplayRectangle (columnIndex, true));
                }
 
                [MonoTODO ("Invalidates whole grid")]
@@ -2543,20 +2734,27 @@ namespace System.Windows.Forms {
                        if (rowIndex < 0 || rowIndex >= rows.Count)
                                throw new ArgumentOutOfRangeException ("Row index is out of range.");
 
-                       Invalidate ();
+                       Invalidate (GetRowDisplayRectangle (rowIndex, true));
                }
 
                public virtual void NotifyCurrentCellDirty (bool dirty) {
                        throw new NotImplementedException();
                }
 
-               public bool RefreshEdit () {
-                       throw new NotImplementedException();
+               public bool RefreshEdit ()
+               {
+                       if (IsCurrentCellInEditMode) {
+                               currentCell.InitializeEditingControl (currentCell.RowIndex, currentCell.FormattedValue, currentCell.InheritedStyle);
+                               return true;
+                       }
+                       
+                       return false;
                }
 
                [EditorBrowsable (EditorBrowsableState.Never)]
-               public override void ResetText () {
-                       throw new NotImplementedException();
+               public override void ResetText ()
+               {
+                       Text = string.Empty;
                }
 
                public void SelectAll () {
@@ -2579,39 +2777,118 @@ namespace System.Windows.Forms {
                                        }
                                        break;
                        }
+                       
+                       Invalidate ();
                }
 
-               public virtual void Sort (IComparer comparer) {
-                       throw new NotImplementedException();
-               }
+               public virtual void Sort (IComparer comparer)
+               {
+                       if (comparer == null)
+                               throw new ArgumentNullException ("comparer");
+                       if (VirtualMode || DataSource != null)
+                               throw new InvalidOperationException ();
 
-               public virtual void Sort (DataGridViewColumn dataGridViewColumn, ListSortDirection direction) {
-                       throw new NotImplementedException();
+                       if (SortedColumn != null)
+                               SortedColumn.HeaderCell.SortGlyphDirection = SortOrder.None;
+
+                       EndEdit ();
+
+                       Rows.Sort (comparer);
+                       
+                       sortedColumn = null;
+                       sortOrder = SortOrder.None;
+                       
+                       currentCell = null;
+                       
+                       Invalidate ();
+                       
+                       OnSorted (EventArgs.Empty);
                }
 
+               public virtual void Sort (DataGridViewColumn dataGridViewColumn, ListSortDirection direction)
+               {
+                       if (dataGridViewColumn == null)
+                               throw new ArgumentNullException ("dataGridViewColumn");
+                       if (dataGridViewColumn.DataGridView != this)
+                               throw new ArgumentException ("dataGridViewColumn");
+                       // XXX: This is thrown too much, disable for now..
+                       //if (DataSource != null && !dataGridViewColumn.IsDataBound)
+                       //        throw new ArgumentException ("dataGridViewColumn");
+                       if (VirtualMode && !dataGridViewColumn.IsDataBound)
+                               throw new InvalidOperationException ();
+
+                       if (SortedColumn != null)
+                               SortedColumn.HeaderCell.SortGlyphDirection = SortOrder.None;
+
+                       EndEdit ();
+                       
+                       ColumnSorter sorter = new ColumnSorter (dataGridViewColumn, direction);
+                       Rows.Sort (sorter);
+
+                       sortedColumn = dataGridViewColumn;
+                       sortOrder = (SortOrder)direction + 1;
+
+                       dataGridViewColumn.HeaderCell.SortGlyphDirection = (SortOrder)direction + 1;
+
+                       Invalidate ();
+
+                       OnSorted (EventArgs.Empty);
+               }
+               
                public void UpdateCellErrorText (int columnIndex, int rowIndex)
                {
-                       throw new NotImplementedException();
+                       if (columnIndex < 0 || columnIndex > Columns.Count - 1)
+                               throw new ArgumentOutOfRangeException ("columnIndex");
+                       if (rowIndex < 0 || rowIndex > Rows.Count - 1)
+                               throw new ArgumentOutOfRangeException ("rowIndex");
+
+                       InvalidateCell (columnIndex, rowIndex);
                }
 
                public void UpdateCellValue (int columnIndex, int rowIndex)
                {
-                       throw new NotImplementedException();
+                       if (columnIndex < 0 || columnIndex > Columns.Count - 1)
+                               throw new ArgumentOutOfRangeException ("columnIndex");
+                       if (rowIndex < 0 || rowIndex > Rows.Count - 1)
+                               throw new ArgumentOutOfRangeException ("rowIndex");
+                       
+                       InvalidateCell (columnIndex, rowIndex);
                }
 
                public void UpdateRowErrorText (int rowIndex)
                {
-                       throw new NotImplementedException();
+                       if (rowIndex < 0 || rowIndex > Rows.Count - 1)
+                               throw new ArgumentOutOfRangeException ("rowIndex");
+
+                       InvalidateRow (rowIndex);
                }
 
-               public void UpdateRowErrorText (int rowIndexStart, int rowIndexEnd) {
-                       throw new NotImplementedException();
+               public void UpdateRowErrorText (int rowIndexStart, int rowIndexEnd)
+               {
+                       if (rowIndexStart < 0 || rowIndexStart > Rows.Count - 1)
+                               throw new ArgumentOutOfRangeException ("rowIndexStart");
+                       if (rowIndexEnd < 0 || rowIndexEnd > Rows.Count - 1)
+                               throw new ArgumentOutOfRangeException ("rowIndexEnd");
+                       if (rowIndexEnd < rowIndexStart)
+                               throw new ArgumentOutOfRangeException ("rowIndexEnd", "rowIndexEnd must be greater than rowIndexStart");
+                               
+                       for (int i = rowIndexStart; i <= rowIndexEnd; i++)
+                               InvalidateRow (i);
                }
 
                public void UpdateRowHeightInfo (int rowIndex, bool updateToEnd) {
                        throw new NotImplementedException();
                }
 
+               protected override bool CanEnableIme {
+                       get {
+                               if (CurrentCell != null && CurrentCell.EditType != null)
+                                       return true;
+                               
+                               return false;
+                       }
+               }
+
                protected override Size DefaultSize {
                        get { return new Size (240, 150); }
                }
@@ -2629,16 +2906,22 @@ namespace System.Windows.Forms {
                        throw new NotImplementedException ();
                }
 
-               protected void AutoResizeColumn (int columnIndex, DataGridViewAutoSizeColumnMode autoSizeColumnMode, bool fixedHeight) {
-                       throw new NotImplementedException();
+               [MonoTODO ("Does not use fixedHeight parameter")]
+               protected void AutoResizeColumn (int columnIndex, DataGridViewAutoSizeColumnMode autoSizeColumnMode, bool fixedHeight)
+               {
+                       AutoResizeColumn (columnIndex, autoSizeColumnMode);
                }
 
-               protected void AutoResizeColumnHeadersHeight (bool fixedRowHeadersWidth, bool fixedColumnsWidth) {
-                       throw new NotImplementedException();
+               [MonoTODO ("Does not use fixedRowHeadersWidth or fixedColumnsWidth parameters")]
+               protected void AutoResizeColumnHeadersHeight (bool fixedRowHeadersWidth, bool fixedColumnsWidth)
+               {
+                       AutoResizeColumnHeadersHeight ();
                }
 
-               protected void AutoResizeColumnHeadersHeight (int columnIndex, bool fixedRowHeadersWidth, bool fixedColumnWidth) {
-                       throw new NotImplementedException();
+               [MonoTODO ("Does not use columnIndex or fixedRowHeadersWidth or fixedColumnsWidth parameters")]
+               protected void AutoResizeColumnHeadersHeight (int columnIndex, bool fixedRowHeadersWidth, bool fixedColumnWidth)
+               {
+                       AutoResizeColumnHeadersHeight (columnIndex);
                }
 
                protected void AutoResizeColumns (DataGridViewAutoSizeColumnsMode autoSizeColumnsMode, bool fixedHeight) {
@@ -2647,24 +2930,84 @@ namespace System.Windows.Forms {
                        }
                }
 
-               protected void AutoResizeRow (int rowIndex, DataGridViewAutoSizeRowMode autoSizeRowMode, bool fixedWidth) {
-                       throw new NotImplementedException();
+               [MonoTODO ("Does not use fixedWidth parameter")]
+               protected void AutoResizeRow (int rowIndex, DataGridViewAutoSizeRowMode autoSizeRowMode, bool fixedWidth)
+               {
+                       AutoResizeRow (rowIndex, autoSizeRowMode);
                }
 
-               protected void AutoResizeRowHeadersWidth (DataGridViewRowHeadersWidthSizeMode rowHeadersWidthSizeMode, bool fixedColumnHeadersHeight, bool fixedRowsHeight) {
-                       throw new NotImplementedException();
+               [MonoTODO ("Does not use fixedColumnHeadersHeight or fixedRowsHeight parameter")]
+               protected void AutoResizeRowHeadersWidth (DataGridViewRowHeadersWidthSizeMode rowHeadersWidthSizeMode, bool fixedColumnHeadersHeight, bool fixedRowsHeight)
+               {
+                       AutoResizeRowHeadersWidth (rowHeadersWidthSizeMode);
                }
 
-               protected void AutoResizeRowHeadersWidth (int rowIndex, DataGridViewRowHeadersWidthSizeMode rowHeadersWidthSizeMode, bool fixedColumnHeadersHeight, bool fixedRowHeight) {
-                       throw new NotImplementedException();
+               [MonoTODO ("Does not use rowIndex or fixedColumnHeadersHeight or fixedRowsHeight parameter")]
+               protected void AutoResizeRowHeadersWidth (int rowIndex, DataGridViewRowHeadersWidthSizeMode rowHeadersWidthSizeMode, bool fixedColumnHeadersHeight, bool fixedRowHeight)
+               {
+                       AutoResizeRowHeadersWidth (rowHeadersWidthSizeMode);
                }
 
-               protected void AutoResizeRows (DataGridViewAutoSizeRowsMode autoSizeRowsMode, bool fixedWidth) {
-                       throw new NotImplementedException();
-               }
+               [MonoTODO ("Does not use fixedMode parameter")]
+               protected void AutoResizeRows (DataGridViewAutoSizeRowsMode autoSizeRowsMode, bool fixedWidth)
+               {
+                       if (autoSizeRowsMode == DataGridViewAutoSizeRowsMode.None)
+                               return;
+                               
+                       bool include_headers = false;
+                       bool include_cells = false;
+                       bool displayed_only = false;
 
-               protected void AutoResizeRows (int rowIndexStart, int rowsCount, DataGridViewAutoSizeRowMode autoSizeRowMode, bool fixedWidth) {
-                       throw new NotImplementedException();
+                       switch (autoSizeRowsMode) {
+                               case DataGridViewAutoSizeRowsMode.AllHeaders:
+                                       include_headers = true;
+                                       break;
+                               case DataGridViewAutoSizeRowsMode.AllCellsExceptHeaders:
+                                       include_cells = true;
+                                       break;
+                               case DataGridViewAutoSizeRowsMode.AllCells:
+                                       include_cells = true;
+                                       include_headers = true;
+                                       break;
+                               case DataGridViewAutoSizeRowsMode.DisplayedHeaders:
+                                       include_headers = true;
+                                       displayed_only = true;
+                                       break;
+                               case DataGridViewAutoSizeRowsMode.DisplayedCellsExceptHeaders:
+                                       include_cells = true;
+                                       displayed_only = true;
+                                       break;
+                               case DataGridViewAutoSizeRowsMode.DisplayedCells:
+                                       include_cells = true;
+                                       include_headers = true;
+                                       displayed_only = true;
+                                       break;
+                       }
+                       
+                       foreach (DataGridViewRow row in Rows) {
+                               int new_height = 0;
+                               
+                               if (include_headers)
+                                       if (!displayed_only || row.HeaderCell.Displayed)
+                                               new_height = Math.Max (new_height, row.HeaderCell.PreferredSize.Height);
+
+                               if (include_cells)
+                                       foreach (DataGridViewCell cell in row.Cells)
+                                               if (!displayed_only || cell.Displayed)
+                                                       new_height = Math.Max (new_height, cell.PreferredSize.Height);
+                               
+                               new_height = Math.Max (new_height, row.MinimumHeight);
+                               
+                               if (row.Height != new_height)
+                                       row.Height = new_height;
+                       }
+               }
+
+               [MonoTODO ("Does not use fixedMode parameter")]
+               protected void AutoResizeRows (int rowIndexStart, int rowsCount, DataGridViewAutoSizeRowMode autoSizeRowMode, bool fixedWidth)
+               {
+                       for (int i = rowIndexStart; i < rowIndexStart + rowsCount; i++)
+                               AutoResizeRow (i, autoSizeRowMode, fixedWidth);
                }
 
                protected void ClearSelection (int columnIndexException, int rowIndexException, bool selectExceptionElement) {
@@ -2754,12 +3097,32 @@ namespace System.Windows.Forms {
 
                protected override bool IsInputChar (char charCode)
                {
-                       return base.IsInputChar(charCode);
+                       return true;
                }
 
                protected override bool IsInputKey (Keys keyData)
                {
-                       return base.IsInputKey(keyData);
+                       // Don't look at the modifiers
+                       keyData = keyData & ~Keys.Modifiers;
+                       
+                       switch (keyData) {
+                               case Keys.Return:
+                               case Keys.PageUp:
+                               case Keys.Next:
+                               case Keys.End:
+                               case Keys.Home:
+                               case Keys.Left:
+                               case Keys.Up:
+                               case Keys.Right:
+                               case Keys.Down:
+                               case Keys.Delete:
+                               case Keys.D0:
+                               case Keys.NumPad0:
+                               case Keys.F2:
+                                       return true;
+                       }
+
+                       return false;
                }
 
                protected virtual void OnAllowUserToAddRowsChanged (EventArgs e)
@@ -3142,6 +3505,13 @@ namespace System.Windows.Forms {
 
                internal void OnColumnAddedInternal (DataGridViewColumnEventArgs e)
                {
+                       if (e.Column.CellTemplate != null) {
+                               RowTemplate.Cells.Add ((DataGridViewCell)e.Column.CellTemplate.Clone ());
+
+                               foreach (DataGridViewRow row in Rows)
+                                       row.Cells.Add ((DataGridViewCell)RowTemplate.Cells[RowTemplate.Cells.Count - 1].Clone ());
+                       }
+                       
                        AutoResizeColumnsInternal ();
                        OnColumnAdded (e);
                        PrepareEditingRow (false, true);
@@ -3205,6 +3575,21 @@ namespace System.Windows.Forms {
 
                protected virtual void OnColumnHeaderMouseClick (DataGridViewCellMouseEventArgs e)
                {
+                       DataGridViewColumn col = Columns[e.ColumnIndex];
+                       
+                       if (col.SortMode == DataGridViewColumnSortMode.Automatic) {
+                               ListSortDirection new_order;
+                               
+                               // Always use ascending unless we are clicking on a
+                               // column that is already sorted ascending.
+                               if (SortedColumn != col || sortOrder != SortOrder.Ascending)
+                                       new_order = ListSortDirection.Ascending;
+                               else
+                                       new_order = ListSortDirection.Descending;
+
+                               Sort (col, new_order);
+                       }
+                       
                        DataGridViewCellMouseEventHandler eh = (DataGridViewCellMouseEventHandler)(Events [ColumnHeaderMouseClickEvent]);
                        if (eh != null)
                                eh (this, e);
@@ -3320,16 +3705,14 @@ namespace System.Windows.Forms {
                                eh (this, e);
                }
 
-               protected virtual void OnDataError (bool displayErrorDialogIfNoHandler, DataGridViewDataErrorEventArgs e) {
+               protected virtual void OnDataError (bool displayErrorDialogIfNoHandler, DataGridViewDataErrorEventArgs e)
+               {
                        DataGridViewDataErrorEventHandler eh = (DataGridViewDataErrorEventHandler)(Events [DataErrorEvent]);
-                       if (eh != null) {
+                       
+                       if (eh != null)
                                eh (this, e);
-                       }
-                       else {
-                               if (displayErrorDialogIfNoHandler) {
-                                       /////////////////////////////////// ERROR DIALOG //////////////////////////////////7
-                               }
-                       }
+                       else if (displayErrorDialogIfNoHandler)
+                               MessageBox.Show (e.ToString ());
                }
                protected virtual void OnDataMemberChanged (EventArgs e) {
                        EventHandler eh = (EventHandler)(Events [DataMemberChangedEvent]);
@@ -3411,6 +3794,9 @@ namespace System.Windows.Forms {
                protected override void OnHandleCreated (EventArgs e)
                {
                        base.OnHandleCreated(e);
+                       
+                       if (Rows.Count > 0 && Columns.Count > 0)
+                               MoveCurrentCell (ColumnDisplayIndexToIndex (0), 0, true, false, false, false);
                }
 
                protected override void OnHandleDestroyed(EventArgs e)
@@ -3421,7 +3807,9 @@ namespace System.Windows.Forms {
                [EditorBrowsable (EditorBrowsableState.Advanced)]
                protected override void OnKeyDown (KeyEventArgs e)
                {
-                       base.OnKeyDown(e);
+                       base.OnKeyDown (e);
+
+                       e.Handled = ProcessDataGridViewKey (e);
                }
 
                [EditorBrowsable (EditorBrowsableState.Advanced)]
@@ -3438,10 +3826,15 @@ namespace System.Windows.Forms {
 
                protected override void OnLayout (LayoutEventArgs e)
                {
-                       if (horizontalScrollBar.Visible)
-                               horizontalScrollBar.Bounds = new Rectangle (BorderWidth, Bottom - BorderWidth - horizontalScrollBar.Height, Width - (2 * BorderWidth), horizontalScrollBar.Height);
-                       if (verticalScrollBar.Visible)
-                               verticalScrollBar.Bounds = new Rectangle (Right - BorderWidth - verticalScrollBar.Width, BorderWidth, verticalScrollBar.Width,  Height - (2 * BorderWidth));
+                       if (horizontalScrollBar.Visible && verticalScrollBar.Visible) {
+                               horizontalScrollBar.Bounds = new Rectangle (BorderWidth, Height - BorderWidth - horizontalScrollBar.Height, Width - (2 * BorderWidth) - verticalScrollBar.Width, horizontalScrollBar.Height);
+                               verticalScrollBar.Bounds = new Rectangle (Width - BorderWidth - verticalScrollBar.Width, BorderWidth, verticalScrollBar.Width, Height - (2 * BorderWidth) - horizontalScrollBar.Height);
+                       } else if (horizontalScrollBar.Visible)
+                               horizontalScrollBar.Bounds = new Rectangle (BorderWidth, Height - BorderWidth - horizontalScrollBar.Height, Width - (2 * BorderWidth), horizontalScrollBar.Height);
+                       else if (verticalScrollBar.Visible)
+                               verticalScrollBar.Bounds = new Rectangle (Width - BorderWidth - verticalScrollBar.Width, BorderWidth, verticalScrollBar.Width,  Height - (2 * BorderWidth));
+                               
+                       Invalidate ();
                }
 
                protected override void OnLeave (EventArgs e)
@@ -3464,13 +3857,28 @@ namespace System.Windows.Forms {
                        //Console.WriteLine("Mouse: Clicks: {0}; Delta: {1}; X: {2}; Y: {3};", e.Clicks, e.Delta, e.X, e.Y);
                        HitTestInfo hit = HitTest (e.X, e.Y);
 
-                       switch (hit.Type) 
-                       {
-                       case DataGridViewHitTestType.Cell:
-                               Rectangle display = GetCellDisplayRectangle (hit.ColumnIndex, hit.RowIndex, false);
-                               OnCellMouseClick (new DataGridViewCellMouseEventArgs (hit.ColumnIndex, hit.RowIndex, e.X - display.X, e.Y - display.Y, e));
-                               break;
-                       
+                       switch (hit.Type) {
+                               case DataGridViewHitTestType.Cell:
+                                       Rectangle display = GetCellDisplayRectangle (hit.ColumnIndex, hit.RowIndex, false);
+                                       Point cellpoint = new Point (e.X - display.X, e.Y - display.Y);
+
+                                       OnCellMouseClick (new DataGridViewCellMouseEventArgs (hit.ColumnIndex, hit.RowIndex, cellpoint.X, cellpoint.Y, e));
+                                       
+                                       DataGridViewCell cell = GetCellInternal (hit.ColumnIndex, hit.RowIndex);
+                                       
+                                       if (cell.GetContentBounds (hit.RowIndex).Contains (cellpoint)) {
+                                               DataGridViewCellEventArgs dgvcea = new DataGridViewCellEventArgs (hit.ColumnIndex, hit.RowIndex);
+                                               OnCellContentClick (dgvcea);
+                                               cell.OnContentClickInternal (dgvcea);
+                                       }
+                                               
+                                       break;
+                               case DataGridViewHitTestType.ColumnHeader:
+                                       Rectangle display2 = GetCellDisplayRectangle (hit.ColumnIndex, hit.RowIndex, false);
+                                       Point cellpoint2 = new Point (e.X - display2.X, e.Y - display2.Y);
+                                       
+                                       OnColumnHeaderMouseClick (new DataGridViewCellMouseEventArgs (hit.ColumnIndex, hit.RowIndex, cellpoint2.X, cellpoint2.Y, e));
+                                       break;
                        }
                }
 
@@ -3494,9 +3902,15 @@ namespace System.Windows.Forms {
                                break;
                        case DataGridViewHitTestType.ColumnHeader:
                                mode = selectionMode == DataGridViewSelectionMode.ColumnHeaderSelect ? DataGridViewSelectionMode.FullColumnSelect : selectionMode;
+                               
+                               if (mode != DataGridViewSelectionMode.FullColumnSelect)
+                                       return;
                                break;
                        case DataGridViewHitTestType.RowHeader:
                                mode = selectionMode == DataGridViewSelectionMode.RowHeaderSelect ?  DataGridViewSelectionMode.FullRowSelect : selectionMode;
+
+                               if (mode != DataGridViewSelectionMode.FullRowSelect)
+                                       return;
                                break; // Handled below
                        default:
                                return;
@@ -3633,6 +4047,10 @@ namespace System.Windows.Forms {
                        DoSelectionOnMouseDown (hitTest);
                        
                        if (hitTest.Type != DataGridViewHitTestType.Cell) {
+                               if (hitTest.Type == DataGridViewHitTestType.ColumnHeader)
+                                       pressed_header_cell = columns [hitTest.ColumnIndex].HeaderCell;
+                               else if (hitTest.Type == DataGridViewHitTestType.RowHeader)
+                                       pressed_header_cell = rows [hitTest.RowIndex].HeaderCell;
                                Invalidate ();
                                return;
                        }
@@ -3644,6 +4062,7 @@ namespace System.Windows.Forms {
                                OnCellLeave(new DataGridViewCellEventArgs(currentCell.ColumnIndex, currentCell.RowIndex));
                        }
                        currentCell = cell;
+                       currentCellAddress = new Point (currentCell.ColumnIndex, currentCell.RowIndex);
                        currentRow = cell.OwningRow;
                        OnCurrentCellChanged(EventArgs.Empty);
                        OnCellEnter(new DataGridViewCellEventArgs(cell.ColumnIndex, cell.RowIndex));
@@ -3661,36 +4080,145 @@ namespace System.Windows.Forms {
 
                protected override void OnMouseLeave (EventArgs e)
                {
-                       base.OnMouseLeave(e);
+                       base.OnMouseLeave (e);
+                       
+                       if (hover_cell != null) {
+                               OnCellMouseLeave (new DataGridViewCellEventArgs (hover_cell.ColumnIndex, hover_cell.RowIndex));
+                               hover_cell = null;
+                       }
+                       
+                       EnteredHeaderCell = null;
                }
-
+               
                protected override void OnMouseMove (MouseEventArgs e)
                {
-                       base.OnMouseMove(e);
+                       base.OnMouseMove (e);
+                       
                        HitTestInfo hit = this.HitTest (e.X, e.Y);
                        
-                       switch (hit.Type)
-                       {
-                       case DataGridViewHitTestType.Cell:
-                               Rectangle display = GetCellDisplayRectangle (hit.ColumnIndex, hit.RowIndex, false);
-                               OnCellMouseMove (new DataGridViewCellMouseEventArgs (hit.ColumnIndex, hit.RowIndex, e.X - display.X, e.Y - display.Y, e));
-                               break;
-                       case DataGridViewHitTestType.ColumnHeader:
-                       case DataGridViewHitTestType.RowHeader:
-                       case DataGridViewHitTestType.TopLeftHeader:
+                       if (hit.Type == DataGridViewHitTestType.Cell) {
+                               EnteredHeaderCell = null;
+
+                               DataGridViewCell new_cell = GetCellInternal (hit.ColumnIndex, hit.RowIndex);
+                               
+                               // Check if we have moved into an error icon area
+                               Rectangle icon = new_cell.ErrorIconBounds;
+
+                               if (!icon.IsEmpty) {
+                                       Point loc = GetCellDisplayRectangle (hit.ColumnIndex, hit.RowIndex, false).Location;
+                                       
+                                       icon.X += loc.X;
+                                       icon.Y += loc.Y;
+                                       
+                                       if (icon.Contains (e.X, e.Y)) {
+                                               if (tooltip_currently_showing != new_cell)
+                                                       MouseEnteredErrorIcon (new_cell);
+                                       } else
+                                               MouseLeftErrorIcon (new_cell);
+                               }
+                               
+                               // We have never been in a cell before
+                               if (hover_cell == null) {
+                                       hover_cell = new_cell;
+                                       OnCellMouseEnter (new DataGridViewCellEventArgs (hit.ColumnIndex, hit.RowIndex));
+                                       
+                                       Rectangle display = GetCellDisplayRectangle (hit.ColumnIndex, hit.RowIndex, false);
+                                       OnCellMouseMove (new DataGridViewCellMouseEventArgs (hit.ColumnIndex, hit.RowIndex, e.X - display.X, e.Y - display.Y, e));
+                                       
+                                       return;
+                               }
                        
-                       case DataGridViewHitTestType.HorizontalScrollBar:
-                       case DataGridViewHitTestType.VerticalScrollBar:
+                               // Were we already in this cell?
+                               if (hover_cell.RowIndex == hit.RowIndex && hover_cell.ColumnIndex == hit.ColumnIndex) {
+                                       Rectangle display = GetCellDisplayRectangle (hit.ColumnIndex, hit.RowIndex, false);
+                                       OnCellMouseMove (new DataGridViewCellMouseEventArgs (hit.ColumnIndex, hit.RowIndex, e.X - display.X, e.Y - display.Y, e));
+                               
+                                       return;
+                               }
                        
+                               // We are changing cells
+                               OnCellMouseLeave (new DataGridViewCellEventArgs (hover_cell.ColumnIndex, hover_cell.RowIndex));
+
+                               hover_cell = new_cell;
+                               
+                               OnCellMouseEnter (new DataGridViewCellEventArgs (hit.ColumnIndex, hit.RowIndex));
+
+                               Rectangle display2 = GetCellDisplayRectangle (hit.ColumnIndex, hit.RowIndex, false);
+                               OnCellMouseMove (new DataGridViewCellMouseEventArgs (hit.ColumnIndex, hit.RowIndex, e.X - display2.X, e.Y - display2.Y, e));
+
+                               return;
+                       } else if (hit.Type == DataGridViewHitTestType.RowHeader) {
+                               DataGridViewRowHeaderCell new_cell = Rows[hit.RowIndex].HeaderCell;
+
+                               EnteredHeaderCell = new_cell;
+
+                               // Check if we have moved into an error icon area
+                               Rectangle icon = new_cell.InternalErrorIconsBounds;
+
+                               if (!icon.IsEmpty) {
+                                       Point loc = GetCellDisplayRectangle (0, hit.RowIndex, false).Location;
+
+                                       icon.X += BorderWidth;
+                                       icon.Y += loc.Y;
+
+                                       if (icon.Contains (e.X, e.Y)) {
+                                               if (tooltip_currently_showing != new_cell)
+                                                       MouseEnteredErrorIcon (new_cell);
+                                       } else
+                                               MouseLeftErrorIcon (new_cell);
+                               }
+                       } else if (hit.Type == DataGridViewHitTestType.TopLeftHeader) {
+                               EnteredHeaderCell = null;
+
+                               DataGridViewTopLeftHeaderCell new_cell = (DataGridViewTopLeftHeaderCell)TopLeftHeaderCell;
+
+                               // Check if we have moved into an error icon area
+                               Rectangle icon = new_cell.InternalErrorIconsBounds;
+
+                               if (!icon.IsEmpty) {
+                                       Point loc = Point.Empty;
+
+                                       icon.X += BorderWidth;
+                                       icon.Y += loc.Y;
+
+                                       if (icon.Contains (e.X, e.Y)) {
+                                               if (tooltip_currently_showing != new_cell)
+                                                       MouseEnteredErrorIcon (new_cell);
+                                       } else
+                                               MouseLeftErrorIcon (new_cell);
+                               }
                        
-                       case DataGridViewHitTestType.None:
-                               break;
+                       } else {
+                               if (hit.Type == DataGridViewHitTestType.ColumnHeader)
+                                       EnteredHeaderCell = Columns [hit.ColumnIndex].HeaderCell;
+                               else
+                                       EnteredHeaderCell = null;
+
+                               // We have left the cell area
+                               if (hover_cell != null) {
+                                       OnCellMouseLeave (new DataGridViewCellEventArgs (hover_cell.ColumnIndex, hover_cell.RowIndex));
+                                       hover_cell = null;
+                               }
                        }
                }
 
                protected override void OnMouseUp (MouseEventArgs e)
                {
                        base.OnMouseUp(e);
+
+                       HitTestInfo hit = this.HitTest (e.X, e.Y);
+
+                       if (hit.Type == DataGridViewHitTestType.Cell) {
+                               Rectangle display = GetCellDisplayRectangle (hit.ColumnIndex, hit.RowIndex, false);
+                               OnCellMouseUp (new DataGridViewCellMouseEventArgs (hit.ColumnIndex, hit.RowIndex, e.X - display.X, e.Y - display.Y, e));
+                       }
+
+                       if (pressed_header_cell != null) {
+                               DataGridViewHeaderCell cell = pressed_header_cell;
+                               pressed_header_cell = null;
+                               if (ThemeEngine.Current.DataGridViewHeaderCellHasPressedStyle (this))
+                                       Invalidate (GetHeaderCellBounds (cell));
+                       }
                }
 
                protected override void OnMouseWheel (MouseEventArgs e)
@@ -3709,6 +4237,9 @@ namespace System.Windows.Forms {
                        if (eh != null) eh (this, e);
                }
 
+               int first_row_index = 0;
+               internal int first_col_index = 0;
+
                protected override void OnPaint (PaintEventArgs e)
                {
                        base.OnPaint(e);
@@ -3718,16 +4249,14 @@ namespace System.Windows.Forms {
                        
                        // Paint the background
                        PaintBackground (g, e.ClipRectangle, bounds);
-                       
-                       ArrayList sortedColumns = columns.ColumnDisplayIndexSortedArrayList;
-                       bounds.Y = -verticalScrollingOffset;
-                       bounds.X = -horizontalScrollingOffset;
+
+                       List<DataGridViewColumn> sortedColumns = columns.ColumnDisplayIndexSortedArrayList;
                        
                        // Take borders into account
                        bounds.Inflate (-BorderWidth, -BorderWidth);
                        
                        // Paint the top left cell
-                       if (rowHeadersVisible && columnHeadersVisible) {
+                       if (rowHeadersVisible && columnHeadersVisible && ColumnCount > 0) {
                                Rectangle topleftbounds = new Rectangle (bounds.X, bounds.Y, rowHeadersWidth, columnHeadersHeight);
                                
                                TopLeftHeaderCell.PaintWork (g, e.ClipRectangle, topleftbounds, -1, TopLeftHeaderCell.State, ColumnHeadersDefaultCellStyle, AdvancedColumnHeadersBorderStyle, DataGridViewPaintParts.All);
@@ -3741,7 +4270,12 @@ namespace System.Windows.Forms {
                                if (rowHeadersVisible)
                                        headerBounds.X += rowHeadersWidth;
                                
-                               foreach (DataGridViewColumn col in sortedColumns) {
+                               for (int index = first_col_index; index < sortedColumns.Count; index++) {
+                                       DataGridViewColumn col = sortedColumns[index];
+                                       
+                                       if (!col.Visible)
+                                               continue;
+                                       
                                        headerBounds.Width = col.Width;
                                        DataGridViewCell cell = col.HeaderCell;
 
@@ -3756,31 +4290,73 @@ namespace System.Windows.Forms {
                                bounds.Y += columnHeadersHeight;
                        }
                        
+                       gridWidth = rowHeadersVisible ? rowHeadersWidth : 0;
+                       gridHeight = 0;
+                       
+                       int rows_displayed = 0;
+                       int first_row_height = Rows.Count > 0 ? Rows[Math.Min (Rows.Count - 1, first_row_index)].Height : 0;
+//                     int room_left = this.Height;
+                       
+                       // Reset all columns to !Displayed
+                       for (int i = 0; i < Columns.Count; i++)
+                               Columns[i].DisplayedInternal = false;
+                       
+                       // Set Displayed columns
+                       for (int i = first_col_index; i < Columns.Count; i++) {
+                               DataGridViewColumn col = Columns.ColumnDisplayIndexSortedArrayList[i];
+
+                               if (!col.Visible)
+                                       continue;
+                       
+                               col.DisplayedInternal = true;
+                               gridWidth += col.Width;
+                               
+                               if (gridWidth >= Width)
+                                       break;
+                       }
+                       
+                       // Reset all rows to !Displayed
+                       for (int i = 0; i < Rows.Count; i++)
+                               GetRowInternal (i).DisplayedInternal = false;
                        
                        // Draw rows
-                       foreach (DataGridViewRow row in rows) {
+                       for (int index = first_row_index; index < Rows.Count; index++) {
+                               DataGridViewRow row = Rows[index];
+                               GetRowInternal (index).DisplayedInternal = true;
+       
                                bounds.Height = row.Height;
                                bool is_first = row.Index == 0;
                                bool is_last = row.Index == rows.Count - 1;
 
                                row.Paint (g, e.ClipRectangle, bounds, row.Index, row.GetState (row.Index), is_first, is_last);
-                                                               
+
                                bounds.Y += bounds.Height;
-                               bounds.X = -horizontalScrollingOffset + BorderWidth;
+                               bounds.X = BorderWidth;
+                               
+                               if (bounds.Y < ClientSize.Height - (horizontalScrollBar.Visible ? horizontalScrollBar.Height : 0))
+                                       rows_displayed++;
+                               else
+                                       break;
+                                       
+                               gridHeight += row.Height;
                        }
-                       
+
                        gridWidth = 0;
-                       gridHeight = 0;
                        
                        foreach (DataGridViewColumn col in sortedColumns)
-                               gridWidth += col.Width;
+                               if (col.Visible)
+                                       gridWidth += col.Width;
+
+                       gridHeight = 0;
+                       
+                       foreach (DataGridViewRow row in Rows)
+                               gridHeight += row.Height;
 
-                       if (rowHeadersVisible) {
+                       if (rowHeadersVisible)
                                gridWidth += rowHeadersWidth;
-                       }
-                       if (columnHeadersVisible) {
+
+                       if (columnHeadersVisible)
                                gridHeight += columnHeadersHeight;
-                       }
                        
                        bool horizontalVisible = false;
                        bool verticalVisible = false;
@@ -3805,30 +4381,24 @@ namespace System.Windows.Forms {
                                }
                                if (horizontalVisible) {
                                        horizontalScrollBar.Minimum = 0;
-                                       if (verticalVisible) {
-                                               horizontalScrollBar.Maximum = gridWidth - ClientRectangle.Width + verticalScrollBar.Width;
-                                       }
-                                       else {
-                                               horizontalScrollBar.Maximum = gridWidth - ClientRectangle.Width;
-                                       }
-                                       horizontalScrollBar.LargeChange = horizontalScrollBar.Maximum / 10;
-                                       horizontalScrollBar.SmallChange = horizontalScrollBar.Maximum / 20;
+                                       horizontalScrollBar.Maximum = gridWidth;
+                                       horizontalScrollBar.SmallChange = Columns[first_col_index].Width;
+                                       horizontalScrollBar.LargeChange = ClientSize.Width - rowHeadersWidth;
                                }
                                if (verticalVisible) {
                                        verticalScrollBar.Minimum = 0;
-                                       if (horizontalVisible) {
-                                               verticalScrollBar.Maximum = gridHeight - ClientRectangle.Height + horizontalScrollBar.Height;
-                                       }
-                                       else {
-                                               verticalScrollBar.Maximum = gridHeight - ClientRectangle.Height;
-                                       }
-                                       verticalScrollBar.LargeChange = verticalScrollBar.Maximum / 10;
-                                       verticalScrollBar.SmallChange = verticalScrollBar.Maximum / 20;
+                                       verticalScrollBar.Maximum = gridHeight;
+                                       verticalScrollBar.SmallChange = first_row_height + 1;
+                                       verticalScrollBar.LargeChange = ClientSize.Height - columnHeadersHeight;
                                }
                        }
 
                        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;
@@ -3851,9 +4421,10 @@ namespace System.Windows.Forms {
 
                protected override void OnResize (EventArgs e) {
                        base.OnResize(e);
-                       horizontalScrollingOffset = ((gridWidth - Size.Width) > 0)? (gridWidth - Size.Width) : 0;
-                       verticalScrollingOffset = ((gridHeight - Size.Height) > 0)? (gridHeight - Size.Height) : 0;
                        AutoResizeColumnsInternal ();
+                       
+                       OnVScrollBarScroll (this, new ScrollEventArgs (ScrollEventType.ThumbPosition, verticalScrollBar.Value));
+                       OnHScrollBarScroll (this, new ScrollEventArgs (ScrollEventType.ThumbPosition, horizontalScrollBar.Value));
                }
 
                protected override void OnRightToLeftChanged (EventArgs e) {
@@ -4106,106 +4677,475 @@ namespace System.Windows.Forms {
 
                protected bool ProcessAKey (Keys keyData)
                {
-                       throw new NotImplementedException();
+                       if (!MultiSelect)
+                               return false;
+                               
+                       if ((keyData & Keys.Control) == Keys.Control) {
+                               SelectAll ();
+                               return true;
+                       }
+                       
+                       return false;
                }
 
                protected virtual bool ProcessDataGridViewKey (KeyEventArgs e)
                {
-                       throw new NotImplementedException();
+                       switch (e.KeyData & ~Keys.Modifiers) {
+                               case Keys.A:
+                                       return ProcessAKey (e.KeyData);
+                               case Keys.Delete:
+                                       return ProcessDeleteKey (e.KeyData);
+                               case Keys.Down:
+                                       return ProcessDownKey (e.KeyData);
+                               case Keys.Escape:
+                                       return ProcessEscapeKey (e.KeyData);
+                               case Keys.End:
+                                       return ProcessEndKey (e.KeyData);
+                               case Keys.Enter:
+                                       return ProcessEnterKey (e.KeyData);
+                               case Keys.F2:
+                                       return ProcessF2Key (e.KeyData);
+                               case Keys.Home:
+                                       return ProcessHomeKey (e.KeyData);
+                               case Keys.Left:
+                                       return ProcessLeftKey (e.KeyData);
+                               case Keys.Next:
+                                       return ProcessNextKey (e.KeyData);
+                               case Keys.Prior:
+                                       return ProcessPriorKey (e.KeyData);
+                               case Keys.Right:
+                                       return ProcessRightKey (e.KeyData);
+                               case Keys.Space:
+                                       return ProcessSpaceKey (e.KeyData);
+                               case Keys.Tab:
+                                       return ProcessTabKey (e.KeyData);
+                               case Keys.Up:
+                                       return ProcessUpKey (e.KeyData);
+                               case Keys.D0:
+                               case Keys.NumPad0:
+                                       return ProcessZeroKey (e.KeyData);
+                       }
+                       
+                       return false;
                }
 
                protected bool ProcessDeleteKey (Keys keyData)
                {
-                       throw new NotImplementedException();
+                       if (!allowUserToDeleteRows || SelectedRows.Count == 0)
+                               return false;
+
+                       int index = Math.Max (selected_row - SelectedRows.Count + 1, 0);
+                       
+                       for (int i = SelectedRows.Count - 1; i >= 0; i--) {
+                               DataGridViewRow row = SelectedRows[i];
+
+                               if (row.IsNewRow)
+                                       continue;
+
+                               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);
+                               else
+                                       Rows.RemoveAt (row.Index);
+                       }
+
+                       if (selected_rows != null)
+                               selected_rows.InternalClear ();
+                       if (selected_columns != null)
+                               selected_columns.InternalClear ();
+
+                       SetSelectedCellCore (0, Math.Min (index, Rows.Count - 1), true);
+                               
+                       return true;
                }
 
                protected override bool ProcessDialogKey (Keys keyData)
                {
+                       switch (keyData) {
+                               case Keys.Tab:
+                               case Keys.Shift | Keys.Tab:
+                                       if (standardTab)
+                                               return base.ProcessDialogKey (keyData & ~Keys.Control);
+                                               
+                                       if (ProcessDataGridViewKey (new KeyEventArgs (keyData)))
+                                               return true;
+                                               
+                                       break;
+                               case Keys.Control | Keys.Tab:
+                               case Keys.Control | Keys.Shift | Keys.Tab:
+                                       if (!standardTab)
+                                               return base.ProcessDialogKey (keyData & ~Keys.Control);
+
+                                       if (ProcessDataGridViewKey (new KeyEventArgs (keyData)))
+                                               return true;
+                                               
+                                       break;
+                       }
+                       
                        return base.ProcessDialogKey(keyData);
                }
 
-               protected bool ProcessDownKey (Keys keyData) {
-                       throw new NotImplementedException();
+               protected bool ProcessDownKey (Keys keyData)
+               {
+                       int current_row = CurrentCellAddress.Y;
+                       
+                       if (current_row < Rows.Count - 1) {
+                               EndEdit ();
+                               
+                               // Move to the last cell in the column
+                               if ((keyData & Keys.Control) == Keys.Control)
+                                       MoveCurrentCell (CurrentCellAddress.X, Rows.Count - 1, true, (keyData & Keys.Control) == Keys.Control, (keyData & Keys.Shift) == Keys.Shift, true);
+                               // Move one cell down
+                               else
+                                       MoveCurrentCell (CurrentCellAddress.X, current_row + 1, true, (keyData & Keys.Control) == Keys.Control, (keyData & Keys.Shift) == Keys.Shift, true);
+                               
+                               return true;
+                       }
+                       
+                       return false;
                }
 
-               protected bool ProcessEndKey (Keys keyData) {
-                       throw new NotImplementedException();
+               protected bool ProcessEndKey (Keys keyData)
+               {
+                       int disp_index = ColumnIndexToDisplayIndex (currentCellAddress.X);
+
+                       // Move to the last cell in the control
+                       if ((keyData & Keys.Control) == Keys.Control) {
+                               MoveCurrentCell (ColumnDisplayIndexToIndex (Columns.Count - 1), Rows.Count - 1, true, (keyData & Keys.Control) == Keys.Control, (keyData & Keys.Shift) == Keys.Shift, true);
+                               return true;
+                       }
+                       
+                       // Move to the last cell in the row
+                       if (disp_index < Columns.Count - 1) {
+                               MoveCurrentCell (ColumnDisplayIndexToIndex (Columns.Count - 1), currentCellAddress.Y, true, (keyData & Keys.Control) == Keys.Control, (keyData & Keys.Shift) == Keys.Shift, true);
+                               return true;
+                       }
+
+                       return false;
                }
 
-               protected bool ProcessEnterKey (Keys keyData) {
-                       throw new NotImplementedException();
+               protected bool ProcessEnterKey (Keys keyData)
+               {
+                       if (!IsCurrentCellInEditMode)
+                               return false;
+                               
+                       CommitEdit (DataGridViewDataErrorContexts.Commit);
+                       
+                       // Move one cell down
+                       if ((keyData & Keys.Control) == 0) {
+                               int current_row = CurrentCellAddress.Y;
+                               
+                               if (current_row < Rows.Count - 1)
+                                       MoveCurrentCell (CurrentCellAddress.X, current_row + 1, true, (keyData & Keys.Control) == Keys.Control, (keyData & Keys.Shift) == Keys.Shift, true);
+                       }
+                       
+                       return true;
                }
 
-               protected bool ProcessEscapeKey (Keys keyData) {
-                       throw new NotImplementedException();
+               protected bool ProcessEscapeKey (Keys keyData)
+               {
+                       if (!IsCurrentCellInEditMode)
+                               return false;
+
+                       CancelEdit ();
+                       return true;
                }
 
-               protected bool ProcessF2Key (Keys keyData) {
-                       throw new NotImplementedException();
+               protected bool ProcessF2Key (Keys keyData)
+               {
+                       if (editMode == DataGridViewEditMode.EditOnF2 || editMode == DataGridViewEditMode.EditOnKeystrokeOrF2) {
+                               BeginEdit (true);
+                               return true;
+                       }
+                       
+                       return false;
                }
 
-               protected bool ProcessHomeKey (Keys keyData) {
-                       throw new NotImplementedException();
+               protected bool ProcessHomeKey (Keys keyData)
+               {
+                       int disp_index = ColumnIndexToDisplayIndex (currentCellAddress.X);
+
+                       // Move to the first cell in the control
+                       if ((keyData & Keys.Control) == Keys.Control) {
+                               MoveCurrentCell (ColumnDisplayIndexToIndex (0), 0, true, (keyData & Keys.Control) == Keys.Control, (keyData & Keys.Shift) == Keys.Shift, true);
+                               return true;
+                       }
+                       
+                       // Move to the first cell in the row
+                       if (disp_index > 0) {
+                               MoveCurrentCell (ColumnDisplayIndexToIndex (0), currentCellAddress.Y, true, (keyData & Keys.Control) == Keys.Control, (keyData & Keys.Shift) == Keys.Shift, true);
+                               return true;
+                       }
+
+                       return false;
                }
 
-               protected bool ProcessInsertKey (Keys keyData) {
-                       throw new NotImplementedException();
+               [MonoTODO ("What does insert do?")]
+               protected bool ProcessInsertKey (Keys keyData)
+               {
+                       return false;
                }
 
-               protected override bool ProcessKeyEventArgs (ref Message m) {
-                       return base.ProcessKeyEventArgs(ref m);
-                       //throw new NotImplementedException();
+               protected override bool ProcessKeyEventArgs (ref Message m)
+               {
+                       DataGridViewCell cell = CurrentCell;
+                       
+                       if (cell != null)
+                               if (cell.KeyEntersEditMode (new KeyEventArgs ((Keys)m.WParam.ToInt32 ())))
+                                       BeginEdit (true);
+
+                       return base.ProcessKeyEventArgs (ref m);
                }
 
-               protected override bool ProcessKeyPreview (ref Message m) {
-                       return base.ProcessKeyPreview(ref m);
-                       //throw new NotImplementedException();
+               protected override bool ProcessKeyPreview (ref Message m)
+               {
+                       if ((Msg)m.Msg == Msg.WM_KEYDOWN && (IsCurrentCellInEditMode || m.HWnd == horizontalScrollBar.Handle || m.HWnd == verticalScrollBar.Handle)) {
+                               KeyEventArgs e = new KeyEventArgs ((Keys)m.WParam.ToInt32 ());
+                       
+                               IDataGridViewEditingControl ctrl = (IDataGridViewEditingControl)EditingControlInternal;
+                               
+                               if (ctrl != null)
+                                       if (ctrl.EditingControlWantsInputKey (e.KeyData, false))
+                                               return false;
+
+                               switch (e.KeyData) {
+                                       case Keys.Escape:
+                                       case Keys.Down:
+                                       case Keys.Up:
+                                       case Keys.Left:
+                                       case Keys.Right:
+                                       case Keys.Tab:
+                                       case Keys.Prior:
+                                       case Keys.Next:
+                                               return ProcessDataGridViewKey (e);
+                               }
+                       }
+                       
+                       return base.ProcessKeyPreview (ref m);
                }
 
-               protected bool ProcessLeftKey (Keys keyData) {
-                       throw new NotImplementedException();
+               protected bool ProcessLeftKey (Keys keyData)
+               {
+                       int disp_index = ColumnIndexToDisplayIndex (currentCellAddress.X);
+
+                       if (disp_index > 0) {
+                               EndEdit ();
+                               
+                               // Move to the first cell in the row
+                               if ((keyData & Keys.Control) == Keys.Control)
+                                       MoveCurrentCell (ColumnDisplayIndexToIndex (0), currentCellAddress.Y, true, (keyData & Keys.Control) == Keys.Control, (keyData & Keys.Shift) == Keys.Shift, true);
+                               // Move one cell to the left
+                               else
+                                       MoveCurrentCell (ColumnDisplayIndexToIndex (disp_index - 1), currentCellAddress.Y, true, (keyData & Keys.Control) == Keys.Control, (keyData & Keys.Shift) == Keys.Shift, true);
+
+                               return true;
+                       }
+
+                       return false;
                }
 
-               protected bool ProcessNextKey (Keys keyData) {
-                       // PAGE DOWN
-                       throw new NotImplementedException();
+               // Page Down
+               protected bool ProcessNextKey (Keys keyData)
+               {
+                       int current_row = CurrentCellAddress.Y;
+
+                       if (current_row < Rows.Count - 1) {
+                               EndEdit ();
+
+                               // Move one "page" of cells down
+                               int new_row = Math.Min (Rows.Count - 1, current_row + DisplayedRowCount (false));
+
+                               MoveCurrentCell (CurrentCellAddress.X, new_row, true, (keyData & Keys.Control) == Keys.Control, (keyData & Keys.Shift) == Keys.Shift, true);
+
+                               return true;
+                       }
+
+                       return false;
                }
 
-               protected bool ProcessPriorKey (Keys keyData) {
-                       // PAGE UP
-                       throw new NotImplementedException();
+               // Page Up
+               protected bool ProcessPriorKey (Keys keyData)
+               {
+                       int current_row = CurrentCellAddress.Y;
+
+                       if (current_row > 0) {
+                               EndEdit ();
+
+                               // Move one "page" of cells up
+                               int new_row = Math.Max (0, current_row - DisplayedRowCount (false));
+
+                               MoveCurrentCell (CurrentCellAddress.X, new_row, true, (keyData & Keys.Control) == Keys.Control, (keyData & Keys.Shift) == Keys.Shift, true);
+
+                               return true;
+                       }
+
+                       return false;
                }
 
-               protected bool ProcessRightKey (Keys keyData) {
-                       throw new NotImplementedException();
+               protected bool ProcessRightKey (Keys keyData)
+               {
+                       int disp_index = ColumnIndexToDisplayIndex (currentCellAddress.X);
+
+                       if (disp_index < Columns.Count - 1) {
+                               EndEdit ();
+                               
+                               // Move to the last cell in the row
+                               if ((keyData & Keys.Control) == Keys.Control)
+                                       MoveCurrentCell (ColumnDisplayIndexToIndex (Columns.Count - 1), currentCellAddress.Y, true, (keyData & Keys.Control) == Keys.Control, (keyData & Keys.Shift) == Keys.Shift, true);
+                               // Move one cell to the right
+                               else
+                                       MoveCurrentCell (ColumnDisplayIndexToIndex (disp_index + 1), currentCellAddress.Y, true, (keyData & Keys.Control) == Keys.Control, (keyData & Keys.Shift) == Keys.Shift, true);
+                               
+                               return true;
+                       }
+
+                       return false;
                }
 
-               protected bool ProcessSpaceKey (Keys keyData) {
-                       throw new NotImplementedException();
+               protected bool ProcessSpaceKey (Keys keyData)
+               {
+                       if ((keyData & Keys.Shift) == Keys.Shift) {
+                               if (selectionMode == DataGridViewSelectionMode.RowHeaderSelect) {
+                                       SetSelectedRowCore (CurrentCellAddress.Y, true);
+                                       InvalidateRow (CurrentCellAddress.Y);
+                                       return true;
+                               }
+                               if (selectionMode == DataGridViewSelectionMode.ColumnHeaderSelect) {
+                                       SetSelectedColumnCore (CurrentCellAddress.X, true);
+                                       InvalidateColumn (CurrentCellAddress.X);
+                                       return true;
+                               }
+                       }
+                       
+                       if (CurrentCell is DataGridViewButtonCell || CurrentCell is DataGridViewLinkCell || CurrentCell is DataGridViewCheckBoxCell) {
+                               DataGridViewCellEventArgs e = new DataGridViewCellEventArgs (CurrentCell.ColumnIndex, CurrentCell.RowIndex);
+                               
+                               OnCellClick (e);
+                               OnCellContentClick (e);
+                               
+                               if (CurrentCell is DataGridViewButtonCell)
+                                       (CurrentCell as DataGridViewButtonCell).OnClickInternal (e);
+                               if (CurrentCell is DataGridViewCheckBoxCell)
+                                       (CurrentCell as DataGridViewCheckBoxCell).OnClickInternal (e);
+                                       
+                               return true;
+                       }
+                       
+                       return false;
                }
 
-               protected bool ProcessTabKey (Keys keyData) {
-                       throw new NotImplementedException();
+               protected bool ProcessTabKey (Keys keyData)
+               {
+                       EndEdit ();
+                       
+                       Form f = FindForm ();
+                       
+                       if (f != null)
+                               f.ActivateFocusCues ();
+                       
+                       int disp_index = ColumnIndexToDisplayIndex (currentCellAddress.X);
+
+                       // Tab goes forward
+                       // Shift-tab goes backwards
+                       if ((keyData & Keys.Shift) == Keys.Shift) {
+                               if (disp_index > 0) {
+                                       // Move one cell to the left
+                                       MoveCurrentCell (ColumnDisplayIndexToIndex (disp_index - 1), currentCellAddress.Y, true, (keyData & Keys.Control) == Keys.Control, false, true);
+                                       return true;
+                               } else if (currentCellAddress.Y > 0) {
+                                       // Move to the last cell in the previous row
+                                       MoveCurrentCell (ColumnDisplayIndexToIndex (Columns.Count - 1), currentCellAddress.Y - 1, true, false, false, true);
+                                       return true;
+                               }
+                       
+                       } else {
+                               if (disp_index < Columns.Count - 1) {
+                                       // Move one cell to the right
+                                       MoveCurrentCell (ColumnDisplayIndexToIndex (disp_index + 1), currentCellAddress.Y, true, (keyData & Keys.Control) == Keys.Control, false, true);
+
+                                       return true;
+                               } else if (currentCellAddress.Y < Rows.Count - 1) {
+                                       // Move to the first cell in the next row
+                                       MoveCurrentCell (ColumnDisplayIndexToIndex (0), currentCellAddress.Y + 1, true, false, false, true);
+                                       return true;
+                               }
+
+                       
+                       }
+                       
+                       return false;
                }
 
-               protected bool ProcessUpKey (Keys keyData) {
-                       throw new NotImplementedException();
+               protected bool ProcessUpKey (Keys keyData)
+               {
+                       int current_row = CurrentCellAddress.Y;
+
+                       if (current_row > 0) {
+                               EndEdit ();
+
+                               // Move to the first cell in the column
+                               if ((keyData & Keys.Control) == Keys.Control)
+                                       MoveCurrentCell (CurrentCellAddress.X, 0, true, (keyData & Keys.Control) == Keys.Control, (keyData & Keys.Shift) == Keys.Shift, true);
+                               // Move one cell up
+                               else
+                                       MoveCurrentCell (CurrentCellAddress.X, current_row - 1, true, (keyData & Keys.Control) == Keys.Control, (keyData & Keys.Shift) == Keys.Shift, true);
+
+                               return true;
+                       }
+
+                       return false;
                }
 
-               protected bool ProcessZeroKey (Keys keyData) {
-                       throw new NotImplementedException();
+               protected bool ProcessZeroKey (Keys keyData)
+               {
+                       if ((keyData & Keys.Control) == Keys.Control && CurrentCell.EditType != null) {
+                               CurrentCell.Value = DBNull.Value;
+                               InvalidateCell (CurrentCell);
+                               return true;
+                       }
+                       
+                       return false;
                }
 
                protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified) {
                        base.SetBoundsCore(x, y, width, height, specified);
                }
 
-               protected virtual bool SetCurrentCellAddressCore (int columnIndex, int rowIndex, bool setAnchorCellAddress, bool validateCurrentCell, bool throughMouseClick) {
-                       throw new NotImplementedException();
+               [MonoTODO ("Does not use validateCurrentCell or throughMouseClick")]
+               protected virtual bool SetCurrentCellAddressCore (int columnIndex, int rowIndex, bool setAnchorCellAddress, bool validateCurrentCell, bool throughMouseClick)
+               {
+                       if ((columnIndex < 0 || columnIndex > Columns.Count - 1) && rowIndex != -1)
+                               throw new ArgumentOutOfRangeException ("columnIndex");
+                       if ((rowIndex < 0 || rowIndex > Rows.Count - 1) && columnIndex != -1)
+                               throw new ArgumentOutOfRangeException ("rowIndex");
+                       
+                       DataGridViewCell cell;
+                       
+                       if (columnIndex == -1 && rowIndex == -1)
+                               cell = null;
+                       else
+                               cell = Rows.SharedRow (rowIndex).Cells[columnIndex];
+                       
+                       if (cell != null && !cell.Visible)
+                               throw new InvalidOperationException ("cell is not visible");
+                               
+                       if (setAnchorCellAddress)
+                               anchor_cell = new Point (columnIndex, rowIndex);
+
+                       currentCellAddress = new Point (columnIndex, rowIndex);
+                       CurrentCell = cell;
+                       
+                       OnCurrentCellChanged (EventArgs.Empty);
+                       
+                       return true;
                }
 
                protected virtual void SetSelectedCellCore (int columnIndex, int rowIndex, bool selected) {
                        rows [rowIndex].Cells [columnIndex].Selected = selected;
+                       
+                       OnSelectionChanged (EventArgs.Empty);
                }
 
                internal void SetSelectedColumnCoreInternal (int columnIndex, bool selected) {
@@ -4249,69 +5189,94 @@ namespace System.Windows.Forms {
                        }
                }
 
-               protected override void WndProc (ref Message m) {
-                       base.WndProc(ref m);
-               }
-
-               void IDropTarget.OnDragDrop (DragEventArgs e)
+               protected override void WndProc (ref Message m)
                {
-                       throw new NotImplementedException ();
+                       base.WndProc (ref m);
                }
 
-               void IDropTarget.OnDragEnter (DragEventArgs e)
+               internal void InternalOnCellClick (DataGridViewCellEventArgs e)
                {
-                       throw new NotImplementedException ();
+                       OnCellClick (e);
                }
 
-               void IDropTarget.OnDragLeave (EventArgs e)
+               internal void InternalOnCellContentClick (DataGridViewCellEventArgs e)
                {
-                       throw new NotImplementedException ();
+                       OnCellContentClick (e);
                }
 
-               void IDropTarget.OnDragOver (DragEventArgs e)
+               internal void InternalOnCellContentDoubleClick (DataGridViewCellEventArgs e)
                {
-                       throw new NotImplementedException ();
-               }
-
-               internal void InternalOnCellClick (DataGridViewCellEventArgs e) {
-                       OnCellClick(e);
-               }
-
-               internal void InternalOnCellContentClick (DataGridViewCellEventArgs e) {
-                       OnCellContentClick(e);
-               }
-
-               internal void InternalOnCellContentDoubleClick (DataGridViewCellEventArgs e) {
-                       OnCellContentDoubleClick(e);
+                       OnCellContentDoubleClick (e);
                }
 
-               internal void InternalOnCellValueChanged (DataGridViewCellEventArgs e) {
-                       OnCellValueChanged(e);
+               internal void InternalOnCellValueChanged (DataGridViewCellEventArgs e)
+               {
+                       OnCellValueChanged (e);
                        
-                       if (editing_row != null && e.RowIndex == editing_row.Index) {
+                       if (editing_row != null && e.RowIndex == editing_row.Index)
                                PrepareEditingRow (true, false);
-                       }
                }
 
-               internal void InternalOnDataError (DataGridViewDataErrorEventArgs e) {
+               internal void InternalOnDataError (DataGridViewDataErrorEventArgs e)
+               {
                        /////////////// false? ////////////
-                       OnDataError(false, e);
+                       OnDataError (false, e);
                }
 
-               internal void InternalOnMouseWheel (MouseEventArgs e) {
-                       OnMouseWheel(e);
+               internal void InternalOnMouseWheel (MouseEventArgs e)
+               {
+                       OnMouseWheel (e);
                }
 
-               internal void OnHScrollBarScroll (object sender, ScrollEventArgs e) {
+               internal void OnHScrollBarScroll (object sender, ScrollEventArgs e)
+               {
                        horizontalScrollingOffset = e.NewValue;
-                       Invalidate();
-                       OnScroll(e);
+                       int left = 0;
+
+                       for (int index = 0; index < Columns.Count; index++) {
+                               DataGridViewColumn col = Columns[index];
+
+                               if (e.NewValue < left + col.Width) {
+                                       if (first_col_index != index) {
+                                               first_col_index = index;
+                                               Invalidate ();
+                                               OnScroll (e);
+                                       }
+
+                                       return;
+                               }
+
+                               left += col.Width;
+                       }
                }
 
-               internal void OnVScrollBarScroll (object sender, ScrollEventArgs e) {
+               internal void OnVScrollBarScroll (object sender, ScrollEventArgs e)
+               {
                        verticalScrollingOffset = e.NewValue;
-                       Invalidate();
-                       OnScroll(e);
+                       int top = 0;
+                       
+                       for (int index = 0; index < Rows.Count; index++) {
+                               DataGridViewRow row = Rows[index];
+                               
+                               if (e.NewValue <= top + row.Height) {
+                                       if (first_row_index != index) {
+                                               first_row_index = index;
+                                               Invalidate ();
+                                               OnScroll (e);
+                                       }
+                                       
+                                       return;
+                               }
+                               
+                               top += row.Height;
+                       }
+                       
+                       if (Rows.Count == 0)
+                               return;
+                               
+                       first_row_index = Rows.Count - DisplayedRowCount (false) + 1;
+                       Invalidate ();
+                       OnScroll (e);
                }
 
                internal void RaiseCellStyleChanged (DataGridViewCellEventArgs e) {
@@ -4473,6 +5438,32 @@ namespace System.Windows.Forms {
                        return result;
                }
 
+               Rectangle GetHeaderCellBounds (DataGridViewHeaderCell cell)
+               {
+                       Rectangle bounds = new Rectangle (ClientRectangle.Location, cell.Size);
+                       if (cell is DataGridViewColumnHeaderCell) {
+                               if (RowHeadersVisible)
+                                       bounds.X += RowHeadersWidth;
+                               List<DataGridViewColumn> sortedColumns = columns.ColumnDisplayIndexSortedArrayList;
+                               for (int index = first_col_index; index < sortedColumns.Count; index++) {
+                                       DataGridViewColumn column = sortedColumns [index];
+                                       if (column.Index == cell.ColumnIndex)
+                                               break;
+                                       bounds.X += column.Width;
+                               }
+                       } else {
+                               if (ColumnHeadersVisible)
+                                       bounds.Y += ColumnHeadersHeight;
+                               for (int index = first_row_index; index < Rows.Count; index++) {
+                                       DataGridViewRow row = GetRowInternal (index);
+                                       if (row.HeaderCell == cell)
+                                               break;
+                                       bounds.Y += row.Height;
+                               }
+                       }
+                       return bounds;
+               }
+
                private void PrepareEditingRow (bool cell_changed, bool column_changed)
                {
                        bool show = false;
@@ -4507,39 +5498,166 @@ namespace System.Windows.Forms {
                }
 
                private void BindIList (IList list) {
-                       if (list is DataView) {
-                               DataView dataView = (DataView) list;
-                               DataTable table = dataView.Table;
-                               DataGridViewCell template = new DataGridViewTextBoxCell();
-                               foreach (DataColumn dataColumn in table.Columns) {
-                                       DataGridViewColumn col = new DataGridViewColumn(template);
-                                       col.Name = dataColumn.ColumnName;
-                                       col.ValueType = dataColumn.DataType;
-                                       columns.Add(col);
+                       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);
+                                       }
                                }
-                               dataView.ListChanged += OnListChanged;
-                       }
-                       else if (list.Count > 0) {
-                               DataGridViewCell template = new DataGridViewTextBoxCell();
-                               foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(list[0])) {
-                                       DataGridViewColumn col = new DataGridViewColumn(template);
-                                       col.Name = property.DisplayName;
-                                       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]);
                                }
-                       }
-                       foreach (object element in list) {
-                               DataGridViewRow row = new DataGridViewRow();
-                               rows.InternalAdd(row);
-                               PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(element);
-                               foreach (PropertyDescriptor property in properties) {
-                                       DataGridViewTextBoxCell cell = new DataGridViewTextBoxCell();
-                                       cell.Value = property.GetValue(element);
-                                       cell.ValueType = property.PropertyType;
-                                       row.Cells.Add(cell);
+                               // Its a normal array/collection type thing
+                               else if (list.GetType ().IsArray) {
+                                       GenerateColumnsFromType (list.GetType ().GetElementType ());
                                }
                        }
+               
+                       // Subscribe to the dataset's change notification
+                       if (list is DataView) {
+                               (list as DataView).ListChanged += OnListChanged;
+                               (list as DataView).Table.ColumnChanged += OnTableColumnChanged;
+                       }
+                       
+                       // Add the rows
+                       foreach (object element in list)
+                               AddBoundRow (element);
+               }
+
+               private void AddBoundRow (object element)
+               {
+                       // Don't add rows if there are no columns
+                       if (ColumnCount == 0)
+                               return;
+                               
+                       DataGridViewRow row = (DataGridViewRow)RowTemplate.Clone ();
+                       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;
+                       }
+               }
+               
+               private void GenerateColumnsFromType (Type type)
+               {
+                       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);
+                       }
+               }
+               
+               private DataGridViewColumn CreateColumnByType (Type type)
+               {
+                       if (type == typeof (bool))
+                               return new DataGridViewCheckBoxColumn ();
+                               
+                       return new DataGridViewTextBoxColumn ();
+               }
+               
+               private void ClearBinding ()
+               {
+                       columns.ClearAutoGeneratedColumns ();
+                       rows.Clear ();
+                       PrepareEditingRow (false, true);
+
+                       if (dataSource != null) {
+                               if (dataSource is DataSet) {
+                                       (dataSource as DataSet).Tables.CollectionChanged -= OnDataSetTableChanged;
+                                       
+                                       DataTable dt = (dataSource as DataSet).Tables[dataMember];
+                                       
+                                       if (dt != null) {
+                                               DataView dv = dt.DefaultView;
+                                       
+                                               if (dv != null) {
+                                                       (dv as DataView).Table.ColumnChanged -= OnTableColumnChanged;
+                                                       (dv as DataView).ListChanged -= OnListChanged;
+                                               }
+                                       }
+                               } else if (dataSource is DataView) {
+                                       (dataSource as DataView).ListChanged -= OnListChanged;
+                                       (dataSource as DataView).Table.ColumnChanged -= OnTableColumnChanged;
+                               } else if (dataSource is DataTable)
+                                       ((dataSource as IListSource).GetList () as DataView).ListChanged -= OnListChanged;
+                       }
                }
+               
+               private void DoBinding ()
+               {
+                       /* The System.Windows.Forms.DataGridView class supports the standard Windows Forms data-binding model. This means the data source can be of any type that implements:
+                        - the System.Collections.IList interface, including one-dimensional arrays.
+                        - the System.ComponentModel.IListSource interface, such as the System.Data.DataTable and System.Data.DataSet classes.
+                        - the System.ComponentModel.IBindingList interface, such as the System.ComponentModel.Collections.BindingList<> class.
+                        - the System.ComponentModel.IBindingListView interface, such as the System.Windows.Forms.BindingSource class.
+                       */
+                       
+                       if (dataSource != null) {
+                               object value = dataSource;
+                               
+                               // DataBinding
+                               if (value is DataSet && string.IsNullOrEmpty (dataMember)) {
+                                       Invalidate ();
+                                       return;
+                               }
+                               if (value is DataSet) {
+                                       (value as DataSet).Tables.CollectionChanged += OnDataSetTableChanged;
+                                       value = (value as DataSet).Tables[dataMember];
+                               }
+                               if (value is BindingSource)
+                                       value = (value as BindingSource).List;
+                                       
+                               if (value is IList)
+                                       BindIList (value as IList);
+                               else if (value is IListSource)
+                                       BindIListSource (value as IListSource);
+                               else if (value is IBindingList)
+                                       BindIBindingList (value as IBindingList);
+                               else if (value is IBindingListView)
+                                       BindIBindingListView (value as IBindingListView);
+
+                               OnDataBindingComplete (new DataGridViewBindingCompleteEventArgs (ListChangedType.Reset));
+                       }
 
+                       Invalidate ();
+               }
+               
                private void BindIListSource (IListSource list) {
                        BindIList(list.GetList());
                }
@@ -4552,24 +5670,212 @@ namespace System.Windows.Forms {
                        BindIList(list);
                }
 
-               private void OnListChanged (object sender, ListChangedEventArgs args) {
-                       if (args.OldIndex >= 0) {
+               private void MoveCurrentCell (int x, int y, bool select, bool isControl, bool isShift, bool scroll)
+               {
+                       bool full_row_selected = Rows.SharedRow(CurrentCellAddress.Y).Selected;
+                       bool full_col_selected = Columns[CurrentCellAddress.X].Selected;
+                       
+                       // Move Selection
+                       DataGridViewSelectionMode mode = selectionMode;
+                       
+                       // If we are row header select and we clicked a row header, use full row
+                       if (mode == DataGridViewSelectionMode.RowHeaderSelect && (x == -1 || (full_row_selected && CurrentCellAddress.X == x)))
+                               mode = DataGridViewSelectionMode.FullRowSelect;
+                       else if (mode == DataGridViewSelectionMode.RowHeaderSelect)
+                               mode = DataGridViewSelectionMode.CellSelect;
+                               
+                       // If we are col header select and we clicked a col header, use full col
+                       if (mode == DataGridViewSelectionMode.ColumnHeaderSelect && (y == -1 || (full_col_selected && CurrentCellAddress.Y == y)))
+                               mode = DataGridViewSelectionMode.FullColumnSelect;
+                       else if (mode == DataGridViewSelectionMode.ColumnHeaderSelect)
+                               mode = DataGridViewSelectionMode.CellSelect;
+                       
+                       // Move CurrentCell
+                       SetCurrentCellAddressCore (x, y, true, false, false);
+                       
+                       // If the current cell isn't visible, scroll to it
+                       if (scroll) {
+                               int disp_x = ColumnIndexToDisplayIndex (x);
+
+                               if (disp_x < first_col_index) {
+                                       int delta_x = 0;
+
+                                       if (disp_x == 0)
+                                               delta_x = horizontalScrollBar.Value;
+                                       else
+                                               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));
+                               }
+
+                               int disp_y = y;
+
+                               if (disp_y < first_row_index) {
+                                       int delta_y = 0;
+
+                                       if (disp_y == 0)
+                                               delta_y = verticalScrollBar.Value;
+                                       else
+                                               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 + DisplayedRowCount (false) - 2) {
+                                       int delta_y = 0;
+                                       
+                                       if (disp_y == Rows.Count - 1)
+                                               delta_y = verticalScrollBar.Maximum - verticalScrollBar.Value;
+                                       else
+                                               for (int i = first_row_index + DisplayedRowCount (false) - 2; i < disp_y; i++)
+                                                       delta_y += GetRowInternal (i).Height;
+
+                                       verticalScrollBar.SafeValueSet (verticalScrollBar.Value + delta_y);
+                                       OnVScrollBarScroll (this, new ScrollEventArgs (ScrollEventType.ThumbPosition, verticalScrollBar.Value));                                
+                               }
                        }
-                       if (args.NewIndex >= 0) {
-                               object element = (sender as DataView)[args.NewIndex];
-                               DataGridViewRow row = new DataGridViewRow();
-                               rows.InternalAdd(row);
-                               PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(element);
-                               foreach (PropertyDescriptor property in properties) {
-                                       DataGridViewTextBoxCell cell = new DataGridViewTextBoxCell();
-                                       cell.Value = property.GetValue(element);
-                                       cell.ValueType = property.PropertyType;
-                                       row.Cells.Add(cell);
+                       
+                       if (!select)
+                               return;
+                       
+                       // Clear old selection unless multi-selecting
+                       if (!isShift)
+                               ClearSelection ();
+                       
+                       switch (mode) {
+                               case DataGridViewSelectionMode.CellSelect:
+                                       SetSelectedCellCore (x, y, true);
+                                       break;
+                               case DataGridViewSelectionMode.FullRowSelect:
+                                       SetSelectedRowCore (y, true);
+                                       break;
+                               case DataGridViewSelectionMode.FullColumnSelect:
+                                       SetSelectedColumnCore (x, true);
+                                       break;
+                       }
+                       
+                       Invalidate ();
+               }
+               
+               private int ColumnIndexToDisplayIndex (int index)
+               {
+                       return Columns[index].DisplayIndex;
+               }
+               
+               private int ColumnDisplayIndexToIndex (int index)
+               {
+                       return Columns.ColumnDisplayIndexSortedArrayList[index].Index;
+               }
+               
+               private void OnListChanged (object sender, ListChangedEventArgs args)
+               {
+                       switch (args.ListChangedType) {
+                               case ListChangedType.ItemAdded:
+                                       AddBoundRow ((sender as DataView)[args.NewIndex]);
+                                       break;
+                               case ListChangedType.ItemDeleted:
+                                       Rows.RemoveAt (args.NewIndex);
+                                       break;
+                       }
+                       
+                       Invalidate ();
+               }
+               
+               private void OnTableColumnChanged (object sender, DataColumnChangeEventArgs e)
+               {
+                       ClearBinding ();
+                       DoBinding ();
+               }
+
+               private void OnDataSetTableChanged (object sender, CollectionChangeEventArgs e)
+               {
+                       ClearBinding ();
+                       DoBinding ();
+               }
+
+               #region Stuff for ToolTips
+               private void MouseEnteredErrorIcon (DataGridViewCell item)
+               {
+                       tooltip_currently_showing = item;
+                       ToolTipTimer.Start ();
+               }
+
+               private void MouseLeftErrorIcon (DataGridViewCell item)
+               {
+                       ToolTipTimer.Stop ();
+                       ToolTipWindow.Hide (this);
+                       tooltip_currently_showing = null;
+               }
+
+               private Timer ToolTipTimer {
+                       get {
+                               if (tooltip_timer == null) {
+                                       tooltip_timer = new Timer ();
+                                       tooltip_timer.Enabled = false;
+                                       tooltip_timer.Interval = 500;
+                                       tooltip_timer.Tick += new EventHandler (ToolTipTimer_Tick);
                                }
-                               Invalidate();
+
+                               return tooltip_timer;
+                       }
+               }
+
+               private ToolTip ToolTipWindow {
+                       get {
+                               if (tooltip_window == null)
+                                       tooltip_window = new ToolTip ();
+
+                               return tooltip_window;
                        }
                }
 
+               private void ToolTipTimer_Tick (object o, EventArgs args)
+               {
+                       string tooltip = tooltip_currently_showing.ErrorText;
+
+                       if (!string.IsNullOrEmpty (tooltip))
+                               ToolTipWindow.Present (this, tooltip);
+
+                       ToolTipTimer.Stop ();
+               }
+               #endregion
+
+               private class ColumnSorter : IComparer
+               {
+                       int column;
+                       int direction = 1;
+
+                       public ColumnSorter (DataGridViewColumn column, ListSortDirection direction)
+                       {
+                               this.column = column.Index;
+
+                               if (direction == ListSortDirection.Descending)
+                                       this.direction = -1;
+                       }
+
+                       #region IComparer Members
+                       public int Compare (object x, object y)
+                       {
+                               DataGridViewRow row1 = (DataGridViewRow)x;
+                               DataGridViewRow row2 = (DataGridViewRow)y;
+
+                               object val1 = row1.Cells[column].FormattedValue;
+                               object val2 = row2.Cells[column].FormattedValue;
+
+                               if (val1 == null && val2 == null)
+                                       return 0;
+                               if (val1 == null)
+                                       return direction;
+                               if (val2 == null)
+                                       return -1 * direction;
+
+                               return string.Compare (val1.ToString (), val2.ToString ()) * direction;
+                       }
+                       #endregion
+               }
+
                public sealed class HitTestInfo {
 
                        public static readonly HitTestInfo Nowhere = new HitTestInfo(-1, -1, -1, -1, DataGridViewHitTestType.None);
@@ -4623,7 +5929,7 @@ namespace System.Windows.Forms {
                        }
 
                        public override string ToString () {
-                               return GetType().Name;
+                               return string.Format ("Type:{0}, Column:{1}, Row:{2}", type, columnIndex, rowIndex);
                        }
 
                }
@@ -4784,7 +6090,6 @@ namespace System.Windows.Forms {
                        #endregion
                }
        }
-
 }
 
 #endif