//
// Author:
// Pedro MartÃnez Juliá <pedromj@gmail.com>
+// Ivan N. Zlatev <contact@i-nz.net>
//
#if NET_2_0
private HScrollBar horizontalScrollBar;
private VScrollBar verticalScrollBar;
private Control editingControl;
- private bool new_row_commited = true;
+ private bool is_autogenerating_columns = false;
+ private bool is_binding = false;
+ private bool new_row_editing = false;
// These are used to implement selection behaviour with SHIFT pressed.
private int selected_row = -1;
private DataGridViewSelectedColumnCollection selected_columns;
private DataGridViewRow editing_row;
- private int gridWidth;
- private int gridHeight;
-
DataGridViewHeaderCell pressed_header_cell;
DataGridViewHeaderCell entered_header_cell;
columnHeadersVisible = true;
columns = CreateColumnsInstance();
columns.CollectionChanged += OnColumnCollectionChanged;
+ currentCellAddress = new Point (-1, -1);
dataMember = String.Empty;
defaultCellStyle = new DataGridViewCellStyle();
defaultCellStyle.BackColor = SystemColors.Window;
selectionMode = DataGridViewSelectionMode.RowHeaderSelect;
showCellErrors = true;
showEditingIcon = true;
+ scrollBars = ScrollBars.Both;
userSetCursor = Cursor.Current;
virtualMode = false;
[DefaultValue (true)]
public bool AllowUserToAddRows {
- get { return allowUserToAddRows; }
+ get {
+ if (allowUserToAddRows && DataManager != null)
+ return DataManager.AllowNew;
+ return allowUserToAddRows;
+ }
set {
if (allowUserToAddRows != value) {
allowUserToAddRows = value;
+ if (!value) {
+ if (new_row_editing)
+ CancelEdit ();
+ RemoveEditingRow ();
+ } else {
+ PrepareEditingRow (false, false);
+ }
OnAllowUserToAddRowsChanged(EventArgs.Empty);
- PrepareEditingRow (false, false);
Invalidate ();
}
}
[DefaultValue (true)]
public bool AllowUserToDeleteRows {
- get { return allowUserToDeleteRows; }
+ get {
+ if (allowUserToDeleteRows && DataManager != null)
+ return DataManager.AllowRemove;
+ return allowUserToDeleteRows;
+ }
set {
if (allowUserToDeleteRows != value) {
allowUserToDeleteRows = value;
throw new InvalidOperationException("Cant change column count if DataSource is set.");
}
if (value < columns.Count) {
- for (int i = value; i < columns.Count; i++) {
+ for (int i = columns.Count -1; i >= value; i--) {
columns.RemoveAt(i);
}
}
else if (value > columns.Count) {
- for (int i = 0; i < value; i++) {
+ for (int i = columns.Count; i < value; i++) {
DataGridViewTextBoxColumn col = new DataGridViewTextBoxColumn ();
columns.Add(col);
}
/// to the data cache, or the new cell is in a hidden
/// row.
/////////////////////////////////////////////////////
- if (value.DataGridView != this) {
+ if (value == null)
+ MoveCurrentCell (-1, -1, true, false, false, true);
+ else if (value.DataGridView != this)
throw new ArgumentException("The cell is not in this DataGridView.");
- }
- currentCell = value;
- currentRow = currentCell.OwningRow;
+ else
+ MoveCurrentCell (value.OwningColumn.Index, value.OwningRow.Index, true, false, false, true);
}
}
[Browsable (false)]
public DataGridViewRow CurrentRow {
- get { return currentRow; }
+ get {
+ if (currentCell != null)
+ return currentCell.OwningRow;
+ return null;
+ }
}
[DefaultValue ("")]
get { return dataMember; }
set {
if (dataMember != value) {
- ClearBinding ();
-
dataMember = value;
+ if (BindingContext != null)
+ ReBind ();
OnDataMemberChanged(EventArgs.Empty);
-
- DoBinding ();
}
}
}
throw new NotSupportedException ("Type cannot be bound.");
ClearBinding ();
-
dataSource = value;
+ if (BindingContext != null)
+ ReBind ();
OnDataSourceChanged (EventArgs.Empty);
-
- DoBinding ();
+ }
+ }
+
+ internal CurrencyManager DataManager {
+ get {
+ if (DataSource != null && BindingContext != null) {
+ string dataMember = DataMember;
+ if (dataMember == null)
+ dataMember = String.Empty;
+ return (CurrencyManager) this.BindingContext[DataSource, dataMember];
+ }
+ return null;
}
}
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
public int NewRowIndex {
get {
- if (!allowUserToAddRows) {
+ if (!AllowUserToAddRows || ColumnCount == 0) {
return -1;
}
return rows.Count - 1;
if (value < 0) {
throw new ArgumentException("RowCount must be >= 0.");
}
- if (value < 1 && allowUserToAddRows) {
+ if (value < 1 && AllowUserToAddRows) {
throw new ArgumentException("RowCount must be >= 1 if AllowUserToAddRows is true.");
}
if (dataSource != null) {
throw new InvalidOperationException("Cant change row count if DataSource is set.");
}
+
if (value < rows.Count) {
- for (int i = value; i < rows.Count; i++) {
+ int removeRangeEndIndex = rows.Count - 1;
+ if (AllowUserToAddRows)
+ removeRangeEndIndex--; // do not remove editing row
+
+ int removeRangeStartIndex = value - 1;
+ if (AllowUserToAddRows)
+ removeRangeStartIndex--; // remove an extra row before/instead of the editing row
+
+ for (int i = removeRangeEndIndex; i > removeRangeStartIndex; i--)
rows.RemoveAt(i);
- }
- }
- else if (value > rows.Count) {
+ } else if (value > rows.Count) {
// If we need to add rows and don't have any columns,
// we create one column
if (ColumnCount == 0)
for (int i = rows.Count; i < value; i++) {
DataGridViewRow row = (DataGridViewRow) RowTemplateFull;
rows.AddInternal (row, false);
-
- foreach (DataGridViewColumn col in columns)
- row.Cells.Add (col.CellTemplate.Clone () as DataGridViewCell);
}
}
}
}
set {
rowTemplate = value;
- rowTemplate.SetDataGridView(this);
}
}
/// or canceled.
///////////////////////////////////////////////////////////
scrollBars = value;
+ PerformLayout ();
+ Invalidate ();
}
}
return topLeftHeaderCell;
}
set {
+ if (topLeftHeaderCell == value)
+ return;
+
+ if (topLeftHeaderCell != null)
+ topLeftHeaderCell.SetDataGridView (null);
+
topLeftHeaderCell = value;
- topLeftHeaderCell.SetDataGridView (this);
+
+ if (topLeftHeaderCell != null)
+ topLeftHeaderCell.SetDataGridView (this);
}
}
public virtual bool BeginEdit (bool selectAll) {
if (currentCell == null || currentCell.IsInEditMode)
return false;
-
+
if (currentCell.RowIndex >= 0) {
if ((currentCell.InheritedState & DataGridViewElementStates.ReadOnly) == DataGridViewElementStates.ReadOnly) {
return false;
}
}
-
+
DataGridViewCell cell = currentCell;
Type editType = cell.EditType;
if (e.Cancel)
return false;
- // If the user begins an edit in the NewRow, add a new row
- if (CurrentCell.RowIndex == NewRowIndex) {
- new_row_commited = false;
- OnUserAddedRow (new DataGridViewRowEventArgs (Rows[NewRowIndex]));
- }
-
cell.SetIsInEditMode (true);
// The cell has an editing control we need to setup
cell.PositionEditingControl (true, true, this.GetCellDisplayRectangle (cell.ColumnIndex, cell.RowIndex, false), bounds, style, false, false, (columns [cell.ColumnIndex].DisplayIndex == 0), (cell.RowIndex == 0));
// Show the editing control
- EditingControlInternal.Visible = true;
+ if (EditingControlInternal != null)
+ EditingControlInternal.Visible = true;
- // Allow editing control to set focus as needed
- (EditingControlInternal as IDataGridViewEditingControl).PrepareEditingControlForEdit (selectAll);
-
+ IDataGridViewEditingControl dgvEditingControl = (IDataGridViewEditingControl) EditingControlInternal;
+ if (dgvEditingControl != null) {
+ dgvEditingControl.EditingControlDataGridView = this;
+ dgvEditingControl.EditingControlRowIndex = currentCell.OwningRow.Index;
+ dgvEditingControl.ApplyCellStyleToEditingControl (style);
+ dgvEditingControl.PrepareEditingControlForEdit (selectAll);
+ dgvEditingControl.EditingControlFormattedValue = currentCell.EditedFormattedValue;
+ }
return true;
}
public bool CancelEdit ()
{
- if (currentCell != null && currentCell.IsInEditMode) {
- // The user's typing caused a new row to be created, but
- // now they are canceling that typing, we have to remove
- // the new row we added.
- if (!new_row_commited) {
- DataGridViewRow delete_row = EditingRow;
- Rows.RemoveInternal (delete_row);
- editing_row = Rows[currentCell.RowIndex];
- OnUserDeletedRow (new DataGridViewRowEventArgs (delete_row));
- new_row_commited = true;
+ if (currentCell != null) {
+ if (currentCell.IsInEditMode) {
+ currentCell.SetIsInEditMode (false);
+ currentCell.DetachEditingControl ();
}
- currentCell.SetIsInEditMode (false);
- currentCell.DetachEditingControl ();
- OnCellEndEdit (new DataGridViewCellEventArgs (currentCell.ColumnIndex, currentCell.RowIndex));
+ if (currentCell.RowIndex == NewRowIndex) {
+ if (DataManager != null)
+ DataManager.CancelCurrentEdit ();
+
+ new_row_editing = false;
+ PrepareEditingRow (false, false);
+ MoveCurrentCell (currentCell.ColumnIndex, NewRowIndex, true, false, false, true);
+ OnUserDeletedRow (new DataGridViewRowEventArgs (EditingRow));
+ }
}
return true;
public bool CommitEdit (DataGridViewDataErrorContexts context)
{
- if (currentCell != null && currentCell.IsInEditMode) {
- IDataGridViewEditingControl ctrl = EditingControl as IDataGridViewEditingControl;
- ctrl.GetEditingControlFormattedValue (DataGridViewDataErrorContexts.Commit);
- currentCell.Value = ctrl.GetEditingControlFormattedValue (DataGridViewDataErrorContexts.Commit);
+ if (currentCell == null)
return true;
+
+ try {
+ currentCell.Value = currentCell.ParseFormattedValue (currentCell.EditedFormattedValue,
+ currentCell.InheritedStyle, null, null);
+ } catch (Exception e) {
+ DataGridViewDataErrorEventArgs args = new DataGridViewDataErrorEventArgs (e, currentCell.ColumnIndex, currentCell.RowIndex,
+ DataGridViewDataErrorContexts.Commit);
+ OnDataError (false, args);
+ if (args.ThrowException)
+ throw e;
+ return false;
}
-
- return false;
+ return true;
}
[MonoTODO ("Always includes partial columns")]
return result;
}
- [MonoTODO ("Always includes partial rows")]
public int DisplayedRowCount (bool includePartialRow)
{
int result = 0;
-
- for (int i = first_row_index; i < Rows.Count; i++)
- if (Rows[i].Displayed)
+ int rowTop = 0;
+
+ if (ColumnHeadersVisible)
+ rowTop += ColumnHeadersHeight;
+
+ Size visibleClientArea = ClientSize;
+ if (verticalScrollBar.Visible)
+ visibleClientArea.Width -= verticalScrollBar.Width;
+ if (horizontalScrollBar.Visible)
+ visibleClientArea.Height -= horizontalScrollBar.Height;
+
+ for (int index = first_row_index; index < Rows.Count; index++) {
+ DataGridViewRow row = GetRowInternal (index);
+ if (rowTop + row.Height <= visibleClientArea.Height) {
result++;
- else
+ rowTop += row.Height;
+ } else {
+ if (includePartialRow)
+ result++;
break;
+ }
+ }
return result;
}
public bool EndEdit ()
{
- if (currentCell != null && currentCell.IsInEditMode) {
- if (EditingControl != null) {
- IDataGridViewEditingControl ctrl = EditingControl as IDataGridViewEditingControl;
- ctrl.GetEditingControlFormattedValue (DataGridViewDataErrorContexts.Commit);
- currentCell.Value = ctrl.GetEditingControlFormattedValue (DataGridViewDataErrorContexts.Commit);
-
- currentCell.SetIsInEditMode (false);
- currentCell.DetachEditingControl ();
- } else if (currentCell is IDataGridViewEditingCell) {
- currentCell.Value = (currentCell as IDataGridViewEditingCell).EditingCellFormattedValue;
- currentCell.SetIsInEditMode (false);
- }
-
- new_row_commited = true;
- OnCellEndEdit (new DataGridViewCellEventArgs (currentCell.ColumnIndex, currentCell.RowIndex));
- }
-
- return true;
+ return EndEdit (DataGridViewDataErrorContexts.Commit);
}
[MonoTODO ("Does not use context parameter")]
public bool EndEdit (DataGridViewDataErrorContexts context)
{
- return EndEdit ();
+ if (currentCell == null || !currentCell.IsInEditMode)
+ return true;
+
+ if (!CommitEdit (context)) {
+ if (DataManager != null)
+ DataManager.EndCurrentEdit ();
+ if (EditingControl != null)
+ EditingControl.Focus ();
+ return false;
+ }
+
+ currentCell.SetIsInEditMode (false);
+ currentCell.DetachEditingControl ();
+ OnCellEndEdit (new DataGridViewCellEventArgs (currentCell.ColumnIndex, currentCell.RowIndex));
+ Focus ();
+ if (currentCell.RowIndex == NewRowIndex) {
+ new_row_editing = false;
+ editing_row = null; // editing row becomes a real row
+ PrepareEditingRow (true, false); // add a new editing row
+ MoveCurrentCell (currentCell.ColumnIndex, NewRowIndex, true, false, false, true);
+ }
+ return true;
}
public int GetCellCount (DataGridViewElementStates includeFilter) {
}
for (int i = first_row_index; i < Rows.Count; i++) {
- if (i == rowIndex) {
+ if (!rows[i].Visible)
+ continue;
+
+ if (rows[i].Index == rowIndex) {
h = rows [i].Height;
break;
}
if (ColumnHeadersVisible)
y += ColumnHeadersHeight;
+
for (int i = first_row_index; i < Rows.Count; i++) {
- if (i == rowIndex) {
- h = rows[i].Height;
+ if (!rows[i].Visible)
+ continue;
+
+ if (rows[i].Index == rowIndex) {
+ h = rows [i].Height;
break;
}
-
- y += rows[i].Height;
+
+ y += rows [i].Height;
}
return new Rectangle (0, y, Width, h);
for (int i = first_row_index; i < Rows.Count; i++) {
DataGridViewRow row = Rows[i];
+ if (!row.Visible)
+ continue;
if (y > top && y <= (top + row.Height)) {
rowindex = i;
}
public virtual void NotifyCurrentCellDirty (bool dirty) {
- throw new NotImplementedException();
+ if (currentCell != null)
+ InvalidateCell (currentCell);
}
public bool RefreshEdit ()
throw new ArgumentNullException ("dataGridViewColumn");
if (dataGridViewColumn.DataGridView != this)
throw new ArgumentException ("dataGridViewColumn");
- // XXX: This is thrown too much, disable for now..
- //if (DataSource != null && !dataGridViewColumn.IsDataBound)
- // throw new ArgumentException ("dataGridViewColumn");
- //if (VirtualMode && !dataGridViewColumn.IsDataBound)
- // throw new InvalidOperationException ();
+
+ if (!EndEdit ())
+ return;
if (SortedColumn != null)
SortedColumn.HeaderCell.SortGlyphDirection = SortOrder.None;
- EndEdit ();
-
- // Figure out if this is a numeric sort or text sort
- bool is_numeric = true;
- double n;
+ sortedColumn = dataGridViewColumn;
+ sortOrder = direction == ListSortDirection.Ascending ? SortOrder.Ascending : SortOrder.Descending;
- foreach (DataGridViewRow row in Rows) {
- object val = row.Cells[dataGridViewColumn.Index].Value;
+ if (Rows.Count == 0)
+ return;
+
+ if (dataGridViewColumn.IsDataBound) {
+ IBindingList bindingList = DataManager.List as IBindingList;
+ if (bindingList != null && bindingList.SupportsSorting) {
+ bindingList.ApplySort (DataManager.GetItemProperties()[dataGridViewColumn.DataPropertyName], direction);
+ dataGridViewColumn.HeaderCell.SortGlyphDirection = sortOrder;
+ }
+ } else {
+ // Figure out if this is a numeric sort or text sort
+ bool is_numeric = true;
+ double n;
- if (val != null && !double.TryParse (val.ToString (), out n)) {
- is_numeric = false;
- break;
+ foreach (DataGridViewRow row in Rows) {
+ object val = row.Cells[dataGridViewColumn.Index].Value;
+
+ if (val != null && !double.TryParse (val.ToString (), out n)) {
+ is_numeric = false;
+ break;
+ }
}
+
+ ColumnSorter sorter = new ColumnSorter (dataGridViewColumn, direction, is_numeric);
+ Rows.Sort (sorter);
+ dataGridViewColumn.HeaderCell.SortGlyphDirection = sortOrder;
}
-
- ColumnSorter sorter = new ColumnSorter (dataGridViewColumn, direction, is_numeric);
- Rows.Sort (sorter);
-
- sortedColumn = dataGridViewColumn;
- sortOrder = (SortOrder)direction + 1;
-
- dataGridViewColumn.HeaderCell.SortGlyphDirection = (SortOrder)direction + 1;
Invalidate ();
-
OnSorted (EventArgs.Empty);
}
}
foreach (DataGridViewRow row in Rows) {
+ if (!row.Visible)
+ continue;
if (!displayed_only || row.Displayed) {
int new_height = row.GetPreferredHeight (row.Index, mode, fixedWidth);
protected override void OnBindingContextChanged (EventArgs e)
{
base.OnBindingContextChanged(e);
+ ReBind();
}
protected virtual void OnBorderStyleChanged (EventArgs e)
protected virtual void OnCellEnter (DataGridViewCellEventArgs e)
{
+ DataGridViewCell cell = GetCellInternal (e.ColumnIndex, e.RowIndex);
+ cell.OnEnterInternal (e.RowIndex, true);
+
DataGridViewCellEventHandler eh = (DataGridViewCellEventHandler)(Events [CellEnterEvent]);
if (eh != null)
eh (this, e);
protected virtual void OnCellLeave (DataGridViewCellEventArgs e)
{
+ DataGridViewCell cell = GetCellInternal (e.ColumnIndex, e.RowIndex);
+ cell.OnLeaveInternal (e.RowIndex, true);
+
DataGridViewCellEventHandler eh = (DataGridViewCellEventHandler)(Events [CellLeaveEvent]);
if (eh != null)
eh (this, e);
eh (this, e);
}
+ internal void OnCellStateChangedInternal (DataGridViewCellStateChangedEventArgs e) {
+ this.OnCellStateChanged (e);
+ }
+
protected virtual void OnCellStateChanged (DataGridViewCellStateChangedEventArgs e)
{
DataGridViewCellStateChangedEventHandler eh = (DataGridViewCellStateChangedEventHandler)(Events [CellStateChangedEvent]);
internal void OnColumnAddedInternal (DataGridViewColumnEventArgs e)
{
if (e.Column.CellTemplate != null) {
+ // The first column has just been added programatically instead of
+ // autogenerated so we need to create the rows for the first time.
+ //
+ if (!is_autogenerating_columns && columns.Count == 1)
+ ReBind ();
foreach (DataGridViewRow row in Rows)
row.Cells.Add ((DataGridViewCell)e.Column.CellTemplate.Clone ());
}
eh (this, e);
}
- internal void OnColumnRemovedInternal (DataGridViewColumnEventArgs e)
+ internal void OnColumnPreRemovedInternal (DataGridViewColumnEventArgs e)
+ {
+ if (Columns.Count - 1 == 0) {
+ MoveCurrentCell (-1, -1, true, false, false, true);
+ rows.ClearInternal ();
+ } else if (currentCell != null && CurrentCell.ColumnIndex == e.Column.Index) {
+ int nextColumnIndex = e.Column.Index;
+ if (nextColumnIndex >= Columns.Count - 1)
+ nextColumnIndex = Columns.Count - 1 - 1;
+ MoveCurrentCell (nextColumnIndex, currentCell.RowIndex, true, false, false, true);
+ if (hover_cell != null && hover_cell.ColumnIndex >= e.Column.Index)
+ hover_cell = null;
+ }
+ }
+
+ private void OnColumnPostRemovedInternal (DataGridViewColumnEventArgs e)
{
if (e.Column.CellTemplate != null) {
int index = e.Column.Index;
}
AutoResizeColumnsInternal ();
- OnColumnRemoved (e);
PrepareEditingRow (false, true);
+
+ OnColumnRemoved (e);
}
protected virtual void OnColumnRemoved (DataGridViewColumnEventArgs e)
protected override void OnHandleCreated (EventArgs e)
{
base.OnHandleCreated(e);
+ ReBind ();
- if (Rows.Count > 0 && Columns.Count > 0)
+ if (DataManager == null && CurrentCell == null && Rows.Count > 0 && Columns.Count > 0)
MoveCurrentCell (ColumnDisplayIndexToIndex (0), 0, true, false, false, false);
}
protected override void OnMouseDoubleClick (MouseEventArgs e)
{
base.OnMouseDoubleClick(e);
+
+ HitTestInfo hitInfo = HitTest (e.X, e.Y);
+ if (hitInfo.Type == DataGridViewHitTestType.Cell)
+ OnCellMouseDoubleClick (new DataGridViewCellMouseEventArgs (hitInfo.ColumnIndex, hitInfo.RowIndex,
+ hitInfo.ColumnX, hitInfo.RowY, e));
}
private void DoSelectionOnMouseDown (HitTestInfo hitTest)
{
base.OnMouseDown(e);
+ if (!EndEdit ())
+ return;
+
HitTestInfo hitTest = HitTest(e.X, e.Y);
DataGridViewCell cell = null;
if (hitTest.Type == DataGridViewHitTestType.ColumnHeader && MouseOverColumnResize (hitTest.ColumnIndex, e.X)) {
if (e.Clicks == 2) {
- EndEdit ();
AutoResizeColumn (hitTest.ColumnIndex);
return;
}
column_resize_active = true;
resize_band_start = e.X;
resize_band_delta = 0;
- EndEdit ();
DrawVerticalResizeLine (resize_band_start);
return;
}
if (hitTest.Type == DataGridViewHitTestType.RowHeader && MouseOverRowResize (hitTest.RowIndex, e.Y)) {
if (e.Clicks == 2) {
- EndEdit ();
AutoResizeRow (hitTest.RowIndex);
return;
}
row_resize_active = true;
resize_band_start = e.Y;
resize_band_delta = 0;
- EndEdit ();
DrawHorizontalResizeLine (resize_band_start);
return;
}
if (hitTest.Type == DataGridViewHitTestType.Cell) {
+ row = rows [hitTest.RowIndex];
+ cell = row.Cells [hitTest.ColumnIndex];
+ SetCurrentCellAddressCore (cell.ColumnIndex, cell.RowIndex, false, true, true);
cellBounds = GetCellDisplayRectangle (hitTest.ColumnIndex, hitTest.RowIndex, false);
OnCellMouseDown (new DataGridViewCellMouseEventArgs (hitTest.ColumnIndex, hitTest.RowIndex, e.X - cellBounds.X, e.Y - cellBounds.Y, e));
OnCellClick (new DataGridViewCellEventArgs (hitTest.ColumnIndex, hitTest.RowIndex));
- row = rows [hitTest.RowIndex];
- cell = row.Cells [hitTest.ColumnIndex];
}
DoSelectionOnMouseDown (hitTest);
return;
}
- if (cell == currentCell) {
- BeginEdit (true);
- return;
- } else if (currentCell != null) {
- EndEdit ();
- OnCellLeave(new DataGridViewCellEventArgs(currentCell.ColumnIndex, currentCell.RowIndex));
- }
- currentCell = cell;
- currentCellAddress = new Point (currentCell.ColumnIndex, currentCell.RowIndex);
- currentRow = cell.OwningRow;
- OnCurrentCellChanged(EventArgs.Empty);
- OnCellEnter(new DataGridViewCellEventArgs(cell.ColumnIndex, cell.RowIndex));
- if (editMode == DataGridViewEditMode.EditOnEnter) {
- BeginEdit (true);
- }
Invalidate();
return;
}
+ private void UpdateBindingPosition (int position)
+ {
+ if (DataManager != null)
+ DataManager.Position = position;
+ }
+
protected override void OnMouseEnter (EventArgs e)
{
base.OnMouseEnter(e);
protected override void OnMouseWheel (MouseEventArgs e)
{
base.OnMouseWheel(e);
+
+ int delta = SystemInformation.MouseWheelScrollLines * verticalScrollBar.SmallChange;
+ if (e.Delta < 0)
+ verticalScrollBar.SafeValueSet (verticalScrollBar.Value + delta);
+ else
+ verticalScrollBar.SafeValueSet (verticalScrollBar.Value - delta);
+
+ OnVScrollBarScroll (this, new ScrollEventArgs (ScrollEventType.ThumbPosition, verticalScrollBar.Value));
}
protected virtual void OnMultiSelectChanged (EventArgs e)
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++)
+ // Reset not displayed columns to !Displayed
+ for (int i = 0; i < first_col_index; i++)
Columns[i].DisplayedInternal = false;
+ int gridWidth = rowHeadersVisible ? rowHeadersWidth : 0;
+
// Set Displayed columns
for (int i = first_col_index; i < Columns.Count; i++) {
DataGridViewColumn col = Columns.ColumnDisplayIndexSortedArrayList[i];
col.DisplayedInternal = true;
gridWidth += col.Width;
-
if (gridWidth >= Width)
break;
}
- // Reset all rows to !Displayed
- for (int i = 0; i < Rows.Count; i++)
+ // Reset all not displayed rows to !Displayed
+ for (int i = 0; i < first_row_index; i++)
GetRowInternal (i).DisplayedInternal = false;
// Draw rows
for (int index = first_row_index; index < Rows.Count; index++) {
DataGridViewRow row = Rows[index];
+ if (!row.Visible)
+ continue;
GetRowInternal (index).DisplayedInternal = true;
bounds.Height = row.Height;
bounds.Y += bounds.Height;
bounds.X = BorderWidth;
- if (bounds.Y < ClientSize.Height - (horizontalScrollBar.Visible ? horizontalScrollBar.Height : 0))
- rows_displayed++;
- else
+ if (bounds.Y >= ClientSize.Height - (horizontalScrollBar.Visible ? horizontalScrollBar.Height : 0))
break;
-
- gridHeight += row.Height;
}
- gridWidth = 0;
+ RefreshScrollBars ();
- foreach (DataGridViewColumn col in sortedColumns)
+ // Paint the bottom right square if both scrollbars are displayed
+ if (horizontalScrollBar.Visible && verticalScrollBar.Visible)
+ g.FillRectangle (SystemBrushes.Control, new Rectangle (horizontalScrollBar.Right, verticalScrollBar.Bottom, verticalScrollBar.Width, horizontalScrollBar.Height));
+
+ // Paint the border
+ bounds = ClientRectangle;
+
+ switch (BorderStyle) {
+ case BorderStyle.FixedSingle:
+ g.DrawRectangle (Pens.Black, new Rectangle (bounds.Left, bounds.Top, bounds.Width - 1, bounds.Height - 1));
+ break;
+ case BorderStyle.Fixed3D:
+ ControlPaint.DrawBorder3D (g, bounds, Border3DStyle.Sunken);
+ break;
+ }
+ }
+
+ private void RefreshScrollBars ()
+ {
+ int gridWidth = 0;
+ int gridHeight = 0;
+
+ foreach (DataGridViewColumn col in columns.ColumnDisplayIndexSortedArrayList)
if (col.Visible)
gridWidth += col.Width;
-
- gridHeight = 0;
foreach (DataGridViewRow row in Rows)
- gridHeight += row.Height;
+ if (row.Visible)
+ gridHeight += row.Height;
if (rowHeadersVisible)
gridWidth += rowHeadersWidth;
-
if (columnHeadersVisible)
gridHeight += columnHeadersHeight;
-
+
bool horizontalVisible = false;
bool verticalVisible = false;
if (AutoSize) {
- if (gridWidth > Size.Width || gridHeight > Size.Height) {
+ if (gridWidth > Size.Width || gridHeight > Size.Height)
Size = new Size(gridWidth, gridHeight);
- }
}
else {
- if (gridWidth > Size.Width) {
+ if (gridWidth > Size.Width)
horizontalVisible = true;
- }
- if (gridHeight > Size.Height) {
+ if (gridHeight > Size.Height)
verticalVisible = true;
- }
- if (horizontalScrollBar.Visible && (gridHeight + horizontalScrollBar.Height) > Size.Height) {
+
+ if (horizontalScrollBar.Visible && (gridHeight + horizontalScrollBar.Height) > Size.Height)
verticalVisible = true;
- }
- if (verticalScrollBar.Visible && (gridWidth + verticalScrollBar.Width) > Size.Width) {
+ if (verticalScrollBar.Visible && (gridWidth + verticalScrollBar.Width) > Size.Width)
horizontalVisible = true;
- }
+
+ if (scrollBars != ScrollBars.Vertical && scrollBars != ScrollBars.Both)
+ verticalVisible = false;
+ if (scrollBars != ScrollBars.Horizontal && scrollBars != ScrollBars.Both)
+ horizontalVisible = false;
+
if (horizontalVisible) {
horizontalScrollBar.Minimum = 0;
horizontalScrollBar.Maximum = gridWidth;
horizontalScrollBar.SmallChange = Columns[first_col_index].Width;
- horizontalScrollBar.LargeChange = ClientSize.Width - rowHeadersWidth;
+ int largeChange = ClientSize.Width - rowHeadersWidth - horizontalScrollBar.Height;
+ if (largeChange <= 0)
+ largeChange = ClientSize.Width;
+ horizontalScrollBar.LargeChange = largeChange;
}
+
if (verticalVisible) {
verticalScrollBar.Minimum = 0;
verticalScrollBar.Maximum = gridHeight;
+ int first_row_height = Rows.Count > 0 ? Rows[Math.Min (Rows.Count - 1, first_row_index)].Height : 0;
verticalScrollBar.SmallChange = first_row_height + 1;
- verticalScrollBar.LargeChange = ClientSize.Height - columnHeadersHeight;
+ int largeChange = ClientSize.Height - columnHeadersHeight - verticalScrollBar.Width;
+ if (largeChange <= 0)
+ largeChange = ClientSize.Height;
+ verticalScrollBar.LargeChange = largeChange;
}
}
horizontalScrollBar.Visible = horizontalVisible;
verticalScrollBar.Visible = verticalVisible;
-
- // Paint the bottom right square if both scrollbars are displayed
- if (horizontalScrollBar.Visible && verticalScrollBar.Visible)
- g.FillRectangle (SystemBrushes.Control, new Rectangle (horizontalScrollBar.Right, verticalScrollBar.Bottom, verticalScrollBar.Width, horizontalScrollBar.Height));
-
- // Paint the border
- bounds = ClientRectangle;
-
- switch (BorderStyle) {
- case BorderStyle.FixedSingle:
- g.DrawRectangle (Pens.Black, new Rectangle (bounds.Left, bounds.Top, bounds.Width - 1, bounds.Height - 1));
- break;
- case BorderStyle.Fixed3D:
- ControlPaint.DrawBorder3D (g, bounds, Border3DStyle.Sunken);
- break;
- }
}
protected virtual void OnReadOnlyChanged (EventArgs e) {
internal void OnRowsAddedInternal (DataGridViewRowsAddedEventArgs e)
{
+ if (hover_cell != null && hover_cell.RowIndex >= e.RowIndex)
+ hover_cell = null;
+
+ // Select the first row if we are not databound.
+ // If we are databound selection is managed by the data manager.
+ if (IsHandleCreated && DataManager == null && Rows.Count == 1 && Columns.Count > 0)
+ MoveCurrentCell (ColumnDisplayIndexToIndex (0), 0, true, false, false, true);
+
+ AutoResizeColumnsInternal ();
Invalidate ();
OnRowsAdded (e);
}
- protected internal virtual void OnRowsAdded (DataGridViewRowsAddedEventArgs e)
+ protected virtual void OnRowsAdded (DataGridViewRowsAddedEventArgs e)
{
DataGridViewRowsAddedEventHandler eh = (DataGridViewRowsAddedEventHandler)(Events [RowsAddedEvent]);
if (eh != null) eh (this, e);
if (eh != null) eh (this, e);
}
- protected internal virtual void OnRowsRemoved (DataGridViewRowsRemovedEventArgs e)
+ internal void OnRowsPreRemovedInternal (DataGridViewRowsRemovedEventArgs e)
+ {
+ if (selected_rows != null)
+ selected_rows.InternalClear ();
+ if (selected_columns != null)
+ selected_columns.InternalClear ();
+
+ if (Rows.Count - e.RowCount <= 0) {
+ MoveCurrentCell (-1, -1, true, false, false, true);
+ hover_cell = null;
+ } else if (Columns.Count == 0) {
+ MoveCurrentCell (-1, -1, true, false, false, true);
+ hover_cell = null;
+ } else if (currentCell != null && currentCell.RowIndex == e.RowIndex) {
+ int nextRowIndex = e.RowIndex;
+ if (nextRowIndex >= Rows.Count - e.RowCount)
+ nextRowIndex = Rows.Count - 1 - e.RowCount;
+ MoveCurrentCell (currentCell != null ? currentCell.ColumnIndex : 0, nextRowIndex,
+ true, false, false, true);
+ if (hover_cell != null && hover_cell.RowIndex >= e.RowIndex)
+ hover_cell = null;
+ }
+ }
+
+ internal void OnRowsPostRemovedInternal (DataGridViewRowsRemovedEventArgs e)
+ {
+ Invalidate ();
+ OnRowsRemoved (e);
+ }
+
+ protected virtual void OnRowsRemoved (DataGridViewRowsRemovedEventArgs e)
{
DataGridViewRowsRemovedEventHandler eh = (DataGridViewRowsRemovedEventHandler)(Events [RowsRemovedEvent]);
if (eh != null) eh (this, e);
protected virtual void OnUserAddedRow (DataGridViewRowEventArgs e)
{
- editing_row = null;
PrepareEditingRow (false, false);
- e = new DataGridViewRowEventArgs (editing_row);
-
+ new_row_editing = true;
+ if (DataManager != null) {
+ // Switch the current editing row with a real one
+ if (editing_row != null) {
+ Rows.RemoveInternal (editing_row);
+ editing_row = null;
+ }
+ DataManager.AddNew (); // will raise OnListPositionChanged
+ }
+
+ e = new DataGridViewRowEventArgs (Rows[NewRowIndex]);
DataGridViewRowEventHandler eh = (DataGridViewRowEventHandler)(Events [UserAddedRowEvent]);
if (eh != null) eh (this, e);
}
{
DataGridViewRowEventHandler eh = (DataGridViewRowEventHandler)(Events [UserDeletedRowEvent]);
if (eh != null) eh (this, e);
-
}
protected virtual void OnUserDeletingRow (DataGridViewRowCancelEventArgs e)
protected bool ProcessDeleteKey (Keys keyData)
{
- if (!allowUserToDeleteRows || SelectedRows.Count == 0)
+ if (!AllowUserToDeleteRows || SelectedRows.Count == 0)
return false;
int index = Math.Max (selected_row - SelectedRows.Count + 1, 0);
if (hover_cell != null && hover_cell.OwningRow == row)
hover_cell = null;
- if (DataSource != null && DataSource is DataSet)
- (DataSource as DataSet).Tables[dataMember].Rows.RemoveAt (row.Index);
+ if (DataManager != null)
+ DataManager.RemoveAt (row.Index);
else
Rows.RemoveAt (row.Index);
}
- if (selected_rows != null)
- selected_rows.InternalClear ();
- if (selected_columns != null)
- selected_columns.InternalClear ();
-
- SetSelectedCellCore (0, Math.Min (index, Rows.Count - 1), true);
- Invalidate ();
-
return true;
}
{
DataGridViewCell cell = CurrentCell;
- if (cell != null)
+ if (cell != null) {
if (cell.KeyEntersEditMode (new KeyEventArgs ((Keys)m.WParam.ToInt32 ())))
BeginEdit (true);
+ if (EditingControl != null && ((Msg)m.Msg == Msg.WM_KEYDOWN || (Msg)m.Msg == Msg.WM_CHAR))
+ XplatUI.SendMessage (EditingControl.Handle, (Msg)m.Msg, m.WParam, m.LParam);
+ }
return base.ProcessKeyEventArgs (ref m);
}
base.SetBoundsCore(x, y, width, height, specified);
}
- [MonoTODO ("Does not use validateCurrentCell or throughMouseClick")]
+ [MonoTODO ("Does not use validateCurrentCell")]
protected virtual bool SetCurrentCellAddressCore (int columnIndex, int rowIndex, bool setAnchorCellAddress, bool validateCurrentCell, bool throughMouseClick)
{
if ((columnIndex < 0 || columnIndex > Columns.Count - 1) && rowIndex != -1)
if (cell != null && !cell.Visible)
throw new InvalidOperationException ("cell is not visible");
- if (setAnchorCellAddress)
- anchor_cell = new Point (columnIndex, rowIndex);
+ // Always update the current cell address property
+ // If the row has moved it would be out of date.
+ if (currentCell != null) {
+ if (setAnchorCellAddress) {
+ anchor_cell.X = currentCell.ColumnIndex;
+ anchor_cell.Y = currentCell.RowIndex;
+ }
+ currentCellAddress.X = currentCell.ColumnIndex;
+ currentCellAddress.Y = currentCell.RowIndex;
+ }
+
+ if (cell != currentCell) {
+ if (currentCell != null) {
+ if (currentCell.IsInEditMode) {
+ if (!EndEdit ())
+ return false;
+ else if (currentCell.RowIndex == NewRowIndex && new_row_editing)
+ CancelEdit ();
+ }
+ OnCellLeave (new DataGridViewCellEventArgs(currentCell.ColumnIndex, currentCell.RowIndex));
+ OnRowLeave (new DataGridViewCellEventArgs (currentCell.ColumnIndex, currentCell.RowIndex));
+ }
+
+ currentCell = cell;
+ if (setAnchorCellAddress)
+ anchor_cell = new Point (columnIndex, rowIndex);
+ currentCellAddress = new Point (columnIndex, rowIndex);
+
+ if (cell != null) {
+ UpdateBindingPosition (cell.RowIndex);
+ OnRowEnter (new DataGridViewCellEventArgs (cell.ColumnIndex, cell.RowIndex));
+ OnCellEnter (new DataGridViewCellEventArgs(cell.ColumnIndex, cell.RowIndex));
+ }
+ OnCurrentCellChanged (EventArgs.Empty);
+
+ if (cell != null) {
+ // If the user begins an edit in the NewRow, add a new row
+ if (AllowUserToAddRows && cell.RowIndex == NewRowIndex && !is_binding && !new_row_editing) {
+ // OnUserAddedRow will add a real row and reset the current cell
+ OnUserAddedRow (new DataGridViewRowEventArgs (Rows[NewRowIndex]));
+ } else {
+ if (editMode == DataGridViewEditMode.EditOnEnter)
+ BeginEdit (true);
+ }
+ }
+ } else {
+ if (cell != null && throughMouseClick)
+ BeginEdit (true);
+ }
- currentCellAddress = new Point (columnIndex, rowIndex);
- CurrentCell = cell;
-
- OnCurrentCellChanged (EventArgs.Empty);
-
return true;
}
} else if (selected && !selected_columns.Contains (col)) {
selected_columns.InternalAdd (col);
}
+
+ Invalidate();
}
internal void SetSelectedRowCoreInternal (int rowIndex, bool selected) {
- SetSelectedRowCore (rowIndex, selected);
+ if (rowIndex >= 0 && rowIndex < Rows.Count)
+ SetSelectedRowCore (rowIndex, selected);
}
protected virtual void SetSelectedRowCore (int rowIndex, bool selected) {
} else if (selected && !selected_rows.Contains (row)) {
selected_rows.InternalAdd (row);
}
+
+ Invalidate();
}
protected override void WndProc (ref Message m)
internal void OnVScrollBarScroll (object sender, ScrollEventArgs e)
{
verticalScrollingOffset = e.NewValue;
+ if (Rows.Count == 0)
+ return;
+
int top = 0;
-
+ int lastTopVisibleRowIndex = Rows.Count - DisplayedRowCount (false);
+
for (int index = 0; index < Rows.Count; index++) {
DataGridViewRow row = Rows[index];
-
- if (e.NewValue <= top + row.Height) {
+ if (!row.Visible)
+ continue;
+
+ if (row.Index >= lastTopVisibleRowIndex) {
+ first_row_index = lastTopVisibleRowIndex;
+ } else if (e.NewValue < top + row.Height) {
if (first_row_index != index) {
first_row_index = index;
Invalidate ();
top += row.Height;
}
- if (Rows.Count == 0)
- return;
-
- first_row_index = Rows.Count - DisplayedRowCount (false) + 1;
+ first_row_index = lastTopVisibleRowIndex;
Invalidate ();
OnScroll (e);
}
OnColumnAddedInternal(new DataGridViewColumnEventArgs(e.Element as DataGridViewColumn));
break;
case CollectionChangeAction.Remove:
- OnColumnRemovedInternal(new DataGridViewColumnEventArgs(e.Element as DataGridViewColumn));
+ OnColumnPostRemovedInternal(new DataGridViewColumnEventArgs(e.Element as DataGridViewColumn));
break;
case CollectionChangeAction.Refresh:
break;
case DataGridViewAutoSizeColumnMode.AllCells:
case DataGridViewAutoSizeColumnMode.DisplayedCells:
case DataGridViewAutoSizeColumnMode.DisplayedCellsExceptHeader:
- size = CalculateColumnCellWidth (columnIndex, col.InheritedAutoSizeMode);
+ size = Math.Max (CalculateColumnCellWidth (columnIndex, col.InheritedAutoSizeMode),
+ col.HeaderCell.ContentBounds.Width);
break;
case DataGridViewAutoSizeColumnMode.ColumnHeader:
size = col.HeaderCell.ContentBounds.Width;
only_visible = (mode == DataGridViewAutoSizeColumnMode.DisplayedCells || mode == DataGridViewAutoSizeColumnMode.DisplayedCellsExceptHeader);
for (int i = first_row; i < Rows.Count; i++) {
+ if (!Rows[i].Visible)
+ continue;
if (only_visible) {
Rectangle row_rect = this.GetRowDisplayRectangle (i, false);
if (!ClientRectangle.IntersectsWith (row_rect))
return bounds;
}
- internal void PrepareEditingRow (bool cell_changed, bool column_changed)
+ private void PrepareEditingRow (bool cell_changed, bool column_changed)
{
+ if (new_row_editing)
+ return;
+
bool show = false;
show = ColumnCount > 0 && AllowUserToAddRows;
- if (!show && editing_row != null) {
- Rows.RemoveInternal (editing_row);
- editing_row = null;
+ if (!show) {
+ RemoveEditingRow ();
} else if (show) {
- if (editing_row != null) {
- if (cell_changed) {
- // The row changed, it's no longer an editing row.
- editing_row = null;
- } else if (column_changed) {
- // The number of columns has changed, we need a new editing row.
- Rows.RemoveInternal (editing_row);
- editing_row = null;
- }
+ if (editing_row != null && (cell_changed || column_changed)) {
+ // The row changed, it's no longer an editing row.
+ // or
+ // The number of columns has changed, we need a new editing row.
+ RemoveEditingRow ();
}
if (editing_row == null) {
editing_row = RowTemplateFull;
Rows.AddInternal (editing_row, false);
}
}
-
-
}
- internal DataGridViewRow EditingRow {
- get { return editing_row; }
+ internal void RemoveEditingRow ()
+ {
+ if (editing_row != null) {
+ if (Rows.Contains (editing_row))
+ Rows.RemoveInternal (editing_row);
+ editing_row = null;
+ }
}
- private void BindIList (IList list) {
- if (autoGenerateColumns) {
- // Stuff from a DataSet
- if (list is DataView) {
- DataView dataView = (DataView) list;
- DataTable table = dataView.Table;
-
- foreach (DataColumn dataColumn in table.Columns) {
- DataGridViewColumn col = CreateColumnByType (dataColumn.DataType);
-
- col.Name = dataColumn.ColumnName;
- col.DataPropertyName = dataColumn.ColumnName;
- col.SetIsDataBound (true);
- col.ValueType = dataColumn.DataType;
- col.AutoGenerated = true;
-
- columns.Add (col);
- }
- }
- // Its a generic something or other, like a BindingList<T>, so
- // we can figure out the type from the generic type
- else if (list.GetType ().GetGenericArguments ().Length > 0) {
- GenerateColumnsFromType (list.GetType ().GetGenericArguments ()[0]);
- }
- // Its a normal array/collection type thing
- else if (list.GetType ().IsArray) {
- GenerateColumnsFromType (list.GetType ().GetElementType ());
- } else if (list is BindingSource && (list as BindingSource).item_type != null) {
- foreach (PropertyDescriptor property in TypeDescriptor.GetProperties ((list as BindingSource).item_type)) {
- DataGridViewColumn col = CreateColumnByType (property.PropertyType);
- col.Name = property.DisplayName;
- col.ReadOnly = property.IsReadOnly;
- col.AutoGenerated = true;
- columns.Add (col);
- }
-
- AllowUserToAddRows = (list as BindingSource).AllowNew;
- }
- }
-
- // Subscribe to the dataset's change notification
- if (list is DataView) {
- (list as DataView).ListChanged += OnListChanged;
- (list as DataView).Table.ColumnChanged += OnTableColumnChanged;
- }
-
- // Add the rows
- foreach (object element in list)
- AddBoundRow (element);
+ internal DataGridViewRow EditingRow {
+ get { return editing_row; }
}
private void AddBoundRow (object element)
if (cell == null)
continue;
- cell.valuex = property.GetValue (element);
- cell.valueType = property.PropertyType;
+ cell.Value = property.GetValue (element);
+ cell.ValueType = property.PropertyType;
}
}
- private void GenerateColumnsFromType (Type type)
+ private bool IsColumnAlreadyBound (string name)
{
- foreach (PropertyDescriptor property in TypeDescriptor.GetProperties (type)) {
- // This keeps out things like arrays
- if ((typeof(ICollection).IsAssignableFrom (property.PropertyType)))
- continue;
-
- DataGridViewColumn col = CreateColumnByType (property.PropertyType);
- col.Name = property.DisplayName;
- col.DataPropertyName = property.DisplayName;
- col.ReadOnly = property.IsReadOnly;
- col.SetIsDataBound (true);
- col.ValueType = property.PropertyType;
- col.AutoGenerated = true;
- columns.Add (col);
- }
+ foreach (DataGridViewColumn col in Columns)
+ if (col.DataPropertyName == name)
+ return true;
+
+ return false;
}
-
+
private DataGridViewColumn CreateColumnByType (Type type)
{
if (type == typeof (bool))
return new DataGridViewCheckBoxColumn ();
+ else if (typeof(Bitmap).IsAssignableFrom (type))
+ return new DataGridViewImageColumn ();
return new DataGridViewTextBoxColumn ();
}
private void ClearBinding ()
{
- columns.ClearAutoGeneratedColumns ();
- rows.Clear ();
- PrepareEditingRow (false, true);
+ if (IsCurrentCellInEditMode && !EndEdit ())
+ CancelEdit ();
+ MoveCurrentCell (-1, -1, false, false, false, true);
- if (dataSource != null) {
- if (dataSource is DataSet) {
- (dataSource as DataSet).Tables.CollectionChanged -= OnDataSetTableChanged;
-
- DataTable dt = (dataSource as DataSet).Tables[dataMember];
-
- if (dt != null) {
- DataView dv = dt.DefaultView;
-
- if (dv != null) {
- (dv as DataView).Table.ColumnChanged -= OnTableColumnChanged;
- (dv as DataView).ListChanged -= OnListChanged;
- }
- }
- } else if (dataSource is DataView) {
- (dataSource as DataView).ListChanged -= OnListChanged;
- (dataSource as DataView).Table.ColumnChanged -= OnTableColumnChanged;
- } else if (dataSource is DataTable)
- ((dataSource as IListSource).GetList () as DataView).ListChanged -= OnListChanged;
+ if (DataManager != null) {
+ DataManager.ListChanged -= OnListChanged;
+ DataManager.PositionChanged -= OnListPositionChanged;
+ columns.ClearAutoGeneratedColumns ();
+ rows.Clear ();
+ RemoveEditingRow ();
}
}
+
+ private void ResetRows ()
+ {
+ rows.Clear ();
+ RemoveEditingRow ();
+ if (DataManager != null) {
+ foreach (object element in DataManager.List)
+ AddBoundRow (element);
+ }
+ PrepareEditingRow (false, true);
+ OnListPositionChanged (this, EventArgs.Empty);
+ }
private void DoBinding ()
{
- the System.ComponentModel.IBindingListView interface, such as the System.Windows.Forms.BindingSource class.
*/
- if (dataSource != null) {
- object value = dataSource;
-
- // DataBinding
- if (value is DataSet && string.IsNullOrEmpty (dataMember)) {
- Invalidate ();
- return;
+ if (dataSource != null && DataManager != null) {
+ if (autoGenerateColumns) {
+ is_autogenerating_columns = true;
+
+ foreach (PropertyDescriptor property in DataManager.GetItemProperties()) {
+ // This keeps out things like arrays
+ if ((typeof(ICollection).IsAssignableFrom (property.PropertyType)))
+ continue;
+ if (!property.IsBrowsable)
+ continue;
+
+ if (IsColumnAlreadyBound (property.DisplayName))
+ continue;
+
+ DataGridViewColumn col = CreateColumnByType (property.PropertyType);
+ col.Name = property.DisplayName;
+ col.DataPropertyName = property.DisplayName;
+ col.ReadOnly = !DataManager.AllowEdit || property.IsReadOnly;
+ col.SetIsDataBound (true);
+ col.ValueType = property.PropertyType;
+ col.AutoGenerated = true;
+ columns.Add (col);
+ }
+
+ is_autogenerating_columns = false;
}
- if (value is DataSet) {
- (value as DataSet).Tables.CollectionChanged += OnDataSetTableChanged;
- value = (value as DataSet).Tables[dataMember];
+
+ // DataBind both autogenerated and not columns if there is a matching property
+ foreach (PropertyDescriptor property in DataManager.GetItemProperties()) {
+ foreach (DataGridViewColumn col in Columns) {
+ if (col.DataPropertyName == property.Name)
+ col.SetIsDataBound (true);
+ }
}
- if (value is BindingSource)
- value = (value as BindingSource).List;
-
- if (value is IList)
- BindIList (value as IList);
- else if (value is IListSource)
- BindIListSource (value as IListSource);
- else if (value is IBindingList)
- BindIBindingList (value as IBindingList);
- else if (value is IBindingListView)
- BindIBindingListView (value as IBindingListView);
+ foreach (object element in DataManager.List)
+ AddBoundRow (element);
+
+ DataManager.ListChanged += OnListChanged;
+ DataManager.PositionChanged += OnListPositionChanged;
OnDataBindingComplete (new DataGridViewBindingCompleteEventArgs (ListChangedType.Reset));
+ OnListPositionChanged (this, EventArgs.Empty);
+ } else {
+ if (Rows.Count > 0 && Columns.Count > 0)
+ MoveCurrentCell (0, 0, true, false, false, false);
}
+ PrepareEditingRow (false, true);
+ PerformLayout();
Invalidate ();
}
- private void BindIListSource (IListSource list) {
- BindIList(list.GetList());
- }
+ private void MoveCurrentCell (int x, int y, bool select, bool isControl, bool isShift, bool scroll)
+ {
+ if (x == -1 || y == -1)
+ x = y = -1;
+ else {
+ if (x < 0 || x > Columns.Count - 1)
+ throw new ArgumentOutOfRangeException ("x");
+ if (y < 0 || y > Rows.Count - 1)
+ throw new ArgumentOutOfRangeException ("y");
+
+ if (!Rows[y].Visible) {
+ for (int i = y; i < Rows.Count; i++) {
+ if (Rows[i].Visible) {
+ y = i;
+ break;
+ }
+ }
+ }
- private void BindIBindingList (IBindingList list) {
- BindIList(list);
- }
+ if (!Columns[x].Visible) {
+ for (int i = x; i < Columns.Count; i++) {
+ if (Columns[i].Visible) {
+ x = i;
+ break;
+ }
+ }
+ }
- private void BindIBindingListView (IBindingListView list) {
- BindIList(list);
- }
+ // in case either no visible columns or rows
+ if (!Rows[y].Visible || !Columns[x].Visible)
+ x = y = -1;
+ }
+
+ if (!SetCurrentCellAddressCore (x, y, true, false, false)) {
+ ClearSelection ();
+ return;
+ }
+ if (x == -1 && y == -1) {
+ ClearSelection ();
+ return;
+ }
- 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;
else if (mode == DataGridViewSelectionMode.ColumnHeaderSelect)
mode = DataGridViewSelectionMode.CellSelect;
- // End edit if the old cell was editing, and fire CellLeave for the old cell
- if (currentCell != null) {
- OnCellLeave (new DataGridViewCellEventArgs (currentCell.ColumnIndex, currentCell.RowIndex));
-
- if (currentCell.IsInEditMode)
- EndEdit ();
- }
-
- // 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);
+ bool scrollbarsRefreshed = false;
if (disp_x < first_col_index) {
+ // The trick here is that in order to avoid unnecessary calculations each time a row/column
+ // is added/removed we recalculate the whole grid size just before just before the scroll
+ // to selection.
+ RefreshScrollBars ();
+ scrollbarsRefreshed = true;
int delta_x = 0;
if (disp_x == 0)
delta_x = horizontalScrollBar.Value;
- else
+ else {
+ // in case the column got removed
+ if (first_col_index >= ColumnCount)
+ first_col_index = ColumnCount - 1;
for (int i = disp_x; i < first_col_index; i++)
delta_x += Columns[ColumnDisplayIndexToIndex (i)].Width;
+ }
horizontalScrollBar.SafeValueSet (horizontalScrollBar.Value - delta_x);
OnHScrollBarScroll (this, new ScrollEventArgs (ScrollEventType.ThumbPosition, horizontalScrollBar.Value));
}
int disp_y = y;
+ int displayedRowsCount = DisplayedRowCount (false);
+ int delta_y = 0;
if (disp_y < first_row_index) {
- int delta_y = 0;
+ if (!scrollbarsRefreshed)
+ RefreshScrollBars ();
if (disp_y == 0)
delta_y = verticalScrollBar.Value;
- else
+ else {
+ // in case the row got removed
+ if (first_row_index >= RowCount)
+ first_row_index = RowCount - 1;
for (int i = disp_y; i < first_row_index; i++)
delta_y += GetRowInternal (i).Height;
+ }
verticalScrollBar.SafeValueSet (verticalScrollBar.Value - delta_y);
OnVScrollBarScroll (this, new ScrollEventArgs (ScrollEventType.ThumbPosition, verticalScrollBar.Value));
- } else if (disp_y > first_row_index + DisplayedRowCount (false) - 2) {
- int delta_y = 0;
-
+ } else if (disp_y > first_row_index + displayedRowsCount - 1) {
+ if (!scrollbarsRefreshed)
+ RefreshScrollBars ();
+
if (disp_y == Rows.Count - 1)
delta_y = verticalScrollBar.Maximum - verticalScrollBar.Value;
else
- for (int i = first_row_index + DisplayedRowCount (false) - 2; i < disp_y; i++)
+ for (int i = first_row_index + displayedRowsCount - 1; i < disp_y; i++)
delta_y += GetRowInternal (i).Height;
verticalScrollBar.SafeValueSet (verticalScrollBar.Value + delta_y);
break;
}
- // Raise CellEnter
- OnCellEnter (new DataGridViewCellEventArgs (currentCell.ColumnIndex, currentCell.RowIndex));
-
Invalidate ();
}
private int ColumnIndexToDisplayIndex (int index)
{
+ if (index == -1)
+ return index;
return Columns[index].DisplayIndex;
}
{
switch (args.ListChangedType) {
case ListChangedType.ItemAdded:
- AddBoundRow ((sender as DataView)[args.NewIndex]);
+ AddBoundRow (DataManager[args.NewIndex]);
break;
case ListChangedType.ItemDeleted:
- Rows.RemoveAt (args.NewIndex);
+ Rows.RemoveAtInternal (args.NewIndex);
+ break;
+ case ListChangedType.ItemChanged:
+ break;
+ default:
+ ResetRows ();
break;
}
Invalidate ();
}
- private void OnTableColumnChanged (object sender, DataColumnChangeEventArgs e)
+ private void OnListPositionChanged (object sender, EventArgs args)
{
- ClearBinding ();
- DoBinding ();
+ if (Rows.Count > 0 && Columns.Count > 0 && DataManager.Position != -1)
+ MoveCurrentCell (currentCell != null ? currentCell.ColumnIndex : 0, DataManager.Position,
+ true, false, false, true);
+ else
+ MoveCurrentCell (-1, -1, true, false, false, true);
}
- private void OnDataSetTableChanged (object sender, CollectionChangeEventArgs e)
+ private void ReBind ()
{
- ClearBinding ();
- DoBinding ();
+ if (!is_binding) {
+ is_binding = true;
+ ClearBinding ();
+ DoBinding ();
+ is_binding = false;
+ }
}
-
+
private bool MouseOverColumnResize (int col, int mousex)
{
if (!allowUserToResizeColumns)
DataGridViewRow row2 = (DataGridViewRow)y;
if (row1.Cells[column].ValueType == typeof (DateTime) && row2.Cells[column].ValueType == typeof (DateTime))
- return DateTime.Compare ((DateTime)row1.Cells[column].valuex, (DateTime)row2.Cells[column].valuex) * direction;
+ return DateTime.Compare ((DateTime)row1.Cells[column].Value, (DateTime)row2.Cells[column].Value) * direction;
object val1 = row1.Cells[column].FormattedValue;
object val2 = row2.Cells[column].FormattedValue;
+ object val1NullValue = row1.Cells[column].InheritedStyle.NullValue;
+ object val2NullValue = row2.Cells[column].InheritedStyle.NullValue;
- if (val1 == null && val2 == null)
+ if (val1 == val1NullValue && val2 == val2NullValue)
return 0;
- if (val1 == null)
+ if (val1 == val1NullValue)
return direction;
- if (val2 == null)
+ if (val2 == val2NullValue)
return -1 * direction;
if (numeric_sort)