Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / WinForms / Managed / System / WinForms / DataGridViewMethods.cs / 1305376 / DataGridViewMethods.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Windows.Forms { using System.Text; using System.Runtime.InteropServices; using System.Runtime.Remoting; using System.ComponentModel; using System; using System.Diagnostics.CodeAnalysis; using System.Security; using System.Security.Permissions; using System.Collections; using System.Windows.Forms.Design; using System.ComponentModel.Design; using System.Drawing; using System.Windows.Forms.ComponentModel; using System.Globalization; using System.Diagnostics; using System.Windows.Forms.VisualStyles; using System.Windows.Forms.Layout; using Microsoft.Win32; using System.Collections.Specialized; using System.Windows.Forms.Internal; using System.Runtime.Versioning; ///public partial class DataGridView { /// protected virtual void AccessibilityNotifyCurrentCellChanged(Point cellAddress) { if (cellAddress.X < 0 || cellAddress.X >= this.Columns.Count) { throw new ArgumentOutOfRangeException("cellAddress"); } if (cellAddress.Y < 0 || cellAddress.Y >= this.Rows.Count) { throw new ArgumentOutOfRangeException("cellAddress"); } int visibleRowIndex = this.Rows.GetRowCount(DataGridViewElementStates.Visible, 0, cellAddress.Y); int visibleColumnIndex = this.Columns.ColumnIndexToActualDisplayIndex(cellAddress.X, DataGridViewElementStates.Visible); int topHeaderRowIncrement = this.ColumnHeadersVisible ? 1 : 0; int rowHeaderIncrement = this.RowHeadersVisible ? 1 : 0; int objectID = visibleRowIndex + topHeaderRowIncrement // + 1 because the top header row acc obj is at index 0 + 1; // + 1 because objectID's need to be positive and non-zero int childID = visibleColumnIndex + rowHeaderIncrement; // + 1 because the column header cell is at index 0 in top header row acc obj // same thing for the row header cell in the data grid view row acc obj if (this.ContainsFocus) { this.AccessibilityNotifyClients(AccessibleEvents.Focus, objectID, childID); } this.AccessibilityNotifyClients(AccessibleEvents.Selection, objectID, childID); } internal void ActivateToolTip(bool activate, string toolTipText, int columnIndex, int rowIndex) { this.toolTipCaption = toolTipText; this.ptToolTipCell = new Point(columnIndex, rowIndex); this.toolTipControl.Activate(activate); } internal void AddNewRow(bool createdByEditing) { Debug.Assert(this.Columns.Count > 0); Debug.Assert(this.newRowIndex == -1); this.Rows.AddInternal(true /*newRow*/, null /*values*/); this.newRowIndex = this.Rows.Count - 1; this.dataGridViewState1[DATAGRIDVIEWSTATE1_newRowCreatedByEditing] = createdByEditing; if (createdByEditing) { DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs(this.Rows[this.newRowIndex]); OnUserAddedRow(dgvre); } } /// [ EditorBrowsable(EditorBrowsableState.Advanced) ] public virtual DataGridViewAdvancedBorderStyle AdjustColumnHeaderBorderStyle(DataGridViewAdvancedBorderStyle dataGridViewAdvancedBorderStyleInput, DataGridViewAdvancedBorderStyle dataGridViewAdvancedBorderStylePlaceholder, bool isFirstDisplayedColumn, bool isLastVisibleColumn) { if (this.ApplyVisualStylesToHeaderCells) { switch (dataGridViewAdvancedBorderStyleInput.All) { case DataGridViewAdvancedCellBorderStyle.OutsetPartial: case DataGridViewAdvancedCellBorderStyle.OutsetDouble: if (this.RightToLeftInternal) { dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.None; if (isFirstDisplayedColumn) { dataGridViewAdvancedBorderStylePlaceholder.RightInternal = this.RowHeadersVisible ? DataGridViewAdvancedCellBorderStyle.None : DataGridViewAdvancedCellBorderStyle.Outset; } else { dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.None; } } else { if (isFirstDisplayedColumn) { dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = this.RowHeadersVisible ? DataGridViewAdvancedCellBorderStyle.None : DataGridViewAdvancedCellBorderStyle.OutsetDouble; } else { dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.None; } dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.None; } dataGridViewAdvancedBorderStylePlaceholder.TopInternal = DataGridViewAdvancedCellBorderStyle.OutsetDouble; dataGridViewAdvancedBorderStylePlaceholder.BottomInternal = DataGridViewAdvancedCellBorderStyle.Outset; return dataGridViewAdvancedBorderStylePlaceholder; case DataGridViewAdvancedCellBorderStyle.InsetDouble: if (this.RightToLeftInternal) { dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.None; if (isFirstDisplayedColumn) { dataGridViewAdvancedBorderStylePlaceholder.RightInternal = this.RowHeadersVisible ? DataGridViewAdvancedCellBorderStyle.None : DataGridViewAdvancedCellBorderStyle.Inset; } else { dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.None; } } else { if (isFirstDisplayedColumn) { dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = this.RowHeadersVisible ? DataGridViewAdvancedCellBorderStyle.None : DataGridViewAdvancedCellBorderStyle.InsetDouble; } else { dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.None; } dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.None; } dataGridViewAdvancedBorderStylePlaceholder.TopInternal = DataGridViewAdvancedCellBorderStyle.InsetDouble; dataGridViewAdvancedBorderStylePlaceholder.BottomInternal = DataGridViewAdvancedCellBorderStyle.Inset; return dataGridViewAdvancedBorderStylePlaceholder; case DataGridViewAdvancedCellBorderStyle.Single: case DataGridViewAdvancedCellBorderStyle.Outset: case DataGridViewAdvancedCellBorderStyle.Inset: if (!isFirstDisplayedColumn || this.RowHeadersVisible) { dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.None; dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.None; dataGridViewAdvancedBorderStylePlaceholder.TopInternal = dataGridViewAdvancedBorderStyleInput.All; dataGridViewAdvancedBorderStylePlaceholder.BottomInternal = dataGridViewAdvancedBorderStyleInput.All; return dataGridViewAdvancedBorderStylePlaceholder; } else { // isFirstDisplayedColumn == true && this.RowHeadersVisible == false if (this.RightToLeftInternal) { dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.None; dataGridViewAdvancedBorderStylePlaceholder.RightInternal = dataGridViewAdvancedBorderStyleInput.All; } else { dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = dataGridViewAdvancedBorderStyleInput.All; dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.None; } dataGridViewAdvancedBorderStylePlaceholder.TopInternal = dataGridViewAdvancedBorderStyleInput.All; dataGridViewAdvancedBorderStylePlaceholder.BottomInternal = dataGridViewAdvancedBorderStyleInput.All; return dataGridViewAdvancedBorderStylePlaceholder; } } } else { switch (dataGridViewAdvancedBorderStyleInput.All) { case DataGridViewAdvancedCellBorderStyle.OutsetPartial: if (this.RightToLeftInternal) { dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = isLastVisibleColumn ? DataGridViewAdvancedCellBorderStyle.Outset : DataGridViewAdvancedCellBorderStyle.OutsetPartial; if (isFirstDisplayedColumn) { dataGridViewAdvancedBorderStylePlaceholder.RightInternal = this.RowHeadersVisible ? DataGridViewAdvancedCellBorderStyle.Outset : DataGridViewAdvancedCellBorderStyle.OutsetDouble; } else { dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.OutsetPartial; } } else { if (isFirstDisplayedColumn) { dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = this.RowHeadersVisible ? DataGridViewAdvancedCellBorderStyle.Outset : DataGridViewAdvancedCellBorderStyle.OutsetDouble; } else { dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.OutsetPartial; } dataGridViewAdvancedBorderStylePlaceholder.RightInternal = isLastVisibleColumn ? DataGridViewAdvancedCellBorderStyle.Outset : DataGridViewAdvancedCellBorderStyle.OutsetPartial; } dataGridViewAdvancedBorderStylePlaceholder.TopInternal = DataGridViewAdvancedCellBorderStyle.OutsetDouble; dataGridViewAdvancedBorderStylePlaceholder.BottomInternal = DataGridViewAdvancedCellBorderStyle.Outset; return dataGridViewAdvancedBorderStylePlaceholder; case DataGridViewAdvancedCellBorderStyle.OutsetDouble: if (this.RightToLeftInternal) { dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.Outset; if (isFirstDisplayedColumn) { dataGridViewAdvancedBorderStylePlaceholder.RightInternal = this.RowHeadersVisible ? DataGridViewAdvancedCellBorderStyle.Outset : DataGridViewAdvancedCellBorderStyle.OutsetDouble; } else { dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.Outset; } } else { if (isFirstDisplayedColumn) { dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = this.RowHeadersVisible ? DataGridViewAdvancedCellBorderStyle.Outset : DataGridViewAdvancedCellBorderStyle.OutsetDouble; } else { dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.Outset; } dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.Outset; } dataGridViewAdvancedBorderStylePlaceholder.TopInternal = DataGridViewAdvancedCellBorderStyle.OutsetDouble; dataGridViewAdvancedBorderStylePlaceholder.BottomInternal = DataGridViewAdvancedCellBorderStyle.Outset; return dataGridViewAdvancedBorderStylePlaceholder; case DataGridViewAdvancedCellBorderStyle.InsetDouble: if (this.RightToLeftInternal) { dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.Inset; if (isFirstDisplayedColumn) { dataGridViewAdvancedBorderStylePlaceholder.RightInternal = this.RowHeadersVisible ? DataGridViewAdvancedCellBorderStyle.Inset : DataGridViewAdvancedCellBorderStyle.InsetDouble; } else { dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.Inset; } } else { if (isFirstDisplayedColumn) { dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = this.RowHeadersVisible ? DataGridViewAdvancedCellBorderStyle.Inset : DataGridViewAdvancedCellBorderStyle.InsetDouble; } else { dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.Inset; } dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.Inset; } dataGridViewAdvancedBorderStylePlaceholder.TopInternal = DataGridViewAdvancedCellBorderStyle.InsetDouble; dataGridViewAdvancedBorderStylePlaceholder.BottomInternal = DataGridViewAdvancedCellBorderStyle.Inset; return dataGridViewAdvancedBorderStylePlaceholder; case DataGridViewAdvancedCellBorderStyle.Single: if (!isFirstDisplayedColumn || this.RowHeadersVisible) { if (this.RightToLeftInternal) { dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.Single; dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.None; } else { dataGridViewAdvancedBorderStylePlaceholder.LeftInternal = DataGridViewAdvancedCellBorderStyle.None; dataGridViewAdvancedBorderStylePlaceholder.RightInternal = DataGridViewAdvancedCellBorderStyle.Single; } dataGridViewAdvancedBorderStylePlaceholder.TopInternal = DataGridViewAdvancedCellBorderStyle.Single; dataGridViewAdvancedBorderStylePlaceholder.BottomInternal = DataGridViewAdvancedCellBorderStyle.Single; return dataGridViewAdvancedBorderStylePlaceholder; } break; } } return dataGridViewAdvancedBorderStyleInput; } private bool AdjustExpandingColumn(DataGridViewColumn dataGridViewColumn, int rowIndex) { Debug.Assert(dataGridViewColumn != null); Debug.Assert(rowIndex > -1); Debug.Assert(rowIndex < this.Rows.Count); if (!this.IsHandleCreated) { // auto sizing causes handle creation. // don't create the handle inside InitializeComponent because that causes problems w/ data binding this.dataGridViewState2[DATAGRIDVIEWSTATE2_autoSizedWithoutHandle] = true; return false; } bool ret = false; // No autosizing occurs by default. try { this.noAutoSizeCount++; DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex); int preferredThickness = dataGridViewRow.Cells[dataGridViewColumn.Index].GetPreferredWidth(rowIndex, dataGridViewRow.GetHeight(rowIndex)); if (preferredThickness > DataGridViewBand.maxBandThickness) { preferredThickness = DataGridViewBand.maxBandThickness; } if (dataGridViewColumn.Width < preferredThickness) { // Column needs to be expanded dataGridViewColumn.ThicknessInternal = preferredThickness; ret = true; } } finally { Debug.Assert(this.noAutoSizeCount > 0); this.noAutoSizeCount--; } return ret; } private bool AdjustExpandingColumns(DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFilter, int rowIndex) { Debug.Assert(autoSizeColumnCriteriaFilter != DataGridViewAutoSizeColumnCriteriaInternal.None); Debug.Assert((autoSizeColumnCriteriaFilter & DataGridViewAutoSizeColumnCriteriaInternal.Fill) == 0); bool ret = false; // No column autosizes by default DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); while (dataGridViewColumn != null) { DataGridViewAutoSizeColumnCriteriaInternal inheritedAutoSizeColumnCriteria = (DataGridViewAutoSizeColumnCriteriaInternal)dataGridViewColumn.InheritedAutoSizeMode; DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFiltered = (inheritedAutoSizeColumnCriteria & autoSizeColumnCriteriaFilter); if (autoSizeColumnCriteriaFiltered != 0) { ret |= AdjustExpandingColumn(dataGridViewColumn, rowIndex); } dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); } return ret; } private int AdjustExpandingRow(int rowIndex, int columnIndex, bool fixedWidth) { Debug.Assert(columnIndex >= -1 && columnIndex < this.Columns.Count); Debug.Assert(rowIndex >= 0 && rowIndex < this.Rows.Count); Debug.Assert(this.autoSizeRowsMode == DataGridViewAutoSizeRowsMode.DisplayedHeaders || this.autoSizeRowsMode == DataGridViewAutoSizeRowsMode.DisplayedCellsExceptHeaders || this.autoSizeRowsMode == DataGridViewAutoSizeRowsMode.DisplayedCells); // Use of WindowsFormsUtils.CreateMeasurementGraphics() avoid use of this.Handle // IntPtr handle = this.Handle; // Force creation of control's handle because for databound grids, handle creation wipes out and recreates the columns/rows. int width = 0; DataGridViewCell dataGridViewCell; if (columnIndex > -1 && (((DataGridViewAutoSizeRowsModeInternal) autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0) { dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex]; if (fixedWidth) { width = this.Columns[columnIndex].Thickness; } } else { Debug.Assert(columnIndex == -1); Debug.Assert((((DataGridViewAutoSizeRowsModeInternal) autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.Header) != 0); dataGridViewCell = this.Rows.SharedRow(rowIndex).HeaderCell; if (fixedWidth) { Debug.Assert(this.RowHeadersWidth > 0); Debug.Assert(this.RowHeadersVisible); width = this.RowHeadersWidth; } } int preferredThickness; if (fixedWidth) { preferredThickness = dataGridViewCell.GetPreferredHeight(rowIndex, width); } else { preferredThickness = dataGridViewCell.GetPreferredSize(rowIndex).Height; } int height, minimumHeight; this.Rows.SharedRow(rowIndex).GetHeightInfo(rowIndex, out height, out minimumHeight); if (preferredThickness < height) { preferredThickness = height; } Debug.Assert(preferredThickness >= minimumHeight); if (preferredThickness > DataGridViewBand.maxBandThickness) { preferredThickness = DataGridViewBand.maxBandThickness; } if (height != preferredThickness) { Debug.Assert(this.autoSizeRowsMode != DataGridViewAutoSizeRowsMode.None); this.Rows[rowIndex].Thickness = preferredThickness; // unsharing the resized row } return preferredThickness; } [SuppressMessage("Microsoft.Performance", "CA1817:DoNotCallPropertiesThatCloneValuesInLoops")] // Can't cache DataGridViewRow object because rowIndex is changing in loop. private void AdjustExpandingRows(int columnIndex, bool fixedWidth) { if ((((DataGridViewAutoSizeRowsModeInternal) this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0 || ((((DataGridViewAutoSizeRowsModeInternal) this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.Header) != 0 && this.RowHeadersVisible)) { if (!this.IsHandleCreated) { // auto sizing causes handle creation. // don't create the handle inside InitializeComponent because that causes problems w/ data binding this.dataGridViewState2[DATAGRIDVIEWSTATE2_autoSizedWithoutHandle] = true; return; } // Very expensive processing - the developer should avoid this scenario. // Switch to batch operation this.inBulkPaintCount++; try { if ((((DataGridViewAutoSizeRowsModeInternal) this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllRows) != 0) { this.inBulkLayoutCount++; try { for (int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); rowIndex != -1; rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible)) { int width = 0; DataGridViewCell dataGridViewCell; if (columnIndex > -1 && (((DataGridViewAutoSizeRowsModeInternal) this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0) { dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex]; if (fixedWidth) { width = this.Columns[columnIndex].Thickness; } } else { //Debug.Assert(columnIndex == -1); Debug.Assert((((DataGridViewAutoSizeRowsModeInternal) this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.Header) != 0); dataGridViewCell = this.Rows.SharedRow(rowIndex).HeaderCell; if (fixedWidth) { Debug.Assert(this.RowHeadersWidth > 0); Debug.Assert(this.RowHeadersVisible); width = this.RowHeadersWidth; } } int preferredHeight; if (fixedWidth) { preferredHeight = dataGridViewCell.GetPreferredHeight(rowIndex, width); } else { preferredHeight = dataGridViewCell.GetPreferredSize(rowIndex).Height; } if (this.Rows.SharedRow(rowIndex).Height < preferredHeight) { this.Rows[rowIndex].Height = preferredHeight; // unsharing the row to be resized } } } finally { ExitBulkLayout(false /*invalidInAdjustFillingColumns*/); } } else { Debug.Assert((((DataGridViewAutoSizeRowsModeInternal) this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.DisplayedRows) != 0); int displayHeight = this.layout.Data.Height; int cy = 0; int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); while (rowIndex != -1 && cy < displayHeight) { cy += AdjustExpandingRow(rowIndex, columnIndex, fixedWidth); rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); } if (cy < displayHeight) { rowIndex = this.displayedBandsInfo.FirstDisplayedScrollingRow; while (rowIndex != -1 && cy < displayHeight) { cy += AdjustExpandingRow(rowIndex, columnIndex, fixedWidth); rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible); } } } } finally { ExitBulkPaint(-1, -1); } } } internal void AdjustFillingColumn(DataGridViewColumn dataGridViewColumn, int width) { if (this.InAdjustFillingColumns) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAlterAutoFillColumnParameter)); } this.dataGridViewOper[DATAGRIDVIEWOPER_inAdjustFillingColumn] = true; try { Debug.Assert(dataGridViewColumn != null); Debug.Assert(dataGridViewColumn.Visible); Debug.Assert(!dataGridViewColumn.Frozen); Debug.Assert(dataGridViewColumn.MinimumWidth <= width); Debug.Assert(dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill); Debug.Assert(!this.layout.dirty); if (this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible) > this.layout.Data.Width) { // Columns are scrolling - this means that all columns have reached their minimum width. // Do not affect their width or fill weight Debug.Assert(dataGridViewColumn.MinimumWidth == dataGridViewColumn.Width); return; } int availableWidth = this.layout.Data.Width; // Width available for auto-filled columns // Check if the column is the first or last visible scrolling column if (this.DesignMode || dataGridViewColumn == this.Columns.GetFirstColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen) || dataGridViewColumn == this.Columns.GetLastColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen)) { // Changing the width is equivalent to adjusting the FillWeight when: // - the column is not scrolling and is the first non-frozen visible column // - the column is not scrolling and is the last non-frozen visible column float weightSum = 0; // Weights of all auto filled visible columns. int widthSum = 0; // Sum of widths of visible auto filled columns. int imposedWidthSum = 0; // Minimum width required for all other columns. bool otherFillingColumnExists = false; foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns) { if (dataGridViewColumnTmp.Visible) { if (dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill) { Debug.Assert(!dataGridViewColumnTmp.Frozen); widthSum += dataGridViewColumnTmp.Width; if (dataGridViewColumnTmp.Index != dataGridViewColumn.Index) { imposedWidthSum += dataGridViewColumnTmp.MinimumWidth; otherFillingColumnExists = true; } weightSum += dataGridViewColumnTmp.FillWeight; } else { imposedWidthSum += dataGridViewColumnTmp.Width; availableWidth -= dataGridViewColumnTmp.Width; } } } if (!otherFillingColumnExists) { // The resized column is the only one that is filling. This is a no-op operation. // Neither the width nor the fill weight can change return; } int maximumPossibleWidth = this.layout.Data.Width - imposedWidthSum; if (width > maximumPossibleWidth) { width = maximumPossibleWidth; } // Determine fill weight equivalent to 'width' float oldWeight = dataGridViewColumn.FillWeight; float newWeight = (float)(width * weightSum) / (float)widthSum; bool desiredWidthTooSmall = false; foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns) { if (dataGridViewColumnTmp.Index != dataGridViewColumn.Index && dataGridViewColumnTmp.Visible && dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill) { dataGridViewColumnTmp.FillWeightInternal = (weightSum - newWeight) * dataGridViewColumnTmp.FillWeight / (weightSum - oldWeight); if (dataGridViewColumnTmp.FillWeight < (dataGridViewColumnTmp.MinimumWidth * weightSum) / (float)widthSum) { desiredWidthTooSmall = true; dataGridViewColumnTmp.DesiredFillWidth = -1; } else { dataGridViewColumnTmp.DesiredFillWidth = 0; } } } dataGridViewColumn.FillWeightInternal = newWeight; if (desiredWidthTooSmall) { // At least one column hits its minimum width // Adjust UsedFillWeight values are adjusted FillWeight values float usedWeightSumNoneMinimal = weightSum; float weightSumNoneMinimal = weightSum; float usedFillWeights = 0F; foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns) { if (dataGridViewColumnTmp.Visible && dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill) { if (dataGridViewColumnTmp.Index == dataGridViewColumn.Index) { dataGridViewColumnTmp.UsedFillWeight = dataGridViewColumnTmp.FillWeight; usedWeightSumNoneMinimal -= dataGridViewColumnTmp.UsedFillWeight; weightSumNoneMinimal -= dataGridViewColumnTmp.FillWeight; usedFillWeights += dataGridViewColumnTmp.UsedFillWeight; } else if (dataGridViewColumnTmp.DesiredFillWidth == -1) { dataGridViewColumnTmp.UsedFillWeight = weightSum * dataGridViewColumnTmp.MinimumWidth / widthSum; usedWeightSumNoneMinimal -= dataGridViewColumnTmp.UsedFillWeight; weightSumNoneMinimal -= dataGridViewColumnTmp.FillWeight; usedFillWeights += dataGridViewColumnTmp.UsedFillWeight; } } } foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns) { if (dataGridViewColumnTmp.Index != dataGridViewColumn.Index && dataGridViewColumnTmp.Visible && dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill && dataGridViewColumnTmp.DesiredFillWidth != -1) { dataGridViewColumnTmp.UsedFillWeight = Math.Max(dataGridViewColumnTmp.FillWeight * usedWeightSumNoneMinimal / weightSumNoneMinimal, weightSum * dataGridViewColumnTmp.MinimumWidth / widthSum); usedFillWeights += dataGridViewColumnTmp.UsedFillWeight; } } dataGridViewColumn.UsedFillWeight += weightSum - usedFillWeights; } else { // No column hits its minimum width // Each UsedFillWeight simply equals the FillWeight foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns) { if (dataGridViewColumnTmp.Visible && dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill) { dataGridViewColumnTmp.UsedFillWeight = dataGridViewColumnTmp.FillWeight; } } } #if DEBUG float weightSumDbg = 0F; foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns) { if (dataGridViewColumnTmp.Visible && dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill) { weightSumDbg += dataGridViewColumnTmp.UsedFillWeight; } } Debug.Assert(Math.Abs(weightSum - weightSumDbg) < 1.0F); #endif } else { // This column is not the first nor the last visible non-frozen column // Changing its width only affects the width and weight of the columns displayed after it // First figure out the maximum possible width int imposedWidthSum = 0; // Minimum width required for all other columns float weightSum = 0; // Weights of all auto filled visible columns. float oldWeightSum = 0F; // Fill weights of the columns displayed after this resized column bool otherFillingColumnExists = false; foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns) { if (dataGridViewColumnTmp.Visible) { if (dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill) { Debug.Assert(!dataGridViewColumnTmp.Frozen); if (dataGridViewColumnTmp.Index != dataGridViewColumn.Index) { if (this.Columns.DisplayInOrder(dataGridViewColumn.Index, dataGridViewColumnTmp.Index)) { imposedWidthSum += dataGridViewColumnTmp.MinimumWidth; // Column is allowed to shrink down to its minimum oldWeightSum += dataGridViewColumnTmp.FillWeight; } else { // Column is displayed before 'dataGridViewColumn', it is not allowed to shrink at all imposedWidthSum += dataGridViewColumnTmp.Width; } otherFillingColumnExists = true; } weightSum += dataGridViewColumnTmp.FillWeight; } else { imposedWidthSum += dataGridViewColumnTmp.Width; availableWidth -= dataGridViewColumnTmp.Width; } } } if (!otherFillingColumnExists) { // The resized column is the only one that is filling. This is a no-op operation. // Neither the width nor the fill weight can change return; } int maximumPossibleWidth = this.layout.Data.Width - imposedWidthSum; if (width > maximumPossibleWidth) { width = maximumPossibleWidth; } // Then figure out the target fill weights float oldWeight = dataGridViewColumn.FillWeight; float newWeight = weightSum * width / availableWidth; float newWeightSum = oldWeightSum + oldWeight - newWeight; Debug.Assert(newWeightSum > 0); foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns) { if (dataGridViewColumnTmp.Index != dataGridViewColumn.Index && dataGridViewColumnTmp.Visible && dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill && this.Columns.DisplayInOrder(dataGridViewColumn.Index, dataGridViewColumnTmp.Index)) { dataGridViewColumnTmp.FillWeightInternal = dataGridViewColumnTmp.FillWeight * newWeightSum / oldWeightSum; } } dataGridViewColumn.FillWeightInternal = newWeight; bool desiredWidthTooSmall = false; foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns) { if (dataGridViewColumnTmp.Visible && dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill) { if (dataGridViewColumnTmp.FillWeight < (dataGridViewColumnTmp.MinimumWidth * weightSum) / (float)availableWidth) { desiredWidthTooSmall = true; dataGridViewColumnTmp.DesiredFillWidth = -1; } else { dataGridViewColumnTmp.DesiredFillWidth = 0; } } } if (desiredWidthTooSmall) { // At least one column hits its minimum width // Adjust UsedFillWeight values are adjusted FillWeight values float usedWeightSumNoneMinimal = weightSum; float weightSumNoneMinimal = weightSum; float usedFillWeights = 0F; foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns) { if (dataGridViewColumnTmp.Visible && dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill) { if (dataGridViewColumnTmp.Index == dataGridViewColumn.Index || this.Columns.DisplayInOrder(dataGridViewColumnTmp.Index, dataGridViewColumn.Index)) { if (dataGridViewColumnTmp.Index == dataGridViewColumn.Index) { dataGridViewColumnTmp.UsedFillWeight = dataGridViewColumnTmp.FillWeight; } else { dataGridViewColumnTmp.UsedFillWeight = weightSum * dataGridViewColumnTmp.Width / availableWidth; } usedWeightSumNoneMinimal -= dataGridViewColumnTmp.UsedFillWeight; weightSumNoneMinimal -= dataGridViewColumnTmp.FillWeight; usedFillWeights += dataGridViewColumnTmp.UsedFillWeight; } else if (dataGridViewColumnTmp.DesiredFillWidth == -1) { dataGridViewColumnTmp.UsedFillWeight = weightSum * dataGridViewColumnTmp.MinimumWidth / availableWidth; usedWeightSumNoneMinimal -= dataGridViewColumnTmp.UsedFillWeight; weightSumNoneMinimal -= dataGridViewColumnTmp.FillWeight; usedFillWeights += dataGridViewColumnTmp.UsedFillWeight; } } } foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns) { if (this.Columns.DisplayInOrder(dataGridViewColumn.Index, dataGridViewColumnTmp.Index) && dataGridViewColumnTmp.Visible && dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill && dataGridViewColumnTmp.DesiredFillWidth != -1) { dataGridViewColumnTmp.UsedFillWeight = Math.Max(dataGridViewColumnTmp.FillWeight * usedWeightSumNoneMinimal / weightSumNoneMinimal, weightSum * dataGridViewColumnTmp.MinimumWidth / availableWidth); usedFillWeights += dataGridViewColumnTmp.UsedFillWeight; } } dataGridViewColumn.UsedFillWeight += weightSum - usedFillWeights; } else { // No column hits its minimum width // Each UsedFillWeight simply equals the FillWeight foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns) { if (dataGridViewColumnTmp.Visible && dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill) { dataGridViewColumnTmp.UsedFillWeight = dataGridViewColumnTmp.FillWeight; } } } #if DEBUG float weightSumDbg = 0F; foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns) { if (dataGridViewColumnTmp.Visible && dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill) { weightSumDbg += dataGridViewColumnTmp.UsedFillWeight; } } Debug.Assert(Math.Abs(weightSum - weightSumDbg) < 1.0F); #endif } // UsedFillWeight properties are up-to-date this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = false; this.availableWidthForFillColumns = availableWidth; // AdjustFillingColumns() will resize columns based on the UsedFillWeight values PerformLayoutPrivate(false /*useRowShortcut*/, true /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); } finally { this.dataGridViewOper[DATAGRIDVIEWOPER_inAdjustFillingColumn] = false; } } private bool AdjustFillingColumns() { if (this.dataGridViewOper[DATAGRIDVIEWOPER_inAdjustFillingColumns]) { // No need to auto fill columns while we're already doing it. return false; } this.dataGridViewOper[DATAGRIDVIEWOPER_inAdjustFillingColumns] = true; bool columnsAdjusted = false; try { // Determine free space for filling columns. int numVisibleFillColumns = 0; // number of visible columns that are auto filled. int imposedWidthSum = 0; // total width of columns that don't have a flexible width. int requiredWidthSum = 0; // total of the minimum widths of the visible auto filled columns. float weightSum = 0F; // total of the weights of the visible auto filled columns. ArrayList autoFillColumns = null; foreach (DataGridViewColumn dataGridViewColumn in this.Columns) { if (dataGridViewColumn.Visible) { if (dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill) { Debug.Assert(!dataGridViewColumn.Frozen); numVisibleFillColumns++; requiredWidthSum += dataGridViewColumn.DesiredMinimumWidth > 0 ? dataGridViewColumn.DesiredMinimumWidth : dataGridViewColumn.MinimumWidth; weightSum += dataGridViewColumn.FillWeight; if (autoFillColumns == null) { autoFillColumns = new ArrayList(this.Columns.Count); } autoFillColumns.Add(dataGridViewColumn); } else { imposedWidthSum += dataGridViewColumn.Width; } } } if (numVisibleFillColumns > 0) { // Assuming no vertical scrollbar has been accounted for yet Debug.Assert(this.layout.Data.Width == this.layout.Inside.Width - this.layout.RowHeaders.Width - (this.SingleVerticalBorderAdded ? 1 : 0)); int availableWidth = this.layout.Data.Width - imposedWidthSum; if ((this.scrollBars == ScrollBars.Both || this.scrollBars == ScrollBars.Vertical) /*&& (availableWidth > requiredWidthSum || this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty])*/) { int totalVisibleRowCount = this.Rows.GetRowCount(DataGridViewElementStates.Visible); int totalVisibleHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible); int totalVisibleFrozenHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); // Assuming there is no horizontal scrollbar, is a vertical scrollbar required? ComputeVisibleRows(); // Make sure this.displayedBandsInfo.FirstDisplayedScrollingRow and other row count info variables have been set if (this.displayedBandsInfo.NumTotallyDisplayedFrozenRows == this.Rows.GetRowCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen) && this.displayedBandsInfo.NumTotallyDisplayedScrollingRows != totalVisibleRowCount - this.Rows.GetRowCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen) && (totalVisibleHeight - totalVisibleFrozenHeight != ComputeHeightOfFittingTrailingScrollingRows(totalVisibleFrozenHeight)) && this.layout.Data.Height > totalVisibleFrozenHeight && SystemInformation.VerticalScrollBarWidth <= this.layout.Data.Width) { // Vertical scrollbar is required, even when there is not horizontal one. availableWidth -= SystemInformation.VerticalScrollBarWidth; } } int columnEntry; if (availableWidth <= requiredWidthSum) { // All auto filled columns need to take their minimum width. If (availableWidth < requiredWidthSum) a horizontal scrollbar appears. availableWidth = 0; for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++) { DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry]; int minimumWidth = dataGridViewColumn.DesiredMinimumWidth > 0 ? dataGridViewColumn.DesiredMinimumWidth : dataGridViewColumn.MinimumWidth; if (dataGridViewColumn.Thickness != minimumWidth) { columnsAdjusted = true; dataGridViewColumn.ThicknessInternal = minimumWidth; } availableWidth += dataGridViewColumn.Thickness; } //if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty]) { for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++) { // Make sure the UsedFillWeight correspond to the actual column width DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry]; dataGridViewColumn.UsedFillWeight = dataGridViewColumn.Width * weightSum / availableWidth; } this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = false; this.availableWidthForFillColumns = availableWidth; } return columnsAdjusted; } // Auto filling columns can share some real estate. int usedWidth = 0; // Update the UsedFillWeight value if dirty if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty]) { // Assign desired widths Debug.Assert(weightSum > 0); bool desiredWidthTooSmall = false; for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++) { DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry]; if (columnEntry == autoFillColumns.Count - 1) { dataGridViewColumn.DesiredFillWidth = availableWidth - usedWidth; } else { float desiredFillWidth = (dataGridViewColumn.FillWeight / weightSum) * availableWidth; dataGridViewColumn.DesiredFillWidth = (int)Math.Round(desiredFillWidth, MidpointRounding.AwayFromZero); usedWidth += dataGridViewColumn.DesiredFillWidth; } int minimumWidth = dataGridViewColumn.DesiredMinimumWidth > 0 ? dataGridViewColumn.DesiredMinimumWidth : dataGridViewColumn.MinimumWidth; if (dataGridViewColumn.DesiredFillWidth < minimumWidth) { desiredWidthTooSmall = true; dataGridViewColumn.DesiredFillWidth = -1; } } if (desiredWidthTooSmall) { // At least one column hits its minimum width // Adjust UsedFillWeight values are adjusted FillWeight values float usedWeightSumNoneMinimal = weightSum; float weightSumNoneMinimal = weightSum; for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++) { DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry]; if (dataGridViewColumn.DesiredFillWidth == -1) { int minimumWidth = dataGridViewColumn.DesiredMinimumWidth > 0 ? dataGridViewColumn.DesiredMinimumWidth : dataGridViewColumn.MinimumWidth; dataGridViewColumn.UsedFillWeight = weightSum * minimumWidth / availableWidth; usedWeightSumNoneMinimal -= dataGridViewColumn.UsedFillWeight; weightSumNoneMinimal -= dataGridViewColumn.FillWeight; } } for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++) { DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry]; if (dataGridViewColumn.DesiredFillWidth != -1) { dataGridViewColumn.UsedFillWeight = dataGridViewColumn.FillWeight * usedWeightSumNoneMinimal / weightSumNoneMinimal; } } } else { // No column hits its minimum width // Each UsedFillWeight simply equals the FillWeight for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++) { DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry]; dataGridViewColumn.UsedFillWeight = dataGridViewColumn.FillWeight; } } this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = false; this.availableWidthForFillColumns = availableWidth; } else if (availableWidth != this.availableWidthForFillColumns) { // The available width for auto-filled columns has changed - UsedFillWeight values need to be adjusted. if (availableWidth > this.availableWidthForFillColumns) { // Available width increased int widthGain = availableWidth - this.availableWidthForFillColumns; // Allocate additional width according to UsedFillWeight and FillWeight values for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++) { DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry]; dataGridViewColumn.DesiredFillWidth = dataGridViewColumn.Width; } float[] floatDesiredWidths = new float[autoFillColumns.Count]; for (int gain = 0; gain < widthGain; gain++) { float fillWeightRatioSum = 0F; bool minimumColumnExists = false; for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++) { DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry]; fillWeightRatioSum += dataGridViewColumn.FillWeight / dataGridViewColumn.UsedFillWeight; if (dataGridViewColumn.DesiredFillWidth <= dataGridViewColumn.MinimumWidth) { minimumColumnExists = true; } } for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++) { DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry]; if (gain == 0) { floatDesiredWidths[columnEntry] = this.availableWidthForFillColumns * dataGridViewColumn.UsedFillWeight / weightSum; } if (minimumColumnExists) { floatDesiredWidths[columnEntry] += dataGridViewColumn.FillWeight / dataGridViewColumn.UsedFillWeight / fillWeightRatioSum; } else { floatDesiredWidths[columnEntry] += dataGridViewColumn.FillWeight / weightSum; } } } for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++) { DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry]; dataGridViewColumn.UsedFillWeight = weightSum / availableWidth * floatDesiredWidths[columnEntry]; } } else { // availableWidth < this.availableWidthForFillColumns - Available width decreased int totalWidthLoss = this.availableWidthForFillColumns - availableWidth; int cumulatedWidthLoss = 0; for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++) { DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry]; dataGridViewColumn.DesiredFillWidth = dataGridViewColumn.Width; } // the width loss is accounted for in steps of 10% (see VSWhidbey 568343) do { int stepDownAvailableWidthForFillColumns = this.availableWidthForFillColumns - cumulatedWidthLoss; int widthLoss = Math.Min(stepDownAvailableWidthForFillColumns - availableWidth, Math.Max(1, (int)(stepDownAvailableWidthForFillColumns * 0.1F))); cumulatedWidthLoss += widthLoss; bool changeDone; do { changeDone = false; // Determine which column deserves to shrink the most float biggestWeightDeficiency = 0F, fillWeightRatioSum = 0F, fillWeightRatio; DataGridViewColumn mostDeservingDataGridViewColumn = null; for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++) { DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry]; if (dataGridViewColumn.DesiredFillWidth > dataGridViewColumn.MinimumWidth) { fillWeightRatio = dataGridViewColumn.UsedFillWeight / dataGridViewColumn.FillWeight; fillWeightRatioSum += fillWeightRatio; if (fillWeightRatio > biggestWeightDeficiency) { mostDeservingDataGridViewColumn = dataGridViewColumn; biggestWeightDeficiency = fillWeightRatio; } } } if (mostDeservingDataGridViewColumn != null) { float floatDesiredWidth = (stepDownAvailableWidthForFillColumns * mostDeservingDataGridViewColumn.UsedFillWeight / weightSum) - widthLoss * mostDeservingDataGridViewColumn.UsedFillWeight / mostDeservingDataGridViewColumn.FillWeight / fillWeightRatioSum; if (floatDesiredWidth < (float)mostDeservingDataGridViewColumn.MinimumWidth) { floatDesiredWidth = (int)mostDeservingDataGridViewColumn.MinimumWidth; } int oldDesiredWidth = mostDeservingDataGridViewColumn.DesiredFillWidth; mostDeservingDataGridViewColumn.DesiredFillWidth = Math.Min(oldDesiredWidth, (int)Math.Round(floatDesiredWidth, MidpointRounding.AwayFromZero)); changeDone = (oldDesiredWidth != mostDeservingDataGridViewColumn.DesiredFillWidth); if (!changeDone && widthLoss == 1 && oldDesiredWidth > mostDeservingDataGridViewColumn.MinimumWidth) { mostDeservingDataGridViewColumn.DesiredFillWidth--; changeDone = true; } Debug.Assert(oldDesiredWidth >= mostDeservingDataGridViewColumn.DesiredFillWidth); widthLoss -= oldDesiredWidth - mostDeservingDataGridViewColumn.DesiredFillWidth; if (changeDone) { stepDownAvailableWidthForFillColumns -= oldDesiredWidth - mostDeservingDataGridViewColumn.DesiredFillWidth; for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++) { DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry]; dataGridViewColumn.UsedFillWeight = weightSum / stepDownAvailableWidthForFillColumns * dataGridViewColumn.DesiredFillWidth; } } Debug.Assert(widthLoss >= 0); } } while (changeDone && widthLoss > 0); } while (cumulatedWidthLoss < totalWidthLoss); } this.availableWidthForFillColumns = availableWidth; } #if DEBUG float weightSumDbg = 0F; for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++) { DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry]; weightSumDbg += dataGridViewColumn.UsedFillWeight; } Debug.Assert(Math.Abs(weightSum - weightSumDbg) < 1.0F); #endif // Finally update the columns' width according the UsedFillWeight values. try { this.dataGridViewState2[DATAGRIDVIEWSTATE2_allowHorizontalScrollbar] = false; usedWidth = 0; float carryover = 0F; while (autoFillColumns.Count > 0) { DataGridViewColumn mostDeservingDataGridViewColumn = null; if (autoFillColumns.Count == 1) { mostDeservingDataGridViewColumn = (DataGridViewColumn)autoFillColumns[0]; mostDeservingDataGridViewColumn.DesiredFillWidth = Math.Max(availableWidth - usedWidth, mostDeservingDataGridViewColumn.MinimumWidth); autoFillColumns.Clear(); } else { float biggestWeightDiscrepancy = 0F, weightDiscrepancy; for (columnEntry = 0; columnEntry < autoFillColumns.Count; columnEntry++) { DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)autoFillColumns[columnEntry]; weightDiscrepancy = Math.Abs(dataGridViewColumn.UsedFillWeight - dataGridViewColumn.FillWeight) / dataGridViewColumn.FillWeight; if (weightDiscrepancy > biggestWeightDiscrepancy || mostDeservingDataGridViewColumn == null) { mostDeservingDataGridViewColumn = dataGridViewColumn; biggestWeightDiscrepancy = weightDiscrepancy; } } float floatDesiredWidth = (mostDeservingDataGridViewColumn.UsedFillWeight * availableWidth / weightSum) + carryover; mostDeservingDataGridViewColumn.DesiredFillWidth = Math.Max(mostDeservingDataGridViewColumn.MinimumWidth, (int)Math.Round(floatDesiredWidth, MidpointRounding.AwayFromZero)); carryover = floatDesiredWidth - mostDeservingDataGridViewColumn.DesiredFillWidth; usedWidth += mostDeservingDataGridViewColumn.DesiredFillWidth; autoFillColumns.Remove(mostDeservingDataGridViewColumn); } if (mostDeservingDataGridViewColumn.DesiredFillWidth != mostDeservingDataGridViewColumn.Thickness) { columnsAdjusted = true; mostDeservingDataGridViewColumn.ThicknessInternal = mostDeservingDataGridViewColumn.DesiredFillWidth; } } } finally { this.dataGridViewState2[DATAGRIDVIEWSTATE2_allowHorizontalScrollbar] = true; } } #if DEBUG if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty]) { foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns) { if (dataGridViewColumnTmp.Visible && dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill) { Debug.Assert(Math.Abs(dataGridViewColumnTmp.UsedFillWeight * this.availableWidthForFillColumns - weightSum * dataGridViewColumnTmp.Width) / weightSum / dataGridViewColumnTmp.Width <= 1.25F / dataGridViewColumnTmp.Width); } } } bool nonMinColumnExists = false; int widthSum = 0; foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns) { if (dataGridViewColumnTmp.Visible && dataGridViewColumnTmp.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill) { widthSum += dataGridViewColumnTmp.Width; if (dataGridViewColumnTmp.Width > dataGridViewColumnTmp.MinimumWidth) { nonMinColumnExists = true; } } } if (nonMinColumnExists) { Debug.Assert(widthSum == this.availableWidthForFillColumns); } #endif } finally { this.dataGridViewOper[DATAGRIDVIEWOPER_inAdjustFillingColumns] = false; } return columnsAdjusted; } private void AdjustShrinkingRows(DataGridViewAutoSizeRowsMode autoSizeRowsMode, bool fixedWidth, bool internalAutosizing) { if ((((DataGridViewAutoSizeRowsModeInternal) autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0 || ((((DataGridViewAutoSizeRowsModeInternal) autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.Header) != 0 && this.RowHeadersVisible)) { // Switch to batch operation this.inBulkPaintCount++; try { if ((((DataGridViewAutoSizeRowsModeInternal) autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllRows) != 0) { // Very expensive processing - the developer should avoid this scenario. this.inBulkLayoutCount++; try { for (int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); rowIndex != -1; rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible)) { AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(autoSizeRowsMode), fixedWidth, internalAutosizing); } } finally { ExitBulkLayout(false /*invalidInAdjustFillingColumns*/); } } else { Debug.Assert((((DataGridViewAutoSizeRowsModeInternal) autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.DisplayedRows) != 0); int displayHeight = this.layout.Data.Height; int cy = 0; int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); while (rowIndex != -1 && cy < displayHeight) { AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(autoSizeRowsMode), fixedWidth, internalAutosizing); cy += this.Rows.SharedRow(rowIndex).GetHeight(rowIndex); rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); } if (cy < displayHeight) { int cyFrozen = cy; int oldFirstVisibleScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow; rowIndex = oldFirstVisibleScrollingRow; while (rowIndex != -1 && cy < displayHeight && oldFirstVisibleScrollingRow == this.displayedBandsInfo.FirstDisplayedScrollingRow) { AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(autoSizeRowsMode), fixedWidth, internalAutosizing); cy += this.Rows.SharedRow(rowIndex).GetHeight(rowIndex); rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible); } do { oldFirstVisibleScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow; if (cy < displayHeight) { int rowAboveFirstVisibleScrollingRow = this.Rows.GetPreviousRow(this.displayedBandsInfo.FirstDisplayedScrollingRow, DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); if (rowAboveFirstVisibleScrollingRow != -1) { AutoResizeRowInternal(rowAboveFirstVisibleScrollingRow, MapAutoSizeRowsModeToRowMode(autoSizeRowsMode), fixedWidth, internalAutosizing); } } cy = cyFrozen; rowIndex = this.displayedBandsInfo.FirstDisplayedScrollingRow; while (rowIndex != -1 && cy < displayHeight) { AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(autoSizeRowsMode), fixedWidth, internalAutosizing); cy += this.Rows.SharedRow(rowIndex).GetHeight(rowIndex); rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible); } } while (oldFirstVisibleScrollingRow != this.displayedBandsInfo.FirstDisplayedScrollingRow); } } } finally { ExitBulkPaint(-1, -1); } } } /// // Does not seem to be a valid fxcop violation report. Contacting fxcop team to double-check. [SuppressMessage("Microsoft.Performance", "CA1817:DoNotCallPropertiesThatCloneValuesInLoops")] public bool AreAllCellsSelected(bool includeInvisibleCells) { if (this.Columns.Count == 0 && this.Rows.Count == 0) { return true; } if (!includeInvisibleCells && (this.Rows.GetFirstRow(DataGridViewElementStates.Visible) == -1 || this.Columns.GetFirstColumn(DataGridViewElementStates.Visible) == null)) { return true; } DataGridViewRow dataGridViewRow = null; bool allCellsSelected; switch (this.SelectionMode) { case DataGridViewSelectionMode.CellSelect: { allCellsSelected = this.individualSelectedCells.Count == this.Columns.Count * this.Rows.Count; if (allCellsSelected || includeInvisibleCells) { return allCellsSelected; } else { for (int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); rowIndex != -1; rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible)) { dataGridViewRow = this.Rows[rowIndex]; // unshares this row DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); while (dataGridViewColumn != null) { if (!dataGridViewRow.Cells[dataGridViewColumn.Index].Selected) { return false; } dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); } } return true; } } case DataGridViewSelectionMode.FullColumnSelect: case DataGridViewSelectionMode.ColumnHeaderSelect: { allCellsSelected = this.selectedBandIndexes.Count * this.Rows.Count + this.individualSelectedCells.Count == this.Columns.Count * this.Rows.Count; if (allCellsSelected || includeInvisibleCells) { return allCellsSelected; } else { DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); while (dataGridViewColumn != null) { if (!this.selectedBandIndexes.Contains(dataGridViewColumn.Index)) { for (int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); rowIndex != -1; rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible)) { dataGridViewRow = this.Rows[rowIndex]; // unshares this row if (!dataGridViewRow.Cells[dataGridViewColumn.Index].Selected) { return false; } } } dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); } return true; } } case DataGridViewSelectionMode.FullRowSelect: case DataGridViewSelectionMode.RowHeaderSelect: { allCellsSelected = this.selectedBandIndexes.Count * this.Columns.Count + this.individualSelectedCells.Count == this.Columns.Count * this.Rows.Count; if (allCellsSelected || includeInvisibleCells) { return allCellsSelected; } else { for (int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); rowIndex != -1; rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible)) { Debug.Assert(this.selectedBandIndexes.Contains(rowIndex) == ((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Selected) != 0)); if ((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Selected) == 0) { dataGridViewRow = this.Rows[rowIndex]; // unshares this row DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); while (dataGridViewColumn != null) { if (!dataGridViewRow.Cells[dataGridViewColumn.Index].Selected) { return false; } dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); } } } return true; } } } Debug.Fail("DataGridView.AreAllCellsSelected - Shouldn't reach this code"); return false; } /// /// internal override void AssignParent(Control value) { if (this.toolTipControl.Activated) { this.toolTipControl.Activate(false /*activate*/); } base.AssignParent(value); } private void AutoGenerateDataBoundColumns(DataGridViewColumn[] boundColumns) { DataGridViewColumnCollection dataGridViewCols = this.Columns; DataGridViewColumn[] clonedColumns = new DataGridViewColumn[dataGridViewCols.Count]; int clonedColumnsCount = 0; int i; // 1. Clone all the columns which are currently bound and will also be bound under the new DataSource/DataMember combination. // 2. Delete all the currently bound columns. // 3. Sort the cloned columns in order of their DisplayIndex. // 4. Add the new data bound columns. Here are the rules: // a. if the cloned collection contains (possible multiple) columns with DataProperyHame == current data field, // add the first cloned column that maps to the data field. // b. other wise add the new bound column. // 5. Add the remaining cloned columns in the order of their DisplayIndex. // 1. Clone all the currently bound columns. // // We can't do 1. and 2. in the same loop because we need to save the DisplayIndex. for (i = 0; i < dataGridViewCols.Count; i++) { if (this.DataSource != null && !String.IsNullOrEmpty(dataGridViewCols[i].DataPropertyName) && !dataGridViewCols[i].IsDataBound) { MapDataGridViewColumnToDataBoundField(dataGridViewCols[i]); } if (dataGridViewCols[i].IsDataBound) { // We only clone columns which are data bound w/ the new DataSource/DataMember combination. if (this.dataConnection != null && this.dataConnection.BoundColumnIndex(dataGridViewCols[i].DataPropertyName) != -1) { clonedColumns[clonedColumnsCount] = (DataGridViewColumn) dataGridViewCols[i].Clone(); clonedColumns[clonedColumnsCount].DisplayIndex = dataGridViewCols[i].DisplayIndex; clonedColumnsCount ++; } } } i = 0; // 2. Delete all the currently bound columns. while (i < dataGridViewCols.Count) { if (dataGridViewCols[i].IsDataBound) { dataGridViewCols.RemoveAtInternal(i, true /*force*/); } else { i++; } } // 3. Sort the cloned columns in the order of their DisplayIndex. // Sort the cloned columns array by the display index. // We need to copy the cloned columns into a possibly smaller array. DataGridViewColumn[] finalClonedColumns; if (clonedColumns.Length == clonedColumnsCount) { finalClonedColumns = clonedColumns; } else { finalClonedColumns = new DataGridViewColumn[clonedColumnsCount]; Array.Copy(clonedColumns, finalClonedColumns, clonedColumnsCount); } // Sort the array. Array.Sort(finalClonedColumns, System.Windows.Forms.DataGridViewColumnCollection.ColumnCollectionOrderComparer); // 4. Add new columns for the Fields which were not data bound previously ( ie, for fields which do not have a clone ). if (boundColumns != null) { for (int j = 0; j < boundColumns.Length; j ++) { if (boundColumns[j] != null && boundColumns[j].IsBrowsableInternal) { bool addNewColumn = true; // Go thru the list of cloned columns and see if there is another column w/ the same data property name. int clonedColIndex = 0; for (; clonedColIndex < clonedColumnsCount; clonedColIndex ++) { if (finalClonedColumns[clonedColIndex] != null && String.Compare(finalClonedColumns[clonedColIndex].DataPropertyName, boundColumns[j].DataPropertyName, true /*ignoreCase*/, CultureInfo.InvariantCulture) == 0) { addNewColumn = false; break; } } if (addNewColumn) { dataGridViewCols.Add(boundColumns[j]); } else { // add the cloned column. dataGridViewCols.Add(finalClonedColumns[clonedColIndex]); MapDataGridViewColumnToDataBoundField(finalClonedColumns[clonedColIndex]); Debug.Assert(finalClonedColumns[clonedColIndex].IsDataBound); finalClonedColumns[clonedColIndex] = null; } } } } #if DEBUG else { // If there are no data bound columns then there are no cloned columns either. Debug.Assert(finalClonedColumns.Length == 0); Debug.Assert(clonedColumnsCount == 0); } #endif // DEBUG // 5. Add remaining cloned columns. if (clonedColumnsCount > 0) { for (int k = 0; k < finalClonedColumns.Length; k++) { if (finalClonedColumns[k] != null) { dataGridViewCols.Add(finalClonedColumns[k]); MapDataGridViewColumnToDataBoundField(finalClonedColumns[k]); Debug.Assert(finalClonedColumns[k].IsDataBound); } } } } private bool AutoResizeAllVisibleColumnsInternal(DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFilter, bool fixedHeight) { Debug.Assert(autoSizeColumnCriteriaFilter != DataGridViewAutoSizeColumnCriteriaInternal.None); Debug.Assert((autoSizeColumnCriteriaFilter & DataGridViewAutoSizeColumnCriteriaInternal.Fill) == 0); bool ret = false; // No column autosizes by default DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); while (dataGridViewColumn != null) { DataGridViewAutoSizeColumnCriteriaInternal inheritedAutoSizeColumnCriteria = (DataGridViewAutoSizeColumnCriteriaInternal) dataGridViewColumn.InheritedAutoSizeMode; DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFiltered = (inheritedAutoSizeColumnCriteria & autoSizeColumnCriteriaFilter); if (autoSizeColumnCriteriaFiltered != 0) { ret |= AutoResizeColumnInternal(dataGridViewColumn.Index, inheritedAutoSizeColumnCriteria, fixedHeight); } dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); } return ret; } ///Assigns a new parent control to the DataGridView. ///public void AutoResizeColumn(int columnIndex) { AutoResizeColumn(columnIndex, DataGridViewAutoSizeColumnMode.AllCells); } /// public void AutoResizeColumn(int columnIndex, DataGridViewAutoSizeColumnMode autoSizeColumnMode) { AutoResizeColumn(columnIndex, autoSizeColumnMode, true); } /// protected void AutoResizeColumn(int columnIndex, DataGridViewAutoSizeColumnMode autoSizeColumnMode, bool fixedHeight) { if (autoSizeColumnMode == DataGridViewAutoSizeColumnMode.NotSet || autoSizeColumnMode == DataGridViewAutoSizeColumnMode.None || autoSizeColumnMode == DataGridViewAutoSizeColumnMode.Fill) { throw new ArgumentException(SR.GetString(SR.DataGridView_NeedColumnAutoSizingCriteria, "autoSizeColumnMode")); } switch (autoSizeColumnMode) { case DataGridViewAutoSizeColumnMode.NotSet: case DataGridViewAutoSizeColumnMode.None: case DataGridViewAutoSizeColumnMode.ColumnHeader: case DataGridViewAutoSizeColumnMode.AllCellsExceptHeader: case DataGridViewAutoSizeColumnMode.AllCells: case DataGridViewAutoSizeColumnMode.DisplayedCellsExceptHeader: case DataGridViewAutoSizeColumnMode.DisplayedCells: case DataGridViewAutoSizeColumnMode.Fill: break; default: throw new InvalidEnumArgumentException("autoSizeColumnMode", (int)autoSizeColumnMode, typeof(DataGridViewAutoSizeColumnMode)); } if (columnIndex < 0 || columnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("columnIndex"); } if (autoSizeColumnMode == DataGridViewAutoSizeColumnMode.ColumnHeader && !this.ColumnHeadersVisible) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAutoSizeInvisibleColumnHeader)); } AutoResizeColumnInternal(columnIndex, (DataGridViewAutoSizeColumnCriteriaInternal) autoSizeColumnMode, fixedHeight); } /// public void AutoResizeColumnHeadersHeight() { AutoResizeColumnHeadersHeight(true, true); } /// public void AutoResizeColumnHeadersHeight(int columnIndex) { AutoResizeColumnHeadersHeight(columnIndex, true, true); } /// protected void AutoResizeColumnHeadersHeight(bool fixedRowHeadersWidth, bool fixedColumnsWidth) { if (!this.ColumnHeadersVisible) { return; } if (!this.IsHandleCreated) { // auto sizing causes handle creation. // don't create the handle inside InitializeComponent because that causes problems w/ data binding this.dataGridViewState2[DATAGRIDVIEWSTATE2_autoSizedWithoutHandle] = true; return; } try { this.noAutoSizeCount++; // Use of WindowsFormsUtils.CreateMeasurementGraphics() avoid use of this.Handle // IntPtr handle = this.Handle; // Force creation of control's handle because for databound grids, handle creation wipes out and recreates the columns/rows. int preferredHeight = 0; if (this.layout.TopLeftHeader.Width > 0) { if (fixedRowHeadersWidth) { preferredHeight = this.TopLeftHeaderCell.GetPreferredHeight(-1, this.layout.TopLeftHeader.Width); } else { preferredHeight = this.TopLeftHeaderCell.GetPreferredSize(-1).Height; } } int columnsCount = this.Columns.Count; for (int columnIndex = 0; columnIndex < columnsCount; columnIndex++) { if (this.Columns[columnIndex].Visible) { if (fixedColumnsWidth) { preferredHeight = Math.Max(preferredHeight, this.Columns[columnIndex].HeaderCell.GetPreferredHeight(-1, this.Columns[columnIndex].Thickness)); } else { preferredHeight = Math.Max(preferredHeight, this.Columns[columnIndex].HeaderCell.GetPreferredSize(-1).Height); } } } if (preferredHeight < minimumColumnHeadersHeight) { preferredHeight = minimumColumnHeadersHeight; } if (preferredHeight > maxHeadersThickness) { preferredHeight = maxHeadersThickness; } if (preferredHeight != this.ColumnHeadersHeight) { SetColumnHeadersHeightInternal(preferredHeight, !fixedColumnsWidth /*invalidInAdjustFillingColumns*/); } } finally { Debug.Assert(this.noAutoSizeCount > 0); this.noAutoSizeCount--; } } /// protected void AutoResizeColumnHeadersHeight(int columnIndex, bool fixedRowHeadersWidth, bool fixedColumnWidth) { if (columnIndex < -1 || columnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("columnIndex"); } if (!this.ColumnHeadersVisible) { return; } if (!this.IsHandleCreated) { // auto sizing causes handle creation. // don't create the handle inside InitializeComponent because that causes problems w/ data binding this.dataGridViewState2[DATAGRIDVIEWSTATE2_autoSizedWithoutHandle] = true; return; } try { this.noAutoSizeCount++; // Use of WindowsFormsUtils.CreateMeasurementGraphics() avoid use of this.Handle // IntPtr handle = this.Handle; // Force creation of control's handle because for databound grids, handle creation wipes out and recreates the columns/rows. int preferredHeight = 0; if (this.layout.TopLeftHeader.Width > 0) { if (columnIndex != -1 || fixedRowHeadersWidth) { preferredHeight = this.TopLeftHeaderCell.GetPreferredHeight(-1, this.layout.TopLeftHeader.Width); } else { preferredHeight = this.TopLeftHeaderCell.GetPreferredSize(-1).Height; } } int columnsCount = this.Columns.Count; for (int columnIndexTmp = 0; columnIndexTmp < columnsCount; columnIndexTmp++) { if (this.Columns[columnIndexTmp].Visible) { if (columnIndex != columnIndexTmp || fixedColumnWidth) { preferredHeight = Math.Max(preferredHeight, this.Columns[columnIndexTmp].HeaderCell.GetPreferredHeight(-1, this.Columns[columnIndexTmp].Thickness)); } else { preferredHeight = Math.Max(preferredHeight, this.Columns[columnIndexTmp].HeaderCell.GetPreferredSize(-1).Height); } } } if (preferredHeight < minimumColumnHeadersHeight) { preferredHeight = minimumColumnHeadersHeight; } if (preferredHeight > maxHeadersThickness) { preferredHeight = maxHeadersThickness; } if (preferredHeight != this.ColumnHeadersHeight) { SetColumnHeadersHeightInternal(preferredHeight, !fixedColumnWidth /*invalidInAdjustFillingColumns*/); } } finally { Debug.Assert(this.noAutoSizeCount > 0); this.noAutoSizeCount--; } } private bool AutoResizeColumnInternal(int columnIndex, DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaInternal, bool fixedHeight) { Debug.Assert(autoSizeColumnCriteriaInternal == DataGridViewAutoSizeColumnCriteriaInternal.Header || autoSizeColumnCriteriaInternal == DataGridViewAutoSizeColumnCriteriaInternal.AllRows || autoSizeColumnCriteriaInternal == DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows || autoSizeColumnCriteriaInternal == (DataGridViewAutoSizeColumnCriteriaInternal.Header | DataGridViewAutoSizeColumnCriteriaInternal.AllRows) || autoSizeColumnCriteriaInternal == (DataGridViewAutoSizeColumnCriteriaInternal.Header | DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows)); Debug.Assert(columnIndex >= 0 && columnIndex < this.Columns.Count); Debug.Assert(autoSizeColumnCriteriaInternal != DataGridViewAutoSizeColumnCriteriaInternal.Header || this.ColumnHeadersVisible); if (!this.IsHandleCreated) { // auto sizing causes handle creation. // don't create the handle inside InitializeComponent because that causes problems w/ data binding this.dataGridViewState2[DATAGRIDVIEWSTATE2_autoSizedWithoutHandle] = true; return false; } bool ret = false; // No autosizing occurs by default. try { this.noAutoSizeCount++; // Use of WindowsFormsUtils.CreateMeasurementGraphics() avoid use of this.Handle // IntPtr handle = this.Handle; // Force creation of control's handle because for databound grids, handle creation wipes out and recreates the columns. // Note: Even none-resizable column can programmatically be resized. DataGridViewColumn dataGridViewColumn = this.Columns[columnIndex]; int preferredColumnWidth = dataGridViewColumn.GetPreferredWidth((DataGridViewAutoSizeColumnMode) autoSizeColumnCriteriaInternal, fixedHeight); if (preferredColumnWidth < dataGridViewColumn.MinimumThickness) { preferredColumnWidth = dataGridViewColumn.MinimumThickness; } if (preferredColumnWidth > DataGridViewBand.maxBandThickness) { preferredColumnWidth = DataGridViewBand.maxBandThickness; } if (preferredColumnWidth != dataGridViewColumn.Thickness) { if (dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill) { AdjustFillingColumn(dataGridViewColumn, preferredColumnWidth); } else { this.Columns[columnIndex].ThicknessInternal = preferredColumnWidth; } ret = true; } } finally { Debug.Assert(this.noAutoSizeCount > 0); this.noAutoSizeCount--; } return ret; } /// public void AutoResizeColumns() { AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells); } /// public void AutoResizeColumns(DataGridViewAutoSizeColumnsMode autoSizeColumnsMode) { AutoResizeColumns(autoSizeColumnsMode, true); } /// protected void AutoResizeColumns(DataGridViewAutoSizeColumnsMode autoSizeColumnsMode, bool fixedHeight) { for (int columnIndex = 0; columnIndex < this.Columns.Count; columnIndex++) { AutoResizeColumn(columnIndex, (DataGridViewAutoSizeColumnMode)autoSizeColumnsMode, fixedHeight); } } /// public void AutoResizeRow(int rowIndex) { AutoResizeRow(rowIndex, DataGridViewAutoSizeRowMode.AllCells); } /// public void AutoResizeRow(int rowIndex, DataGridViewAutoSizeRowMode autoSizeRowMode) { AutoResizeRow(rowIndex, autoSizeRowMode, true /*fixedWidth*/); } /// protected void AutoResizeRow(int rowIndex, DataGridViewAutoSizeRowMode autoSizeRowMode, bool fixedWidth) { if (rowIndex < 0 || rowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("rowIndex"); } // not using ClientUtils here because it's a flags enum, masking instead. if (((DataGridViewAutoSizeRowCriteriaInternal) autoSizeRowMode & invalidDataGridViewAutoSizeRowCriteriaInternalMask) != 0) { throw new InvalidEnumArgumentException("autoSizeRowMode", (int) autoSizeRowMode, typeof(DataGridViewAutoSizeRowMode)); } if (autoSizeRowMode == DataGridViewAutoSizeRowMode.RowHeader && !this.RowHeadersVisible) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAutoSizeRowInvisibleRowHeader)); } AutoResizeRowInternal(rowIndex, autoSizeRowMode, fixedWidth, false /*internalAutosizing*/); } /// // User can override this if there is a quicker way to determine preferred row headers width public void AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode rowHeadersWidthSizeMode) { AutoResizeRowHeadersWidth(rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, true /*fixedRowsHeight*/); } /// // User can override this if there is a quicker way to determine preferred row headers width protected void AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode rowHeadersWidthSizeMode, bool fixedColumnHeadersHeight, bool fixedRowsHeight) { if (rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing || rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.DisableResizing) { throw new ArgumentException(SR.GetString(SR.DataGridView_NeedAutoSizingCriteria, "rowHeadersWidthSizeMode")); } // custom range checking, not using ClientUtils. if (rowHeadersWidthSizeMode < DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders || rowHeadersWidthSizeMode > DataGridViewRowHeadersWidthSizeMode.AutoSizeToFirstHeader) { throw new InvalidEnumArgumentException("rowHeadersWidthSizeMode", (int)rowHeadersWidthSizeMode, typeof(DataGridViewRowHeadersWidthSizeMode)); } if (!this.RowHeadersVisible) { return; } if (!this.IsHandleCreated) { // auto sizing causes handle creation. // don't create the handle inside InitializeComponent because that causes problems w/ data binding this.dataGridViewState2[DATAGRIDVIEWSTATE2_autoSizedWithoutHandle] = true; return; } try { this.noAutoSizeCount++; // Use of WindowsFormsUtils.CreateMeasurementGraphics() avoid use of this.Handle // IntPtr handle = this.Handle; // Force creation of control's handle because for databound grids, handle creation wipes out and recreates the columns/rows. int preferredWidth = 0, rowIndex; if (this.layout.TopLeftHeader.Width > 0) { if (fixedColumnHeadersHeight) { preferredWidth = this.TopLeftHeaderCell.GetPreferredWidth(-1, this.layout.TopLeftHeader.Height); } else { preferredWidth = this.TopLeftHeaderCell.GetPreferredSize(-1).Width; } } switch (rowHeadersWidthSizeMode) { case DataGridViewRowHeadersWidthSizeMode.AutoSizeToFirstHeader: { rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); if (rowIndex != -1) { if (fixedRowsHeight) { preferredWidth = Math.Max(preferredWidth, this.Rows.SharedRow(rowIndex).HeaderCell.GetPreferredWidth(rowIndex, this.Rows.SharedRow(rowIndex).GetHeight(rowIndex))); } else { preferredWidth = Math.Max(preferredWidth, this.Rows.SharedRow(rowIndex).HeaderCell.GetPreferredSize(rowIndex).Width); } } break; } case DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders: { int displayHeight = this.layout.Data.Height, cy = 0; rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); while (rowIndex != -1 && cy < displayHeight) { DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex); int dataGridViewRowHeight = dataGridViewRow.GetHeight(rowIndex); cy += dataGridViewRowHeight; if (fixedRowsHeight) { preferredWidth = Math.Max(preferredWidth, dataGridViewRow.HeaderCell.GetPreferredWidth(rowIndex, dataGridViewRowHeight)); } else { preferredWidth = Math.Max(preferredWidth, dataGridViewRow.HeaderCell.GetPreferredSize(rowIndex).Width); } rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); } if (cy < displayHeight) { rowIndex = this.displayedBandsInfo.FirstDisplayedScrollingRow; while (rowIndex != -1 && cy < displayHeight) { DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex); int dataGridViewRowHeight = dataGridViewRow.GetHeight(rowIndex); cy += dataGridViewRowHeight; if (fixedRowsHeight) { preferredWidth = Math.Max(preferredWidth, dataGridViewRow.HeaderCell.GetPreferredWidth(rowIndex, dataGridViewRowHeight)); } else { preferredWidth = Math.Max(preferredWidth, dataGridViewRow.HeaderCell.GetPreferredSize(rowIndex).Width); } rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible); } } break; } case DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders: { for (rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); rowIndex != -1; rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible)) { if (fixedRowsHeight) { preferredWidth = Math.Max(preferredWidth, this.Rows.SharedRow(rowIndex).HeaderCell.GetPreferredWidth(rowIndex, this.Rows.SharedRow(rowIndex).GetHeight(rowIndex))); } else { preferredWidth = Math.Max(preferredWidth, this.Rows.SharedRow(rowIndex).HeaderCell.GetPreferredSize(rowIndex).Width); } } break; } default: { Debug.Fail("Unexpected rowHeadersWidthSizeMode value in AutoResizeRowHeadersWidth"); break; } } if (preferredWidth < minimumRowHeadersWidth) { preferredWidth = minimumRowHeadersWidth; } if (preferredWidth != this.RowHeadersWidth) { this.RowHeadersWidthInternal = preferredWidth; } } finally { Debug.Assert(this.noAutoSizeCount > 0); this.noAutoSizeCount--; } } /// public void AutoResizeRowHeadersWidth(int rowIndex, DataGridViewRowHeadersWidthSizeMode rowHeadersWidthSizeMode) { AutoResizeRowHeadersWidth(rowIndex, rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, true /*fixedRowHeight*/); } /// protected void AutoResizeRowHeadersWidth(int rowIndex, DataGridViewRowHeadersWidthSizeMode rowHeadersWidthSizeMode, bool fixedColumnHeadersHeight, bool fixedRowHeight) { if (rowIndex < -1 || rowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("rowIndex"); } if (rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing || rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.DisableResizing) { throw new ArgumentException(SR.GetString(SR.DataGridView_NeedAutoSizingCriteria, "rowHeadersWidthSizeMode")); } if (rowHeadersWidthSizeMode < DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders || rowHeadersWidthSizeMode > DataGridViewRowHeadersWidthSizeMode.AutoSizeToFirstHeader) { throw new InvalidEnumArgumentException("rowHeadersWidthSizeMode", (int)rowHeadersWidthSizeMode, typeof(DataGridViewRowHeadersWidthSizeMode)); } if (!this.RowHeadersVisible) { return; } if (rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.AutoSizeToFirstHeader && rowIndex != -1 && rowIndex != this.Rows.GetFirstRow(DataGridViewElementStates.Visible)) { return; } if (rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders && rowIndex != -1) { DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex); bool rowDisplayed = (rowState & DataGridViewElementStates.Displayed) != 0; if (!rowDisplayed) { return; } } if (!this.IsHandleCreated) { // auto sizing causes handle creation. // don't create the handle inside InitializeComponent because that causes problems w/ data binding this.dataGridViewState2[DATAGRIDVIEWSTATE2_autoSizedWithoutHandle] = true; return; } try { this.noAutoSizeCount++; // Use of WindowsFormsUtils.CreateMeasurementGraphics() avoid use of this.Handle // IntPtr handle = this.Handle; // Force creation of control's handle because for databound grids, handle creation wipes out and recreates the columns/rows. int preferredWidth = 0, rowIndexTmp; if (this.layout.TopLeftHeader.Width > 0) { if (rowIndex != -1 || fixedColumnHeadersHeight) { preferredWidth = this.TopLeftHeaderCell.GetPreferredWidth(-1, this.layout.TopLeftHeader.Height); } else { preferredWidth = this.TopLeftHeaderCell.GetPreferredSize(-1).Width; } } switch (rowHeadersWidthSizeMode) { case DataGridViewRowHeadersWidthSizeMode.AutoSizeToFirstHeader: { rowIndexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); if (rowIndexTmp != -1) { if (rowIndex != rowIndexTmp || fixedRowHeight) { preferredWidth = Math.Max(preferredWidth, this.Rows.SharedRow(rowIndexTmp).HeaderCell.GetPreferredWidth(rowIndexTmp, this.Rows.SharedRow(rowIndexTmp).GetHeight(rowIndexTmp))); } else { preferredWidth = Math.Max(preferredWidth, this.Rows.SharedRow(rowIndexTmp).HeaderCell.GetPreferredSize(rowIndexTmp).Width); } } break; } case DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders: { int displayHeight = this.layout.Data.Height, cy = 0; rowIndexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); while (rowIndexTmp != -1 && cy < displayHeight) { DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndexTmp); int dataGridViewRowHeight = dataGridViewRow.GetHeight(rowIndexTmp); cy += dataGridViewRowHeight; if (rowIndex != rowIndexTmp || fixedRowHeight) { preferredWidth = Math.Max(preferredWidth, dataGridViewRow.HeaderCell.GetPreferredWidth(rowIndexTmp, dataGridViewRowHeight)); } else { preferredWidth = Math.Max(preferredWidth, dataGridViewRow.HeaderCell.GetPreferredSize(rowIndexTmp).Width); } rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); } if (cy < displayHeight) { rowIndexTmp = this.displayedBandsInfo.FirstDisplayedScrollingRow; while (rowIndexTmp != -1 && cy < displayHeight) { DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndexTmp); int dataGridViewRowHeight = dataGridViewRow.GetHeight(rowIndexTmp); cy += dataGridViewRowHeight; if (rowIndex != rowIndexTmp || fixedRowHeight) { preferredWidth = Math.Max(preferredWidth, dataGridViewRow.HeaderCell.GetPreferredWidth(rowIndexTmp, dataGridViewRowHeight)); } else { preferredWidth = Math.Max(preferredWidth, dataGridViewRow.HeaderCell.GetPreferredSize(rowIndexTmp).Width); } rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible); } } break; } case DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders: { for (rowIndexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); rowIndexTmp != -1; rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible)) { if (rowIndex != rowIndexTmp || fixedRowHeight) { preferredWidth = Math.Max(preferredWidth, this.Rows.SharedRow(rowIndexTmp).HeaderCell.GetPreferredWidth(rowIndexTmp, this.Rows.SharedRow(rowIndexTmp).GetHeight(rowIndexTmp))); } else { preferredWidth = Math.Max(preferredWidth, this.Rows.SharedRow(rowIndexTmp).HeaderCell.GetPreferredSize(rowIndexTmp).Width); } } break; } default: { Debug.Fail("Unexpected rowHeadersWidthSizeMode value in AutoResizeRowHeadersWidth"); break; } } if (preferredWidth < minimumRowHeadersWidth) { preferredWidth = minimumRowHeadersWidth; } if (preferredWidth != this.RowHeadersWidth) { this.RowHeadersWidthInternal = preferredWidth; } } finally { Debug.Assert(this.noAutoSizeCount > 0); this.noAutoSizeCount--; } } private void AutoResizeRowInternal(int rowIndex, DataGridViewAutoSizeRowMode autoSizeRowMode, bool fixedWidth, bool internalAutosizing) { Debug.Assert(rowIndex >= 0 && rowIndex < this.Rows.Count); Debug.Assert(((DataGridViewAutoSizeRowCriteriaInternal) autoSizeRowMode & invalidDataGridViewAutoSizeRowCriteriaInternalMask) == 0); if (!this.IsHandleCreated) { // auto sizing causes handle creation. // don't create the handle inside InitializeComponent because that causes problems w/ data binding this.dataGridViewState2[DATAGRIDVIEWSTATE2_autoSizedWithoutHandle] = true; return; } try { this.noAutoSizeCount++; // Use of WindowsFormsUtils.CreateMeasurementGraphics() avoid use of this.Handle // IntPtr handle = this.Handle; // Force creation of control's handle because for databound grids, handle creation wipes out and recreates the columns/rows. // Note: Even none-resizable row can programmatically be resized. DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex); int height, minimumHeight; dataGridViewRow.GetHeightInfo(rowIndex, out height, out minimumHeight); int preferredThickness = dataGridViewRow.GetPreferredHeight(rowIndex, autoSizeRowMode, fixedWidth); if (preferredThickness < minimumHeight) { preferredThickness = minimumHeight; } if (preferredThickness > DataGridViewBand.maxBandThickness) { preferredThickness = DataGridViewBand.maxBandThickness; } if (height != preferredThickness) { if (this.autoSizeRowsMode == DataGridViewAutoSizeRowsMode.None) { if (!OnRowHeightInfoPushed(rowIndex, preferredThickness, minimumHeight)) { this.Rows[rowIndex].ThicknessInternal = preferredThickness; // unsharing the resized row } } else { if (internalAutosizing) { this.Rows[rowIndex].ThicknessInternal = preferredThickness; // unsharing the resized row } else { this.Rows[rowIndex].Thickness = preferredThickness; // unsharing the resized row } } } } finally { Debug.Assert(this.noAutoSizeCount > 0); this.noAutoSizeCount--; } } /// public void AutoResizeRows() { AutoResizeRows(DataGridViewAutoSizeRowsMode.AllCells); } /// public void AutoResizeRows(DataGridViewAutoSizeRowsMode autoSizeRowsMode) { AutoResizeRows(autoSizeRowsMode, true /*fixedWidth*/); } /// protected void AutoResizeRows(DataGridViewAutoSizeRowsMode autoSizeRowsMode, bool fixedWidth) { switch (autoSizeRowsMode) { case DataGridViewAutoSizeRowsMode.None: case DataGridViewAutoSizeRowsMode.AllHeaders: case DataGridViewAutoSizeRowsMode.AllCellsExceptHeaders: case DataGridViewAutoSizeRowsMode.AllCells: case DataGridViewAutoSizeRowsMode.DisplayedHeaders: case DataGridViewAutoSizeRowsMode.DisplayedCellsExceptHeaders: case DataGridViewAutoSizeRowsMode.DisplayedCells: break; default: throw new InvalidEnumArgumentException("value", (int)autoSizeRowsMode, typeof(DataGridViewAutoSizeRowsMode)); } if (autoSizeRowsMode == DataGridViewAutoSizeRowsMode.None) { throw new ArgumentException(SR.GetString(SR.DataGridView_NeedAutoSizingCriteria, "autoSizeRowsMode")); } if ((autoSizeRowsMode == DataGridViewAutoSizeRowsMode.AllHeaders || autoSizeRowsMode == DataGridViewAutoSizeRowsMode.DisplayedHeaders) && !this.RowHeadersVisible) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAutoSizeRowsInvisibleRowHeader)); } AdjustShrinkingRows(autoSizeRowsMode, fixedWidth, false /*internalAutosizing*/); } /// protected void AutoResizeRows(int rowIndexStart, int rowsCount, DataGridViewAutoSizeRowMode autoSizeRowMode, bool fixedWidth) { // not using ClientUtils.IsEnumValid here because DataGridViewAutoSizeRowCriteriaInternal is a flags enum. if (((DataGridViewAutoSizeRowCriteriaInternal) autoSizeRowMode & invalidDataGridViewAutoSizeRowCriteriaInternalMask) != 0) { throw new InvalidEnumArgumentException("autoSizeRowMode", (int) autoSizeRowMode, typeof(DataGridViewAutoSizeRowMode)); } if (autoSizeRowMode == DataGridViewAutoSizeRowMode.RowHeader && !this.RowHeadersVisible) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAutoSizeRowsInvisibleRowHeader)); } if (rowsCount < 0) { throw new ArgumentOutOfRangeException("rowsCount"); } if (rowIndexStart < 0) { throw new ArgumentOutOfRangeException("rowIndexStart"); } if (!this.IsHandleCreated) { // auto sizing causes handle creation. // don't create the handle inside InitializeComponent because that causes problems w/ data binding this.dataGridViewState2[DATAGRIDVIEWSTATE2_autoSizedWithoutHandle] = true; return; } this.inBulkPaintCount++; this.inBulkLayoutCount++; try { int rowIndex = this.Rows.GetNextRow(rowIndexStart - 1, DataGridViewElementStates.Visible); int autoSizedCount = 0; while (rowIndex != -1 && autoSizedCount < rowsCount) { AutoResizeRowInternal(rowIndex, autoSizeRowMode, fixedWidth, false /*internalAutosizing*/); autoSizedCount++; if (autoSizedCount < rowsCount) { rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible); } } } finally { ExitBulkLayout(true /*invalidInAdjustFillingColumns*/); ExitBulkPaint(-1, -1); } } private void BeginColumnHeadersResize(int mouseY, int mouseBarOffset) { Rectangle clip = Rectangle.Union(this.layout.ColumnHeaders, this.layout.Data); if (this.layout.TopLeftHeader.Width > 0) { clip = Rectangle.Union(this.layout.TopLeftHeader, clip); } clip.Y += minimumColumnHeadersHeight - mouseBarOffset - 1; // No need to limit the bottom edge of the cursor clip since maxHeadersThickness is very large. CaptureMouse(clip); this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] = true; this.trackRowAnchor = mouseY; this.mouseBarOffset = mouseBarOffset; Debug.Assert(this.lastRowSplitBar == -1); this.currentRowSplitBar = mouseY; Invalidate(CalcRowResizeFeedbackRect(this.currentRowSplitBar)); } private void BeginColumnRelocation(int mouseX, int index) { Rectangle cursorClip = this.layout.ColumnHeaders; int frozenWidth = this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); int scrollingWidth = this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible) - frozenWidth; if (this.Columns[index].Frozen) { // A frozen column cannot be relocated into an unfrozen area if (this.RightToLeftInternal) { cursorClip.X += cursorClip.Width - frozenWidth; } cursorClip.Width = Math.Min(frozenWidth, this.layout.Data.Width); } else { // An unfrozen column cannot be relocated into a frozen area if (!this.RightToLeftInternal) { cursorClip.X += frozenWidth; } else if (this.layout.Data.Width > frozenWidth + scrollingWidth) { cursorClip.X += this.layout.Data.Width - frozenWidth - scrollingWidth; } cursorClip.Width = Math.Min(scrollingWidth, this.layout.Data.Width); } CaptureMouse(cursorClip); this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation] = true; this.dataGridViewState2[DATAGRIDVIEWSTATE2_showColumnRelocationInsertion] = false; this.trackColumn = index; this.trackColumnEdge = -1; this.mouseBarOffset = GetColumnXFromIndex(index) - mouseX; this.lastHeaderShadow = mouseX; Invalidate(this.layout.ColumnHeaders); } private void BeginColumnResize(int mouseX, int mouseBarOffset, int index) { Rectangle clip = Rectangle.Union(this.layout.ColumnHeaders, this.layout.Data); int leftEdge = GetColumnXFromIndex(index); if (this.RightToLeftInternal) { clip.X = this.layout.Data.X - mouseBarOffset - 1; clip.Width = leftEdge - this.Columns[index].MinimumThickness - this.layout.Data.X + 3; int overflowWidth = leftEdge - mouseBarOffset - clip.Left - DataGridViewBand.maxBandThickness + 1; if (overflowWidth > 0) { clip.X += overflowWidth; clip.Width -= overflowWidth; } } else { clip.X = leftEdge + this.Columns[index].MinimumThickness - mouseBarOffset - 1; clip.Width = this.layout.Data.Right - leftEdge - 1; int overflowWidth = clip.Right + mouseBarOffset - leftEdge - DataGridViewBand.maxBandThickness; if (overflowWidth > 0) { clip.Width -= overflowWidth; } } CaptureMouse(clip); this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize] = true; this.trackColAnchor = mouseX; this.trackColumn = index; this.mouseBarOffset = mouseBarOffset; Debug.Assert(this.lastColSplitBar == -1); this.currentColSplitBar = mouseX; Invalidate(CalcColResizeFeedbackRect(this.currentColSplitBar)); } /// public virtual bool BeginEdit(bool selectAll) { if (this.ptCurrentCell.X == -1) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_NoCurrentCell)); } if (this.IsCurrentCellInEditMode) { return true; } return BeginEditInternal(selectAll); } private bool BeginEditInternal(bool selectAll) { if (this.dataGridViewOper[DATAGRIDVIEWOPER_inBeginEdit]) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_BeginEditNotReentrant)); } try { this.dataGridViewOper[DATAGRIDVIEWOPER_inBeginEdit] = true; Debug.Assert(this.ptCurrentCell.X >= 0 && this.ptCurrentCell.X < this.Columns.Count); Debug.Assert(this.ptCurrentCell.Y >= 0 && this.ptCurrentCell.Y < this.Rows.Count); Debug.Assert(!this.IsCurrentCellInEditMode); DataGridViewCell dataGridViewCell = this.CurrentCellInternal; Debug.Assert(dataGridViewCell != null); if (IsSharedCellReadOnly(dataGridViewCell, this.ptCurrentCell.Y) || !ColumnEditable(this.ptCurrentCell.X)) { return false; } Type editControlType = dataGridViewCell.EditType; if (editControlType == null) { // Current cell does not have an editing control. Does it implement IDataGridViewEditingCell? Type editingCellInterface = dataGridViewCell.GetType().GetInterface("System.Windows.Forms.IDataGridViewEditingCell"); if (editingCellInterface == null) { return false; } } DataGridViewCellCancelEventArgs dgvcce = new DataGridViewCellCancelEventArgs(this.ptCurrentCell.X, this.ptCurrentCell.Y); OnCellBeginEdit(dgvcce); if (dgvcce.Cancel) { return false; } Debug.Assert(!this.IsCurrentCellInEditMode); if (this.ptCurrentCell.X > -1) { DataGridViewCell previousCurrentCell = dataGridViewCell; dataGridViewCell = this.CurrentCellInternal; if (previousCurrentCell != dataGridViewCell) { // VSWhidbey 555494. The new current cell can be a whole different cell. // In that case, all tests previously done are no longer valid. if (IsSharedCellReadOnly(dataGridViewCell, this.ptCurrentCell.Y) || !ColumnEditable(this.ptCurrentCell.X)) { return false; } editControlType = dataGridViewCell.EditType; if (editControlType == null) { // Current cell does not have an editing control. Does it implement IDataGridViewEditingCell? Type editingCellInterface = dataGridViewCell.GetType().GetInterface("System.Windows.Forms.IDataGridViewEditingCell"); if (editingCellInterface == null) { return false; } } } } else { return false; } DataGridViewCellStyle dataGridViewCellStyle = dataGridViewCell.GetInheritedStyle(null, this.ptCurrentCell.Y, true); if (editControlType == null) { this.dataGridViewState1[DATAGRIDVIEWSTATE1_currentCellInEditMode] = true; InitializeEditingCellValue(ref dataGridViewCellStyle, ref dataGridViewCell); ((IDataGridViewEditingCell)dataGridViewCell).PrepareEditingCellForEdit(selectAll); return true; } Type editingCtrlInterface = editControlType.GetInterface("System.Windows.Forms.IDataGridViewEditingControl"); if (!editControlType.IsSubclassOf(Type.GetType("System.Windows.Forms.Control")) || editingCtrlInterface == null) { throw new InvalidCastException(SR.GetString(SR.DataGridView_InvalidEditingControl)); } if (this.latestEditingControl != null && editControlType.IsInstanceOfType(this.latestEditingControl) && !this.latestEditingControl.GetType().IsSubclassOf(editControlType)) { this.editingControl = this.latestEditingControl; Debug.Assert(((IDataGridViewEditingControl)this.editingControl).EditingControlDataGridView == this); } else { Debug.Assert(this.editingControl == null); this.editingControl = (Control)SecurityUtils.SecureCreateInstance(editControlType); Debug.Assert(this.editingControl != null); ((IDataGridViewEditingControl)this.editingControl).EditingControlDataGridView = this; if (this.latestEditingControl != null) { this.latestEditingControl.Dispose(); this.latestEditingControl = null; } } Debug.Assert(this.editingControl != null); if (String.IsNullOrEmpty(this.editingControl.AccessibleName)) { this.editingControl.AccessibleName = SR.GetString(SR.DataGridView_AccEditingControlAccName); } this.editingControl.ImeMode = this.ImeMode; ((IDataGridViewEditingControl)this.editingControl).EditingControlRowIndex = this.ptCurrentCell.Y; InitializeEditingControlValue(ref dataGridViewCellStyle, dataGridViewCell); WireEditingControlEvents(); Debug.Assert(this.editingControl != null); Debug.Assert(this.editingPanel != null); DataGridViewEditingControlShowingEventArgs dgvese = new DataGridViewEditingControlShowingEventArgs(this.editingControl, dataGridViewCellStyle); OnEditingControlShowing(dgvese); Debug.Assert(dgvese.CellStyle != null); if (this.editingPanel == null || this.editingControl == null) { return false; } this.editingPanel.BackColor = dgvese.CellStyle.BackColor; ((IDataGridViewEditingControl)this.editingControl).ApplyCellStyleToEditingControl(dgvese.CellStyle); // Get rid of the tooltip if it's showing for the current cell if (this.toolTipControl.Activated && this.ptToolTipCell == this.ptCurrentCell) { this.toolTipControl.Activate(false /*activate*/); } PositionEditingControl(true, true, true); // Guarding against bugs in customer code. // For example setting the CurrentCell to null in DataGridView_OnLostFocus(...) causes this.editingControl // to become null. if (this.editingPanel == null || this.editingControl == null) { return false; } else { ((IDataGridViewEditingControl)this.editingControl).PrepareEditingControlForEdit(selectAll); InvalidateCellPrivate(this.ptCurrentCell.X, this.ptCurrentCell.Y); return true; } } finally { this.dataGridViewOper[DATAGRIDVIEWOPER_inBeginEdit] = false; } } private void BeginRowHeadersResize(int mouseX, int mouseBarOffset) { Rectangle clip = Rectangle.Union(this.layout.RowHeaders, this.layout.Data); if (this.layout.TopLeftHeader.Width > 0) { clip = Rectangle.Union(this.layout.TopLeftHeader, clip); } if (this.RightToLeftInternal) { clip.X -= mouseBarOffset + 1; clip.Width -= minimumRowHeadersWidth - 1; // No need to limit the left edge of the cursor clip since maxHeadersThickness is very large. } else { clip.X += minimumRowHeadersWidth - mouseBarOffset - 1; // No need to limit the right edge of the cursor clip since maxHeadersThickness is very large. } CaptureMouse(clip); this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize] = true; this.trackColAnchor = mouseX; this.mouseBarOffset = mouseBarOffset; Debug.Assert(this.lastColSplitBar == -1); this.currentColSplitBar = mouseX; Invalidate(CalcColResizeFeedbackRect(this.currentColSplitBar)); } private void BeginRowResize(int mouseY, int mouseBarOffset, int index) { Rectangle clip = Rectangle.Union(this.layout.RowHeaders, this.layout.Data); int topEdge = GetRowYFromIndex(index); clip.Y = topEdge + this.Rows.SharedRow(index).GetMinimumHeight(index) - mouseBarOffset - 1; clip.Height = this.layout.Data.Y + this.layout.Data.Height - topEdge - 1; CaptureMouse(clip); this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize] = true; this.trackRowAnchor = mouseY; this.trackRow = index; this.mouseBarOffset = mouseBarOffset; Debug.Assert(this.lastRowSplitBar == -1); this.currentRowSplitBar = mouseY; Invalidate(CalcRowResizeFeedbackRect(this.currentRowSplitBar)); } private void BuildInheritedColumnHeaderCellStyle(DataGridViewCellStyle inheritedCellStyle, DataGridViewCell cell) { Debug.Assert(inheritedCellStyle != null); DataGridViewCellStyle cellStyle = null; if (cell.HasStyle) { cellStyle = cell.Style; Debug.Assert(cellStyle != null); } DataGridViewCellStyle columnHeadersStyle = this.ColumnHeadersDefaultCellStyle; Debug.Assert(columnHeadersStyle != null); DataGridViewCellStyle dataGridViewStyle = this.DefaultCellStyle; Debug.Assert(dataGridViewStyle != null); if (cellStyle != null && !cellStyle.BackColor.IsEmpty) { inheritedCellStyle.BackColor = cellStyle.BackColor; } else if (!columnHeadersStyle.BackColor.IsEmpty) { inheritedCellStyle.BackColor = columnHeadersStyle.BackColor; } else { inheritedCellStyle.BackColor = dataGridViewStyle.BackColor; } if (cellStyle != null && !cellStyle.ForeColor.IsEmpty) { inheritedCellStyle.ForeColor = cellStyle.ForeColor; } else if (!columnHeadersStyle.ForeColor.IsEmpty) { inheritedCellStyle.ForeColor = columnHeadersStyle.ForeColor; } else { inheritedCellStyle.ForeColor = dataGridViewStyle.ForeColor; } if (cellStyle != null && !cellStyle.SelectionBackColor.IsEmpty) { inheritedCellStyle.SelectionBackColor = cellStyle.SelectionBackColor; } else if (!columnHeadersStyle.SelectionBackColor.IsEmpty) { inheritedCellStyle.SelectionBackColor = columnHeadersStyle.SelectionBackColor; } else { inheritedCellStyle.SelectionBackColor = dataGridViewStyle.SelectionBackColor; } if (cellStyle != null && !cellStyle.SelectionForeColor.IsEmpty) { inheritedCellStyle.SelectionForeColor = cellStyle.SelectionForeColor; } else if (!columnHeadersStyle.SelectionForeColor.IsEmpty) { inheritedCellStyle.SelectionForeColor = columnHeadersStyle.SelectionForeColor; } else { inheritedCellStyle.SelectionForeColor = dataGridViewStyle.SelectionForeColor; } if (cellStyle != null && cellStyle.Font != null) { inheritedCellStyle.Font = cellStyle.Font; } else if (columnHeadersStyle.Font != null) { inheritedCellStyle.Font = columnHeadersStyle.Font; } else { inheritedCellStyle.Font = dataGridViewStyle.Font; } if (cellStyle != null && !cellStyle.IsNullValueDefault) { inheritedCellStyle.NullValue = cellStyle.NullValue; } else if (!columnHeadersStyle.IsNullValueDefault) { inheritedCellStyle.NullValue = columnHeadersStyle.NullValue; } else { inheritedCellStyle.NullValue = dataGridViewStyle.NullValue; } if (cellStyle != null && !cellStyle.IsDataSourceNullValueDefault) { inheritedCellStyle.DataSourceNullValue = cellStyle.DataSourceNullValue; } else if (!columnHeadersStyle.IsDataSourceNullValueDefault) { inheritedCellStyle.DataSourceNullValue = columnHeadersStyle.DataSourceNullValue; } else { inheritedCellStyle.DataSourceNullValue = dataGridViewStyle.DataSourceNullValue; } if (cellStyle != null && cellStyle.Format.Length != 0) { inheritedCellStyle.Format = cellStyle.Format; } else if (columnHeadersStyle.Format.Length != 0) { inheritedCellStyle.Format = columnHeadersStyle.Format; } else { inheritedCellStyle.Format = dataGridViewStyle.Format; } if (cellStyle != null && !cellStyle.IsFormatProviderDefault) { inheritedCellStyle.FormatProvider = cellStyle.FormatProvider; } else if (!columnHeadersStyle.IsFormatProviderDefault) { inheritedCellStyle.FormatProvider = columnHeadersStyle.FormatProvider; } else { inheritedCellStyle.FormatProvider = dataGridViewStyle.FormatProvider; } if (cellStyle != null && cellStyle.Alignment != DataGridViewContentAlignment.NotSet) { inheritedCellStyle.AlignmentInternal = cellStyle.Alignment; } else if (columnHeadersStyle != null && columnHeadersStyle.Alignment != DataGridViewContentAlignment.NotSet) { inheritedCellStyle.AlignmentInternal = columnHeadersStyle.Alignment; } else { Debug.Assert(dataGridViewStyle.Alignment != DataGridViewContentAlignment.NotSet); inheritedCellStyle.AlignmentInternal = dataGridViewStyle.Alignment; } if (cellStyle != null && cellStyle.WrapMode != DataGridViewTriState.NotSet) { inheritedCellStyle.WrapModeInternal = cellStyle.WrapMode; } else if (columnHeadersStyle != null && columnHeadersStyle.WrapMode != DataGridViewTriState.NotSet) { inheritedCellStyle.WrapModeInternal = columnHeadersStyle.WrapMode; } else { Debug.Assert(dataGridViewStyle.WrapMode != DataGridViewTriState.NotSet); inheritedCellStyle.WrapModeInternal = dataGridViewStyle.WrapMode; } if (cellStyle != null && cellStyle.Tag != null) { inheritedCellStyle.Tag = cellStyle.Tag; } else if (columnHeadersStyle.Tag != null) { inheritedCellStyle.Tag = columnHeadersStyle.Tag; } else { inheritedCellStyle.Tag = dataGridViewStyle.Tag; } if (cellStyle != null && cellStyle.Padding != Padding.Empty) { inheritedCellStyle.PaddingInternal = cellStyle.Padding; } else if (columnHeadersStyle.Padding != Padding.Empty) { inheritedCellStyle.PaddingInternal = columnHeadersStyle.Padding; } else { inheritedCellStyle.PaddingInternal = dataGridViewStyle.Padding; } } private Rectangle CalcColRelocationFeedbackRect(int mouseX) { Rectangle r, inside = this.layout.ColumnHeaders; if (this.layout.TopLeftHeader.Width > 0) { inside = Rectangle.Union(this.layout.TopLeftHeader, inside); } if (this.RightToLeftInternal) { r = new Rectangle(mouseX + this.mouseBarOffset - this.Columns[this.trackColumn].Thickness + 1, inside.Y, this.Columns[this.trackColumn].Thickness, inside.Height); r.X = Math.Max(inside.Left, r.X); r.X = Math.Min(r.X, inside.Right - r.Width); } else { r = new Rectangle(mouseX + this.mouseBarOffset - 1, inside.Y, this.Columns[this.trackColumn].Thickness, inside.Height); r.X = Math.Min(inside.Right - r.Width, r.X); r.X = Math.Max(r.X, inside.Left); } return r; } private Rectangle CalcColResizeFeedbackRect(int mouseX) { Rectangle inside = this.layout.Data; Rectangle r = new Rectangle(mouseX + this.mouseBarOffset - 1, inside.Y, 3, inside.Height); if (this.RightToLeftInternal) { r.X = Math.Max(inside.Left, r.X); } else { r.X = Math.Min(inside.Right - 3, r.X); r.X = Math.Max(r.X, 0); } return r; } private Rectangle CalcRowResizeFeedbackRect(int mouseY) { Rectangle inside = this.layout.Data; Rectangle r = new Rectangle(inside.X, mouseY + this.mouseBarOffset - 1, inside.Width, 3); r.Y = Math.Min(inside.Bottom - 3, r.Y); r.Y = Math.Max(r.Y, 0); return r; } /// public bool CancelEdit() { return CancelEdit(false /*endEdit, DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.InitialValueRestoration*/); } private bool CancelEdit(bool endEdit /*, DataGridViewDataErrorContexts context*/) { if (this.ptCurrentCell.X != -1) { Debug.Assert(this.ptCurrentCell.Y != -1); int oldCurrentCellX = this.ptCurrentCell.X; DataGridViewDataErrorEventArgs dgvdee = CancelEditPrivate(/*ref dataGridViewCurrentCell, context*/); if (null != dgvdee) { if (dgvdee.ThrowException) { throw dgvdee.Exception; } if (dgvdee.Cancel) { return false; } } if (this.IsCurrentCellInEditMode) { if (endEdit && this.EditMode != DataGridViewEditMode.EditOnEnter && this.editingControl != null) { bool success = EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.InitialValueRestoration, DataGridViewValidateCellInternal.Never /*validateCell*/, false /*fireCellLeave*/, false /*fireCellEnter*/, false /*fireRowLeave*/, false /*fireRowEnter*/, false /*fireLeave*/, true /*keepFocus*/, true /*resetCurrentCell unused here*/, true /*resetAnchorCell unused here*/); Debug.Assert(success); } else { DataGridViewDataErrorEventArgs dgvdee2 = null; IDataGridViewEditingCell dataGridViewEditingCell = null; try { this.dataGridViewState1[DATAGRIDVIEWSTATE1_ignoringEditingChanges] = true; if (this.editingControl != null) { ((IDataGridViewEditingControl)this.editingControl).EditingControlFormattedValue = this.uneditedFormattedValue; ((IDataGridViewEditingControl)this.editingControl).EditingControlValueChanged = false; } else { Debug.Assert(this.dataGridViewState1[DATAGRIDVIEWSTATE1_currentCellInEditMode]); dataGridViewEditingCell = this.CurrentCellInternal as IDataGridViewEditingCell; Debug.Assert(dataGridViewEditingCell != null); dataGridViewEditingCell.EditingCellFormattedValue = this.uneditedFormattedValue; dataGridViewEditingCell.EditingCellValueChanged = false; } } catch (Exception exception) { if (ClientUtils.IsCriticalException(exception)) { throw; } dgvdee2 = new DataGridViewDataErrorEventArgs(exception, this.ptCurrentCell.X, this.ptCurrentCell.Y, DataGridViewDataErrorContexts.InitialValueRestoration); } finally { this.dataGridViewState1[DATAGRIDVIEWSTATE1_ignoringEditingChanges] = false; } if (dgvdee2 != null) { OnDataErrorInternal(dgvdee2); if (dgvdee2.ThrowException) { throw dgvdee2.Exception; } } if (this.editingControl != null) { ((IDataGridViewEditingControl) this.editingControl).PrepareEditingControlForEdit(true /*selectAll*/); } else { Debug.Assert(dataGridViewEditingCell != null); dataGridViewEditingCell.PrepareEditingCellForEdit(true /*selectAll*/); InvalidateCellPrivate(this.ptCurrentCell.X, this.ptCurrentCell.Y); } } } else if (this.ptCurrentCell.X == -1 && this.Focused) { Debug.Assert((this.AllowUserToAddRowsInternal && this.Rows.Count == 1) || (!this.AllowUserToAddRowsInternal && this.Rows.Count == 0)); if (this.Rows.Count > 0) { if (this.Columns.Count > oldCurrentCellX && this.Columns[oldCurrentCellX].Visible) { int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); if (rowIndex != -1) { bool success = SetAndSelectCurrentCellAddress(oldCurrentCellX, rowIndex, true /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false /*throughMouseClick*/, false /*clearSelection*/, false /*forceCurrentCellSelection*/); Debug.Assert(success); } } else { MakeFirstDisplayedCellCurrentCell(true /*includeNewRow*/); } } } } return true; } private DataGridViewDataErrorEventArgs CancelEditPrivate(/*ref DataGridViewCell dataGridViewCurrentCell, DataGridViewDataErrorContexts context*/) { bool currentCellDirty = this.IsCurrentCellDirty; bool currentRowDirty = this.IsCurrentRowDirty; if (this.IsCurrentCellInEditMode) { /* Do not push original value back into the cell - VS Whidbey bug 328624 Exception exception; if (!PushFormattedValue(ref dataGridViewCurrentCell, this.uneditedFormattedValue, out exception)) { Debug.Assert(dataGridViewCurrentCell.RowIndex > -1); DataGridViewDataErrorEventArgs dgvdee = new DataGridViewDataErrorEventArgs(exception, dataGridViewCurrentCell.ColumnIndex, dataGridViewCurrentCell.RowIndex, // dataGridViewCurrentCell.Value, // this.uneditedFormattedValue, context); dgvdee.Cancel = true; OnDataErrorInternal(dgvdee); return dgvdee; } */ if (this.editingControl != null) { ((IDataGridViewEditingControl)this.editingControl).EditingControlValueChanged = false; } else { Debug.Assert(this.dataGridViewState1[DATAGRIDVIEWSTATE1_currentCellInEditMode]); ((IDataGridViewEditingCell)this.CurrentCellInternal).EditingCellValueChanged = false; } this.IsCurrentCellDirtyInternal = false; } if (this.DataSource != null || this.VirtualMode) { if ((currentRowDirty && !currentCellDirty) || (this.dataGridViewState1[DATAGRIDVIEWSTATE1_newRowEdited] && !this.dataGridViewState1[DATAGRIDVIEWSTATE1_editedRowChanged])) { bool discardNewRow = this.dataGridViewState1[DATAGRIDVIEWSTATE1_newRowEdited]; this.IsCurrentRowDirtyInternal = false; if (this.VirtualMode) { QuestionEventArgs qe = new QuestionEventArgs(discardNewRow); OnCancelRowEdit(qe); discardNewRow &= qe.Response; } if (this.DataSource != null) { int oldCurrentCellX = this.ptCurrentCell.X; this.dataConnection.CancelRowEdit(true /*restoreRow*/, this.dataGridViewState1[DATAGRIDVIEWSTATE1_newRowEdited]/*addNewFinished*/); if (this.dataConnection.List.Count == 0) { // There are no rows left in the back end. if (currentCellDirty || this.ptCurrentCell.Y == -1 || this.ptCurrentCell.X == -1) { if (!IsColumnOutOfBounds(oldCurrentCellX) && this.Columns[oldCurrentCellX].Visible) { Debug.Assert(0 == this.Rows.GetFirstRow(DataGridViewElementStates.Visible)); // Setting the current cell to the current column in the first row // will create the new row if the user was editing the cell. SetAndSelectCurrentCellAddress(oldCurrentCellX, 0, true, /*setAnchorCellAddress*/ false, /*validateCurrentCell*/ false, /*throughMouseClick*/ true /*clearSelecttion*/, false /*forceCurrentCellSelection (unused)*/); } } else { // Else, simply add a new row. this.dataConnection.OnNewRowNeeded(); } } // CancelRowEdit discarded the new row if we were editing the new row. discardNewRow = false; } if (this.ptCurrentCell.Y > -1) { InvalidateRowPrivate(this.ptCurrentCell.Y); DataGridViewCell dataGridViewCell = this.CurrentCellInternal; if (this.IsCurrentCellInEditMode) { DataGridViewCellStyle dataGridViewCellStyle = dataGridViewCell.GetInheritedStyle(null, this.ptCurrentCell.Y, true); if (this.editingControl != null) { InitializeEditingControlValue(ref dataGridViewCellStyle, dataGridViewCell); if (((IDataGridViewEditingControl) this.editingControl).RepositionEditingControlOnValueChange) { PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/); } } else { Debug.Assert(this.dataGridViewState1[DATAGRIDVIEWSTATE1_currentCellInEditMode]); InitializeEditingCellValue(ref dataGridViewCellStyle, ref dataGridViewCell); } } } if (discardNewRow && this.ptCurrentCell.Y == this.newRowIndex - 1) { DiscardNewRow(); } } } else { if (!this.IsCurrentRowDirty && this.ptCurrentCell.Y == this.newRowIndex - 1 && this.dataGridViewState1[DATAGRIDVIEWSTATE1_newRowCreatedByEditing]) { DiscardNewRow(); } } return null; } internal bool CancelToolTipPopup(ToolTip toolTip) { if (this.toolTipControl.ToolTip == toolTip) { // Our own tool tip wants to show its text. return false; } else { // This is an external tool tip control which wants to show a tool tip over the DataGridView. // ToolTips from the data Grid view ( the error text, or the formatted text that does not fit in, or the tool tip text from the cell) // and the ShowCellToolTips take precedence over the external tool tip. return String.IsNullOrEmpty(this.toolTipCaption) && this.ShowCellToolTips; } } // determines if a data bound cell can be validated or not private bool CanValidateDataBoundDataGridViewCell(DataGridViewCell dataGridViewCurrentCell) { if (dataGridViewCurrentCell == null) { if (this.ptCurrentCell.X > -1) { dataGridViewCurrentCell = this.CurrentCellInternal; } } if (dataGridViewCurrentCell == null) { return true; } Debug.Assert(dataGridViewCurrentCell.OwningColumn != null); if (!dataGridViewCurrentCell.OwningColumn.IsDataBoundInternal) { // we are not data bound so it's not up to us to decide to stop validation return true; } if (this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose]) { // Dispose is not the place to validate data. Also, chances are that the data source is also disposing itself. return false; } if (this.dataConnection == null) { // if there is no dataConnection then it is not up to this function to stop validation. return true; } ///////////////////////////////////////////////////////////////////////////////////////////////// // // // FROM HERE DOWN THE DATA CONNECTION DETERMINES IF THE DATAGRIDVIEW SHOULD VALIDATE THE CELL. // // // ///////////////////////////////////////////////////////////////////////////////////////////////// if (this.dataConnection.ProcessingMetaDataChanges) { // don't validate a cell in a data bound column while the property descriptors change under us return false; } if (this.dataConnection.CancellingRowEdit && !this.dataConnection.RestoreRow) { // don't validate a cell in a data bound column while we are cancelling a row edit and the old row is not restored return false; } if (this.dataConnection.CurrencyManager.Count <= this.ptCurrentCell.Y) { // don't validate a row beyond the last row in the back end list return false; } if (this.dataConnection.PositionChangingOutsideDataGridView) { // the position changed outside the data grid view and we haven't validated the data grid view cell already // we can't validate it now because if the user cancels validation then we end up // with a position different than the position in the currency manager return false; } if (this.dataConnection.ListWasReset) { // The list was reset outside data grid view. // We can't validate it now because we would be pushing a value into a different object ( possibly located in a different list ). return false; } return true; } private void CaptureMouse(Rectangle cursorClip) { this.CaptureInternal = true; Cursor.ClipInternal = RectangleToScreen(cursorClip); } private void ClearRegionCache() { this.cachedScrollableRegion = null; } /// public void ClearSelection() { this.noDimensionChangeCount++; this.noSelectionChangeCount++; bool switchedToBulkPaint = false; if (this.selectedBandIndexes.Count > DATAGRIDVIEW_bulkPaintThreshold || this.individualSelectedCells.Count > DATAGRIDVIEW_bulkPaintThreshold) { this.inBulkPaintCount++; switchedToBulkPaint = true; } try { RemoveIndividuallySelectedCells(); switch (this.SelectionMode) { case DataGridViewSelectionMode.CellSelect: { // If we change the design and start using this.selectedBandIndexes in this SelectionMode, // we'll have to clear those selections too. break; } case DataGridViewSelectionMode.FullRowSelect: case DataGridViewSelectionMode.RowHeaderSelect: { while(this.selectedBandIndexes.Count > 0) { SetSelectedRowCore(this.selectedBandIndexes.HeadInt, false); } break; } case DataGridViewSelectionMode.FullColumnSelect: case DataGridViewSelectionMode.ColumnHeaderSelect: { while(this.selectedBandIndexes.Count > 0) { SetSelectedColumnCore(this.selectedBandIndexes.HeadInt, false); } break; } } } finally { this.noDimensionChangeCount--; Debug.Assert(this.noDimensionChangeCount >= 0); this.NoSelectionChangeCount--; if (switchedToBulkPaint) { ExitBulkPaint(-1, -1); } } } /// protected void ClearSelection(int columnIndexException, int rowIndexException, bool selectExceptionElement) { switch (this.SelectionMode) { case DataGridViewSelectionMode.CellSelect: case DataGridViewSelectionMode.FullColumnSelect: case DataGridViewSelectionMode.ColumnHeaderSelect: { if (columnIndexException < 0 || columnIndexException >= this.Columns.Count) { throw new ArgumentOutOfRangeException("columnIndexException"); } break; } case DataGridViewSelectionMode.FullRowSelect: case DataGridViewSelectionMode.RowHeaderSelect: { if (columnIndexException < -1 || columnIndexException >= this.Columns.Count) { throw new ArgumentOutOfRangeException("columnIndexException"); } break; } } switch (this.SelectionMode) { case DataGridViewSelectionMode.CellSelect: case DataGridViewSelectionMode.FullRowSelect: case DataGridViewSelectionMode.RowHeaderSelect: { if (rowIndexException < 0 || rowIndexException >= this.Rows.Count) { throw new ArgumentOutOfRangeException("rowIndexException"); } break; } case DataGridViewSelectionMode.FullColumnSelect: case DataGridViewSelectionMode.ColumnHeaderSelect: { if (rowIndexException < -1 || rowIndexException >= this.Rows.Count) { throw new ArgumentOutOfRangeException("rowIndexException"); } break; } } // Clears all selection except the row/column/cell specified as parameter this.noDimensionChangeCount++; this.noSelectionChangeCount++; bool switchedToBulkPaint = false; if (this.selectedBandIndexes.Count > DATAGRIDVIEW_bulkPaintThreshold || this.individualSelectedCells.Count > DATAGRIDVIEW_bulkPaintThreshold) { this.inBulkPaintCount++; switchedToBulkPaint = true; } try { switch (this.SelectionMode) { case DataGridViewSelectionMode.CellSelect: { // If we change the design and start using this.selectedBandIndexes in this SelectionMode, // we'll have to clear those selections too. RemoveIndividuallySelectedCells(columnIndexException, rowIndexException); break; } case DataGridViewSelectionMode.FullRowSelect: case DataGridViewSelectionMode.RowHeaderSelect: { int bandIndex = 0; while (bandIndex < this.selectedBandIndexes.Count) { if (this.selectedBandIndexes[bandIndex] != rowIndexException) { // deselect currently selected row SetSelectedRowCore(this.selectedBandIndexes[bandIndex], false); } else { bandIndex++; } } if (this.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect) { RemoveIndividuallySelectedCells(columnIndexException, rowIndexException); } break; } case DataGridViewSelectionMode.FullColumnSelect: case DataGridViewSelectionMode.ColumnHeaderSelect: { int bandIndex = 0; while (bandIndex < this.selectedBandIndexes.Count) { if (this.selectedBandIndexes[bandIndex] != columnIndexException) { // deselect currently selected column SetSelectedColumnCore(this.selectedBandIndexes[bandIndex], false); } else { bandIndex++; } } if (this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect) { RemoveIndividuallySelectedCells(columnIndexException, rowIndexException); } break; } } if (selectExceptionElement) { SetSelectedElementCore(columnIndexException, rowIndexException, true); } } finally { this.noDimensionChangeCount--; Debug.Assert(this.noDimensionChangeCount >= 0); this.NoSelectionChangeCount--; if (switchedToBulkPaint) { ExitBulkPaint(-1, -1); } } } private bool ColumnEditable(int columnIndex) { Debug.Assert(columnIndex >= 0 && columnIndex < this.Columns.Count, "Invalid columnIndex: " + columnIndex ); if (this.Columns[columnIndex].IsDataBound && this.dataConnection != null && !this.dataConnection.AllowEdit) { return false; } return true; } private bool ColumnNeedsDisplayedState(DataGridViewColumn dataGridViewColumn) { Debug.Assert(dataGridViewColumn != null); if (!dataGridViewColumn.Visible) { return false; } if (dataGridViewColumn.Frozen) { DataGridViewColumn firstVisibleFrozenColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); Debug.Assert(firstVisibleFrozenColumn != null); if (firstVisibleFrozenColumn.Index == dataGridViewColumn.Index) { return this.displayedBandsInfo.NumDisplayedFrozenCols > 0; } Debug.Assert(this.Columns.DisplayInOrder(firstVisibleFrozenColumn.Index, dataGridViewColumn.Index)); return this.Columns.GetColumnCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen, firstVisibleFrozenColumn.Index, dataGridViewColumn.Index) < this.displayedBandsInfo.NumDisplayedFrozenCols; } else { int firstDisplayedScrollingColumnIndex = this.displayedBandsInfo.FirstDisplayedScrollingCol; if (firstDisplayedScrollingColumnIndex != -1) { if (firstDisplayedScrollingColumnIndex == dataGridViewColumn.Index) { return this.displayedBandsInfo.NumDisplayedScrollingCols > 0; } if (this.Columns.DisplayInOrder(firstDisplayedScrollingColumnIndex, dataGridViewColumn.Index)) { return this.Columns.GetColumnCount(DataGridViewElementStates.Visible, firstDisplayedScrollingColumnIndex, dataGridViewColumn.Index) < this.displayedBandsInfo.NumDisplayedScrollingCols; } } } return false; } private bool ColumnRelocationTarget(MouseEventArgs e, HitTestInfo hti, out int previousColumnIndex) { previousColumnIndex = -1; if (hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeadersResizeBottom || hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeader || hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnResizeLeft || hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnResizeRight || hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeaderLeft || hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeaderRight) { Debug.Assert(hti.col != -1); if (hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeadersResizeBottom || hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeader) { int xColumnLeftEdge = GetColumnXFromIndex(hti.col); int wColumn = this.Columns[hti.col].Width; if ((this.RightToLeftInternal && e.X < xColumnLeftEdge - wColumn / 2) || (!this.RightToLeftInternal && e.X > xColumnLeftEdge + wColumn / 2)) { // Insert column on the right of hti.col previousColumnIndex = hti.col; } else { // Insert column on the left of hti.col DataGridViewColumn dataGridViewColumnPrev = this.Columns.GetPreviousColumn(this.Columns[hti.col], DataGridViewElementStates.Visible, DataGridViewElementStates.None); if (dataGridViewColumnPrev != null) { previousColumnIndex = dataGridViewColumnPrev.Index; } } } else { previousColumnIndex = (hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnResizeRight || hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeaderRight) ? hti.col : hti.adjacentCol; } DataGridViewColumn dataGridViewColumnNext = null; if (previousColumnIndex != -1) { dataGridViewColumnNext = this.Columns.GetNextColumn(this.Columns[previousColumnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None); } if (this.trackColumn != previousColumnIndex && !(previousColumnIndex == -1 && hti.col == this.trackColumn) && (dataGridViewColumnNext == null || this.trackColumn != dataGridViewColumnNext.Index)) { return true; } } else if (hti.typeInternal == DataGridViewHitTestTypeInternal.FirstColumnHeaderLeft || hti.typeInternal == DataGridViewHitTestTypeInternal.TopLeftHeaderResizeRight) { Debug.Assert(hti.col != -1); if (hti.col != this.trackColumn) { return true; } } return false; } private static bool ColumnsDisplayInOrder(int columnIndex1, int columnDisplayIndex1, int columnIndex2, int columnDisplayIndex2) { return columnDisplayIndex1 < columnDisplayIndex2 || (columnDisplayIndex1 == columnDisplayIndex2 && columnIndex1 < columnIndex2); } /// public bool CommitEdit(DataGridViewDataErrorContexts context) { if (this.IsCurrentCellInEditMode) { DataGridViewCell dataGridViewCurrentCell = this.CurrentCellInternal; DataGridViewDataErrorEventArgs dgvdee = CommitEdit(ref dataGridViewCurrentCell, context, DataGridViewValidateCellInternal.Never, false /*fireCellLeave*/, false /*fireCellEnter*/, false /*fireRowLeave*/, false /*fireRowEnter*/, false /*fireLeave*/); if (null != dgvdee) { if (dgvdee.ThrowException) { throw dgvdee.Exception; } if (dgvdee.Cancel) { return false; } } } return true; } private DataGridViewDataErrorEventArgs CommitEdit(ref DataGridViewCell dataGridViewCurrentCell, DataGridViewDataErrorContexts context, DataGridViewValidateCellInternal validateCell, bool fireCellLeave, bool fireCellEnter, bool fireRowLeave, bool fireRowEnter, bool fireLeave) { if (validateCell == DataGridViewValidateCellInternal.Always) { Debug.Assert(this.ptCurrentCell.X > -1); if (fireCellLeave) { if (this.ptCurrentCell.X == -1) { return null; } OnCellLeave(ref dataGridViewCurrentCell, this.ptCurrentCell.X, this.ptCurrentCell.Y); } if (fireRowLeave) { if (this.ptCurrentCell.X == -1) { return null; } OnRowLeave(ref dataGridViewCurrentCell, this.ptCurrentCell.X, this.ptCurrentCell.Y); } if (fireLeave) { base.OnLeave(EventArgs.Empty); // [....]: can we be smarter about this? What if validating the current cell below forces a repaint on the cell? // we would end up repainting the current cell twice. // // invalidate the current cell so the data grid view does not paint the focus rectangle any longer if (this.ptCurrentCell.X > -1 && this.ptCurrentCell.Y > -1) { InvalidateCellPrivate(this.ptCurrentCell.X /*columnIndex*/, this.ptCurrentCell.Y /*rowIndex*/); } } // OnCellValidating returns true if the dev cancelled the validation. bool validateFormattedValue = CanValidateDataBoundDataGridViewCell(dataGridViewCurrentCell); if (validateFormattedValue) { if (this.ptCurrentCell.X == -1) { return null; } if (OnCellValidating(ref dataGridViewCurrentCell, this.ptCurrentCell.X, this.ptCurrentCell.Y, context)) { if (fireRowEnter) { if (this.ptCurrentCell.X == -1) { return null; } OnRowEnter(ref dataGridViewCurrentCell, this.ptCurrentCell.X, this.ptCurrentCell.Y, true /*canCreateNewRow*/, true /*validationFailureOccurred*/); } if (fireCellEnter) { if (this.ptCurrentCell.X == -1) { return null; } OnCellEnter(ref dataGridViewCurrentCell, this.ptCurrentCell.X, this.ptCurrentCell.Y); } if (this.ptCurrentCell.X == -1) { return null; } DataGridViewDataErrorEventArgs dgvdee = new DataGridViewDataErrorEventArgs(null, this.ptCurrentCell.X, this.ptCurrentCell.Y, // null, // null, context); dgvdee.Cancel = true; return dgvdee; } if (!this.IsCurrentCellInEditMode || !this.IsCurrentCellDirty) { if (this.ptCurrentCell.X == -1) { return null; } OnCellValidated(ref dataGridViewCurrentCell, this.ptCurrentCell.X, this.ptCurrentCell.Y); } } } if (this.ptCurrentCell.X == -1 || !this.IsCurrentCellInEditMode) { return null; } Debug.Assert( ( (this.editingControl != null && ((IDataGridViewEditingControl)this.editingControl).EditingControlValueChanged) || (this.dataGridViewState1[DATAGRIDVIEWSTATE1_currentCellInEditMode] && ((IDataGridViewEditingCell)this.CurrentCellInternal).EditingCellValueChanged) ) == this.IsCurrentCellDirty || this.dataGridViewState1[DATAGRIDVIEWSTATE1_ignoringEditingChanges]); if (this.IsCurrentCellDirty) { bool validateAndPushFormattedValue = CanValidateDataBoundDataGridViewCell(dataGridViewCurrentCell); if (validateAndPushFormattedValue) { if (validateCell == DataGridViewValidateCellInternal.WhenChanged) { Debug.Assert(this.ptCurrentCell.X > -1); if (this.ptCurrentCell.X == -1) { return null; } if (OnCellValidating(ref dataGridViewCurrentCell, this.ptCurrentCell.X, this.ptCurrentCell.Y, context)) { if (this.ptCurrentCell.X == -1) { return null; } DataGridViewDataErrorEventArgs dgvdee = new DataGridViewDataErrorEventArgs(null, this.ptCurrentCell.X, this.ptCurrentCell.Y, context); dgvdee.Cancel = true; return dgvdee; } } Exception exception; object formattedValue; if (this.editingControl != null) { formattedValue = ((IDataGridViewEditingControl)this.editingControl).GetEditingControlFormattedValue(context); } else { Debug.Assert(this.dataGridViewState1[DATAGRIDVIEWSTATE1_currentCellInEditMode]); formattedValue = ((IDataGridViewEditingCell)this.CurrentCellInternal).GetEditingCellFormattedValue(context); } if (!PushFormattedValue(ref dataGridViewCurrentCell, formattedValue, out exception)) { if (this.ptCurrentCell.X == -1) { return null; } DataGridViewDataErrorEventArgs dgvdee = new DataGridViewDataErrorEventArgs(exception, this.ptCurrentCell.X, this.ptCurrentCell.Y, // dataGridViewCurrentCell.Value, // formattedValue, context); dgvdee.Cancel = true; OnDataErrorInternal(dgvdee); return dgvdee; } if (!this.IsCurrentCellInEditMode) { return null; } this.uneditedFormattedValue = formattedValue; } if (this.editingControl != null) { ((IDataGridViewEditingControl) this.editingControl).EditingControlValueChanged = false; } else { Debug.Assert(this.dataGridViewState1[DATAGRIDVIEWSTATE1_currentCellInEditMode]); ((IDataGridViewEditingCell) this.CurrentCellInternal).EditingCellValueChanged = false; } this.IsCurrentCellDirtyInternal = false; this.IsCurrentRowDirtyInternal = true; if (validateAndPushFormattedValue) { if (validateCell == DataGridViewValidateCellInternal.Always || validateCell == DataGridViewValidateCellInternal.WhenChanged) { if (this.ptCurrentCell.X == -1) { return null; } OnCellValidated(ref dataGridViewCurrentCell, this.ptCurrentCell.X, this.ptCurrentCell.Y); } } } return null; } private bool CommitEdit(DataGridViewDataErrorContexts context, bool forCurrentCellChange, bool forCurrentRowChange) { // If we're already within a CellValidating event handler, don't try to commit the cell again. if (this.dataGridViewOper[DATAGRIDVIEWOPER_inCellValidating]) { return false; } DataGridViewCell dataGridViewCurrentCell = this.CurrentCellInternal; DataGridViewDataErrorEventArgs dgvdee = CommitEdit(ref dataGridViewCurrentCell, context, forCurrentCellChange ? DataGridViewValidateCellInternal.Always : DataGridViewValidateCellInternal.WhenChanged /*validateCell*/, forCurrentCellChange /*fireCellLeave*/, forCurrentCellChange /*fireCellEnter*/, forCurrentRowChange /*fireRowLeave*/, forCurrentRowChange /*fireRowEnter*/, false /*fireLeave*/); if (null != dgvdee) { if (dgvdee.ThrowException) { throw dgvdee.Exception; } if (dgvdee.Cancel) { return false; } dgvdee = CancelEditPrivate(/*ref dataGridViewCurrentCell, DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.Scroll*/); // restore old value if (null != dgvdee) { if (dgvdee.ThrowException) { throw dgvdee.Exception; } if (dgvdee.Cancel) { return false; } } } // See if we can leave the row if (forCurrentRowChange && forCurrentCellChange) { Debug.Assert(this.ptCurrentCell.X > -1); if (this.ptCurrentCell.X == -1) { return false; } int columnIndex = this.ptCurrentCell.X; int rowIndex = this.ptCurrentCell.Y; // OnRowValidating returns true when the row validation was cancelled. if (OnRowValidating(ref dataGridViewCurrentCell, columnIndex, rowIndex)) { if (IsInnerCellOutOfBounds(columnIndex, rowIndex)) { return false; } OnRowEnter(ref dataGridViewCurrentCell, columnIndex, rowIndex, true /*canCreateNewRow*/, true /*validationFailureOccurred*/); if (IsInnerCellOutOfBounds(columnIndex, rowIndex)) { return false; } OnCellEnter(ref dataGridViewCurrentCell, columnIndex, rowIndex); return false; } if (IsInnerCellOutOfBounds(columnIndex, rowIndex)) { return false; } OnRowValidated(ref dataGridViewCurrentCell, columnIndex, rowIndex); } return true; } private bool CommitEditForOperation(int columnIndex, int rowIndex, bool forCurrentCellChange) { if (forCurrentCellChange) { if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.CurrentCellChange, DataGridViewValidateCellInternal.Always /*validateCell*/, true /*fireCellLeave*/, true /*fireCellEnter*/, this.ptCurrentCell.Y != rowIndex /*fireRowLeave*/, this.ptCurrentCell.Y != rowIndex /*fireRowEnter*/, false /*fireLeave*/, this.EditMode != DataGridViewEditMode.EditOnEnter /*keepFocus*/, false /*resetCurrentCell*/, false /*resetAnchorCell unused here*/)) { return false; } if (this.ptCurrentCell.Y != rowIndex && this.ptCurrentCell.Y != -1) { DataGridViewCell dataGridViewCellTmp = null; int columnIndexTmp = this.ptCurrentCell.X; int rowIndexTmp = this.ptCurrentCell.Y; if (OnRowValidating(ref dataGridViewCellTmp, columnIndexTmp, rowIndexTmp)) { // Row validation was cancelled if (IsInnerCellOutOfBounds(columnIndexTmp, rowIndexTmp)) { return false; } OnRowEnter(ref dataGridViewCellTmp, columnIndexTmp, rowIndexTmp, true /*canCreateNewRow*/, true /*validationFailureOccurred*/); if (IsInnerCellOutOfBounds(columnIndexTmp, rowIndexTmp)) { return false; } OnCellEnter(ref dataGridViewCellTmp, columnIndexTmp, rowIndexTmp); if (IsInnerCellOutOfBounds(columnIndexTmp, rowIndexTmp)) { return false; } // Re-enter editing mode if needed if (this.Focused && (!this.IsCurrentCellInEditMode && (this.EditMode == DataGridViewEditMode.EditOnEnter || (this.EditMode != DataGridViewEditMode.EditProgrammatically && this.CurrentCellInternal.EditType == null)))) { BeginEditInternal(true /*selectAll*/); } return false; } if (IsInnerCellOutOfBounds(columnIndexTmp, rowIndexTmp)) { return false; } OnRowValidated(ref dataGridViewCellTmp, columnIndexTmp, rowIndexTmp); } } else { if (!CommitEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.Scroll, false /*forCurrentCellChange*/, this.ptCurrentCell.Y != rowIndex /*forCurrentRowChange*/)) { return false; } } // Row validation was not cancelled, but operation needs to be re-evaluated. Debug.Assert(columnIndex < this.Columns.Count); if (IsColumnOutOfBounds(columnIndex)) { return false; } if (rowIndex >= this.Rows.Count) { // CurrentCell was reset because the commit deleted row(s). // Since the user wants to change the current cell, we don't // want to end up with no CurrentCell. We pick the last visible // row in the grid which may be the 'new row'. int lastVisibleRowIndex = this.Rows.GetLastRow(DataGridViewElementStates.Visible); if (forCurrentCellChange && this.ptCurrentCell.X == -1 && lastVisibleRowIndex != -1) { bool success = SetAndSelectCurrentCellAddress(columnIndex, lastVisibleRowIndex, true, false, false, false /*clearSelection*/, false /*forceCurrentCellSelection*/); Debug.Assert(success); } // Interrupt operation because it has become invalid. return false; } if (rowIndex > -1 && (this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Visible) == 0) { // Interrupt operation because target row has become invisible. return false; } return true; } internal void CompleteCellsCollection(DataGridViewRow dataGridViewRow) { Debug.Assert(dataGridViewRow != null); int cellsInCollection = dataGridViewRow.Cells.Count; if (this.Columns.Count > cellsInCollection) { int cellCount = 0; DataGridViewCell[] cells = new DataGridViewCell[this.Columns.Count - cellsInCollection]; for (int columnIndex = cellsInCollection; columnIndex < this.Columns.Count; columnIndex++) { if (this.Columns[columnIndex].CellTemplate == null) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_AColumnHasNoCellTemplate)); } DataGridViewCell dgvcNew = (DataGridViewCell) this.Columns[columnIndex].CellTemplate.Clone(); cells[cellCount] = dgvcNew; cellCount ++; } dataGridViewRow.Cells.AddRange(cells); } } /// /// Determines which column is the first visible scrolling /// column given the object's horizontalOffset. /// private int ComputeFirstVisibleScrollingColumn() { if (this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen) >= this.layout.Data.Width) { // Not enough room for scrolling columns. this.negOffset = 0; return -1; } DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); if (this.horizontalOffset == 0) { this.negOffset = 0; return (dataGridViewColumn == null) ? -1 : dataGridViewColumn.Index; } int cx = 0; while (dataGridViewColumn != null) { cx += dataGridViewColumn.Thickness; if (cx > this.horizontalOffset) { break; } dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); } if (dataGridViewColumn == null) { Debug.Assert(cx <= this.horizontalOffset); dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); if (dataGridViewColumn == null) { this.negOffset = 0; return -1; } else { if (this.negOffset != this.horizontalOffset) { this.negOffset = 0; } return dataGridViewColumn.Index; } } else { this.negOffset = dataGridViewColumn.Thickness - (cx - this.horizontalOffset); return dataGridViewColumn.Index; } } private int ComputeHeightOfFittingTrailingScrollingRows(int totalVisibleFrozenHeight) { // int displayHeight = this.layout.Data.Height - totalVisibleFrozenHeight; int rowHeight = 0, rowHeights = 0; int indexTmp = this.Rows.Count; if (indexTmp == 0 || displayHeight <= 0) { return 0; } else { indexTmp--; } DataGridViewElementStates rowState = this.Rows.GetRowState(indexTmp); if ((rowState & DataGridViewElementStates.Frozen) != 0) { return 0; } if ((rowState & DataGridViewElementStates.Visible) == 0) { indexTmp = this.Rows.GetPreviousRow(indexTmp, DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); } if (indexTmp != -1) { rowHeight = this.Rows.SharedRow(indexTmp).GetHeight(indexTmp); if (rowHeight > displayHeight) { return rowHeight; } } while (indexTmp != -1 && rowHeights + rowHeight <= displayHeight) { rowHeights += rowHeight; indexTmp = this.Rows.GetPreviousRow(indexTmp, DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); if (indexTmp != -1) { rowHeight = this.Rows.SharedRow(indexTmp).GetHeight(indexTmp); } } return rowHeights; } private int ComputeHeightOfScrolledOffRows() { // int height = 0; if (this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0) { int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); if (rowIndex != -1) { while (rowIndex != this.displayedBandsInfo.FirstDisplayedScrollingRow) { Debug.Assert(rowIndex < this.displayedBandsInfo.FirstDisplayedScrollingRow); height += this.Rows.SharedRow(rowIndex).GetHeight(rowIndex); rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible); } } } return height; } private int ComputeHeightOfTrailingScrollingRows() { if (this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0) { int lastVisibleRowIndex = this.Rows.GetLastRow(DataGridViewElementStates.Visible); return this.Rows.GetRowsHeight(DataGridViewElementStates.Visible, this.displayedBandsInfo.FirstDisplayedScrollingRow, lastVisibleRowIndex) + this.Rows.SharedRow(lastVisibleRowIndex).GetHeight(lastVisibleRowIndex); } return 0; } private bool ComputeLayout() { ClearRegionCache(); LayoutData newLayout = new LayoutData(this.layout); Rectangle oldResizeRect = this.layout.ResizeBoxRect; // Inside region if (this.normalClientRectangle.Width > 0 || this.normalClientRectangle.Height > 0) { newLayout.Inside = this.normalClientRectangle; } else { newLayout.Inside = this.ClientRectangle; } Rectangle inside = newLayout.Inside; int borderWidth = this.BorderWidth; inside.Inflate(-borderWidth, -borderWidth); if (inside.Height < 0) { inside.Height = 0; } if (inside.Width < 0) { inside.Width = 0; } Rectangle insideLeft = inside; // Headers if (this.layout.ColumnHeadersVisible) { Rectangle colHeaders = insideLeft; colHeaders.Height = Math.Min(this.columnHeadersHeight, colHeaders.Height); insideLeft.Y += colHeaders.Height; insideLeft.Height -= colHeaders.Height; Debug.Assert(insideLeft.Height >= 0); newLayout.ColumnHeaders = colHeaders; } else { newLayout.ColumnHeaders = Rectangle.Empty; } if (this.layout.RowHeadersVisible) { Rectangle rowHeaders = insideLeft; rowHeaders.Width = Math.Min(this.rowHeadersWidth, rowHeaders.Width); if (this.RightToLeftInternal) { rowHeaders.X += insideLeft.Width - rowHeaders.Width; } else { insideLeft.X += rowHeaders.Width; } insideLeft.Width -= rowHeaders.Width; Debug.Assert(insideLeft.Width >= 0); newLayout.RowHeaders = rowHeaders; if (this.layout.ColumnHeadersVisible) { Rectangle topLeft; Rectangle colHeaders = newLayout.ColumnHeaders; topLeft = colHeaders; topLeft.Width = Math.Min(this.rowHeadersWidth, topLeft.Width); colHeaders.Width -= topLeft.Width; if (this.RightToLeftInternal) { topLeft.X += insideLeft.Width; } else { colHeaders.X += topLeft.Width; } Debug.Assert(colHeaders.Width >= 0); newLayout.TopLeftHeader = topLeft; newLayout.ColumnHeaders = colHeaders; } else { newLayout.TopLeftHeader = Rectangle.Empty; } } else { newLayout.RowHeaders = Rectangle.Empty; newLayout.TopLeftHeader = Rectangle.Empty; } // Adjust insideLeft in case static top / left edge needs to be painted if (this.SingleVerticalBorderAdded) { if (!this.RightToLeftInternal) { insideLeft.X++; } if (insideLeft.Width > 0) { insideLeft.Width--; } } if (this.SingleHorizontalBorderAdded) { insideLeft.Y++; if (insideLeft.Height > 0) { insideLeft.Height--; } } // Data region newLayout.Data = insideLeft; newLayout.Inside = inside; Debug.Assert(newLayout.Data.X >= 0); Debug.Assert(newLayout.Data.Y >= 0); Debug.Assert(newLayout.Data.Width >= 0); Debug.Assert(newLayout.Data.Height >= 0); this.layout = newLayout; this.layout.dirty = false; bool columnsAdjusted = AdjustFillingColumns(); this.layout = newLayout; Debug.Assert(!this.layout.dirty); LayoutScrollBars(); // if the user shrank the grid client area, then OnResize invalidated the old // resize area. however, we need to invalidate the left upper corner in the new ResizeArea // note that we can't take the Invalidate call from the OnResize method, because if the // user enlarges the form then the old area will not be invalidated. // if (!oldResizeRect.Equals(this.layout.ResizeBoxRect) && !this.layout.ResizeBoxRect.IsEmpty) { Invalidate(this.layout.ResizeBoxRect); } return columnsAdjusted; } private void ComputeLayoutShortcut(bool computeVisibleRows) { // Called instead of ComputeLayout when a row is added, inserted or deleted beyond the limits of // the layout.Data area. // this.layout is unchanged - only the potential vertical scrollbar is affected. if (computeVisibleRows) { ComputeVisibleRows(); } #if DEBUG else { int oldNumTotallyVisibleFrozenRows = this.displayedBandsInfo.NumTotallyDisplayedFrozenRows; int oldNumVisibleScrollingRows = this.displayedBandsInfo.NumDisplayedScrollingRows; int oldNumTotallyVisibleScrollingRows = this.displayedBandsInfo.NumTotallyDisplayedScrollingRows; int oldFirstVisibleScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow; ComputeVisibleRows(); Debug.Assert(oldNumTotallyVisibleFrozenRows == this.displayedBandsInfo.NumTotallyDisplayedFrozenRows); Debug.Assert(oldNumVisibleScrollingRows == this.displayedBandsInfo.NumDisplayedScrollingRows); Debug.Assert(oldNumTotallyVisibleScrollingRows == this.displayedBandsInfo.NumTotallyDisplayedScrollingRows); Debug.Assert(oldFirstVisibleScrollingRow == this.displayedBandsInfo.FirstDisplayedScrollingRow); } #endif #if DEBUG int newFirstVisibleScrollingCol = ComputeFirstVisibleScrollingColumn(); Debug.Assert(newFirstVisibleScrollingCol == this.displayedBandsInfo.FirstDisplayedScrollingCol); int oldLastTotallyVisibleScrollingCol = this.displayedBandsInfo.LastTotallyDisplayedScrollingCol; int oldFirstVisibleScrollingCol = this.displayedBandsInfo.FirstDisplayedScrollingCol; ComputeVisibleColumns(); Debug.Assert(oldLastTotallyVisibleScrollingCol == this.displayedBandsInfo.LastTotallyDisplayedScrollingCol); Debug.Assert(oldFirstVisibleScrollingCol == this.displayedBandsInfo.FirstDisplayedScrollingCol); #endif if (this.vertScrollBar.Enabled) { int totalVisibleHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible); int totalVisibleFrozenHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); int oldVertScrollBarValue = this.vertScrollBar.Value; int oldThumbHeight = Math.Max(((this.vertScrollBar.Height - 2*SystemInformation.VerticalScrollBarArrowHeight) * this.vertScrollBar.LargeChange) / this.vertScrollBar.Maximum, 8); this.vertScrollBar.Maximum = totalVisibleHeight - totalVisibleFrozenHeight; Debug.Assert(this.vertScrollBar.Maximum > 0); this.vertScrollBar.Value = ComputeHeightOfScrolledOffRows(); this.vertScrollBar.LargeChange = this.layout.Data.Height - totalVisibleFrozenHeight; this.verticalOffset = this.vertScrollBar.Value; if (this.vertScrollBar.Visible && (oldVertScrollBarValue != this.verticalOffset || oldThumbHeight != Math.Max(((this.vertScrollBar.Height - 2*SystemInformation.VerticalScrollBarArrowHeight) * this.vertScrollBar.LargeChange) / this.vertScrollBar.Maximum, 8))) { // Only update the vertical scroll bar is the thumb moved or resized. this.vertScrollBar.Invalidate(); } Debug.Assert(this.verticalOffset == this.vertScrollBar.Value); } } /* Unused for now private int ComputeScrolledOffRowCount(int scrolledOffRowsHeight) { int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); if (rowIndex == -1) { // No scrolling rows return 0; } else { int height = 0; int rowCount = 0; while (rowIndex != -1 && height < scrolledOffRowsHeight) { height += this.Rows.SharedRow(rowIndex).GetHeight(rowIndex); if (height <= scrolledOffRowsHeight) { rowCount++; } rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible); } return rowCount; } } */ private void ComputeVisibleColumns() { DataGridViewColumn dataGridViewColumn = null; int numVisibleScrollingCols = 0, visibleScrollingColumnsTmp = 0; int displayWidth = this.layout.Data.Width, cx = 0; int numDisplayedFrozenCols = 0, firstDisplayedFrozenCol = -1, lastDisplayedFrozenCol = -1; int firstDisplayedScrollingCol = this.displayedBandsInfo.FirstDisplayedScrollingCol; // the same problem with negative numbers: // if the width passed in is negative, then return 0 if (displayWidth <= 0 || this.Columns.GetColumnCount(DataGridViewElementStates.Visible) == 0) { this.displayedBandsInfo.FirstDisplayedFrozenCol = -1; this.displayedBandsInfo.NumDisplayedFrozenCols = 0; this.displayedBandsInfo.FirstDisplayedScrollingCol = -1; this.displayedBandsInfo.NumDisplayedScrollingCols = 0; this.displayedBandsInfo.LastDisplayedFrozenCol = -1; this.displayedBandsInfo.LastTotallyDisplayedScrollingCol = -1; return; } dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.None); while (dataGridViewColumn != null) { if (!dataGridViewColumn.Frozen && dataGridViewColumn.Visible) { break; } if (dataGridViewColumn.Visible) { if (firstDisplayedFrozenCol == -1) { firstDisplayedFrozenCol = dataGridViewColumn.Index; } cx += dataGridViewColumn.Width; numDisplayedFrozenCols++; lastDisplayedFrozenCol = dataGridViewColumn.Index; if (cx >= displayWidth) { break; } } dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.None, DataGridViewElementStates.None); } Debug.Assert(cx <= this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen)); if (cx < displayWidth && firstDisplayedScrollingCol >= 0) { dataGridViewColumn = this.Columns[firstDisplayedScrollingCol]; if (dataGridViewColumn.Frozen) { dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); this.negOffset = 0; if (dataGridViewColumn == null) { this.displayedBandsInfo.FirstDisplayedFrozenCol = firstDisplayedFrozenCol; this.displayedBandsInfo.LastDisplayedFrozenCol = lastDisplayedFrozenCol; this.displayedBandsInfo.NumDisplayedFrozenCols = numDisplayedFrozenCols; this.displayedBandsInfo.FirstDisplayedScrollingCol = this.displayedBandsInfo.LastTotallyDisplayedScrollingCol = -1; this.displayedBandsInfo.NumDisplayedScrollingCols = 0; return; } else { firstDisplayedScrollingCol = dataGridViewColumn.Index; } } cx -= this.negOffset; while (cx < displayWidth && dataGridViewColumn != null) { cx += dataGridViewColumn.Thickness; visibleScrollingColumnsTmp++; dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); } numVisibleScrollingCols = visibleScrollingColumnsTmp; // if we inflate the data area then we paint columns to the left of firstDisplayedScrollingCol if (cx < displayWidth) { bool invalidate = false; Debug.Assert(firstDisplayedScrollingCol >= 0); //first minimize value of this.negOffset if (this.negOffset > 0) { invalidate = true; if (displayWidth - cx > this.negOffset) { cx += this.negOffset; this.horizontalOffset -= this.negOffset; this.negOffset = 0; } else { this.horizontalOffset -= displayWidth - cx; this.negOffset -= displayWidth - cx; cx = displayWidth; } } // second try to scroll entire columns if (cx < displayWidth && this.horizontalOffset > 0) { Debug.Assert(this.negOffset == 0); dataGridViewColumn = this.Columns.GetPreviousColumn((this.Columns[firstDisplayedScrollingCol]), DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); while (dataGridViewColumn != null && cx + dataGridViewColumn.Thickness <= displayWidth) { cx += dataGridViewColumn.Thickness; visibleScrollingColumnsTmp++; invalidate = true; firstDisplayedScrollingCol = dataGridViewColumn.Index; this.horizontalOffset -= dataGridViewColumn.Thickness; dataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); } } // third try to partially scroll in first scrolled off column if (cx < displayWidth && this.horizontalOffset > 0 && firstDisplayedScrollingCol != 0) { Debug.Assert(this.negOffset == 0); dataGridViewColumn = this.Columns.GetPreviousColumn((this.Columns[firstDisplayedScrollingCol]), DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); Debug.Assert(dataGridViewColumn != null); Debug.Assert(dataGridViewColumn.Thickness > displayWidth - cx); firstDisplayedScrollingCol = dataGridViewColumn.Index; this.negOffset = dataGridViewColumn.Thickness - displayWidth + cx; this.horizontalOffset -= displayWidth - cx; visibleScrollingColumnsTmp++; invalidate = true; cx = displayWidth; Debug.Assert(this.negOffset == GetNegOffsetFromHorizontalOffset(this.horizontalOffset)); } // update the number of visible columns to the new reality Debug.Assert(numVisibleScrollingCols <= visibleScrollingColumnsTmp, "the number of displayed columns can only grow"); numVisibleScrollingCols = visibleScrollingColumnsTmp; if (invalidate) { InvalidateData(); Invalidate(this.layout.ColumnHeaders); } } int jumpFromFirstVisibleScrollingCol = numVisibleScrollingCols - 1; if (cx > displayWidth) { jumpFromFirstVisibleScrollingCol--; } Debug.Assert(jumpFromFirstVisibleScrollingCol >= -1); if (jumpFromFirstVisibleScrollingCol < 0) { this.displayedBandsInfo.LastTotallyDisplayedScrollingCol = -1; // no totally visible scrolling column at all } else { Debug.Assert(firstDisplayedScrollingCol >= 0); dataGridViewColumn = this.Columns[firstDisplayedScrollingCol]; for (int jump = 0; jump < jumpFromFirstVisibleScrollingCol; jump++) { dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); Debug.Assert(dataGridViewColumn != null); } this.displayedBandsInfo.LastTotallyDisplayedScrollingCol = dataGridViewColumn.Index; } } else { this.displayedBandsInfo.LastTotallyDisplayedScrollingCol = -1; } this.displayedBandsInfo.FirstDisplayedFrozenCol = firstDisplayedFrozenCol; this.displayedBandsInfo.LastDisplayedFrozenCol = lastDisplayedFrozenCol; this.displayedBandsInfo.NumDisplayedFrozenCols = numDisplayedFrozenCols; this.displayedBandsInfo.FirstDisplayedScrollingCol = firstDisplayedScrollingCol; this.displayedBandsInfo.NumDisplayedScrollingCols = numVisibleScrollingCols; Debug.Assert((this.displayedBandsInfo.NumDisplayedScrollingCols > 0 && this.displayedBandsInfo.FirstDisplayedScrollingCol != -1) || (this.displayedBandsInfo.NumDisplayedScrollingCols == 0 && this.displayedBandsInfo.FirstDisplayedScrollingCol == -1)); } private void ComputeVisibleRows() { int firstDisplayedFrozenRow = -1; int firstDisplayedScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow; int lastDisplayedFrozenRow = -1, lastDisplayedScrollingRow = -1; int numTotallyDisplayedFrozenRows = 0; int displayHeight = this.layout.Data.Height; int cy = 0; int visibleScrollingRows = 0; int nRows = this.Rows.Count; int rowIndex; // when minimizing the dataGridView window, we will get negative values for the // layout.Data.Width and layout.Data.Height ( is this a bug or not? if layout.Data.Height == 0 in that case, // the old code would have worked ) // // if this is the case, set numTotallyDisplayedFrozenRows = numDisplayedScrollingRows = numTotallyDisplayedScrollingRows = 0; // if (displayHeight <= 0 || nRows == 0) { this.displayedBandsInfo.NumDisplayedFrozenRows = this.displayedBandsInfo.NumTotallyDisplayedFrozenRows = this.displayedBandsInfo.NumDisplayedScrollingRows = this.displayedBandsInfo.NumTotallyDisplayedScrollingRows = 0; this.displayedBandsInfo.FirstDisplayedFrozenRow = this.displayedBandsInfo.FirstDisplayedScrollingRow = this.displayedBandsInfo.LastDisplayedFrozenRow = this.displayedBandsInfo.LastDisplayedScrollingRow = -1; return; } for (rowIndex = 0; rowIndex < nRows; rowIndex++) { Debug.Assert(cy < displayHeight); DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex); if ((rowState & DataGridViewElementStates.Frozen) == 0 && (rowState & DataGridViewElementStates.Visible) != 0) { break; } if ((rowState & DataGridViewElementStates.Visible) != 0) { cy += this.Rows.SharedRow(rowIndex).GetHeight(rowIndex); if (firstDisplayedFrozenRow == -1) { firstDisplayedFrozenRow = rowIndex; } lastDisplayedFrozenRow = rowIndex; if (cy <= displayHeight) { numTotallyDisplayedFrozenRows++; } if (cy >= displayHeight) { break; } } } if (cy > displayHeight) { this.displayedBandsInfo.NumDisplayedFrozenRows = numTotallyDisplayedFrozenRows + 1; } else { this.displayedBandsInfo.NumDisplayedFrozenRows = numTotallyDisplayedFrozenRows; } // loop exited when: // - all rows are frozen and fit in displayHeight: rowIndex == nRows, cy <= displayHeight // - rowIndex is not frozen: rowIndex < nRows, cy <= displayHeight // - there are more frozen rows than can fit in displayHeight: rowIndex <= nRows, cy > displayHeight if (cy < displayHeight && rowIndex < nRows) { if (firstDisplayedScrollingRow == -1) { firstDisplayedScrollingRow = rowIndex; } while (firstDisplayedScrollingRow < nRows && ( (this.Rows.GetRowState(firstDisplayedScrollingRow) & DataGridViewElementStates.Frozen) != 0 || (this.Rows.GetRowState(firstDisplayedScrollingRow) & DataGridViewElementStates.Visible) == 0 ) ) { firstDisplayedScrollingRow++; } for (int i = firstDisplayedScrollingRow; i < nRows; i++) { if ((this.Rows.GetRowState(i) & DataGridViewElementStates.Visible) != 0) { cy += this.Rows.SharedRow(i).GetHeight(i); visibleScrollingRows++; lastDisplayedScrollingRow = i; } if (cy >= displayHeight) { break; } } if (cy < displayHeight) { for (int i = firstDisplayedScrollingRow - 1; i >= numTotallyDisplayedFrozenRows; i--) { if ((this.Rows.GetRowState(i) & (DataGridViewElementStates.Frozen | DataGridViewElementStates.Visible)) == DataGridViewElementStates.Visible) { int height = this.Rows.SharedRow(i).GetHeight(i); if (cy + height > displayHeight) { break; } cy += height; firstDisplayedScrollingRow = i; visibleScrollingRows++; lastDisplayedScrollingRow = i; } } } this.displayedBandsInfo.NumDisplayedScrollingRows = visibleScrollingRows; if (cy > displayHeight) { this.displayedBandsInfo.NumTotallyDisplayedScrollingRows = visibleScrollingRows - 1; } else { this.displayedBandsInfo.NumTotallyDisplayedScrollingRows = visibleScrollingRows; } if (visibleScrollingRows == 0) { firstDisplayedScrollingRow = -1; Debug.Assert(lastDisplayedScrollingRow == -1); } } else { this.displayedBandsInfo.NumDisplayedScrollingRows = this.displayedBandsInfo.NumTotallyDisplayedScrollingRows = 0; firstDisplayedScrollingRow = -1; } Debug.Assert(firstDisplayedFrozenRow < nRows, "firstDisplayedFrozenRow larger than number of rows"); Debug.Assert(lastDisplayedFrozenRow < nRows, "lastDisplayedFrozenRow larger than number of rows"); Debug.Assert(lastDisplayedScrollingRow < nRows, "lastDisplayedScrollingRow larger than number of rows"); this.displayedBandsInfo.FirstDisplayedFrozenRow = firstDisplayedFrozenRow; this.displayedBandsInfo.FirstDisplayedScrollingRow = firstDisplayedScrollingRow; this.displayedBandsInfo.NumTotallyDisplayedFrozenRows = numTotallyDisplayedFrozenRows; this.displayedBandsInfo.LastDisplayedFrozenRow = lastDisplayedFrozenRow; this.displayedBandsInfo.LastDisplayedScrollingRow = lastDisplayedScrollingRow; Debug.Assert(this.displayedBandsInfo.NumTotallyDisplayedFrozenRows >= 0, "the number of visible frozen rows can't be negative"); Debug.Assert(this.displayedBandsInfo.NumDisplayedScrollingRows >= 0, "the number of visible scrolling rows can't be negative"); Debug.Assert(this.displayedBandsInfo.NumTotallyDisplayedScrollingRows >= 0, "the number of totally visible scrolling rows can't be negative"); Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow < nRows, "firstDisplayedScrollingRow larger than number of rows"); } private Point ConvertCellToGridCoord(int columnIndex, int rowIndex, int x, int y) { int columnX, rowY; if (columnIndex > -1) { columnX = GetColumnXFromIndex(columnIndex); if (this.RightToLeftInternal) { columnX -= this.Columns[columnIndex].Width; } } else { if (this.RightToLeftInternal) { columnX = this.layout.RowHeaders.Left - 1; } else { columnX = this.layout.RowHeaders.Left; } } if (rowIndex > -1) { rowY = GetRowYFromIndex(rowIndex); } else { rowY = this.layout.ColumnHeaders.Top; } return new Point(columnX + x, rowY + y); } private void CorrectColumnDisplayIndexesAfterDeletion(DataGridViewColumn dataGridViewColumn) { // Column indexes have already been adjusted. // This column has already been detached and has retained its old Index and DisplayIndex Debug.Assert(dataGridViewColumn != null); Debug.Assert(dataGridViewColumn.DataGridView == null); Debug.Assert(dataGridViewColumn.Index >= 0); Debug.Assert(dataGridViewColumn.DisplayIndex >= 0); try { this.dataGridViewOper[DATAGRIDVIEWOPER_inDisplayIndexAdjustments] = true; // All remaining columns with a DisplayIndex greater than dataGridViewColumn.DisplayIndex need to be decremented foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns) { if (dataGridViewColumnTmp.DisplayIndex > dataGridViewColumn.DisplayIndex) { dataGridViewColumnTmp.DisplayIndexInternal = dataGridViewColumnTmp.DisplayIndex - 1; dataGridViewColumnTmp.DisplayIndexHasChanged = true; // OnColumnDisplayIndexChanged needs to be raised later on } } #if DEBUG Debug.Assert(this.Columns.VerifyColumnDisplayIndexes()); #endif // Now raise all the OnColumnDisplayIndexChanged events FlushDisplayIndexChanged(true /*raiseEvent*/); } finally { this.dataGridViewOper[DATAGRIDVIEWOPER_inDisplayIndexAdjustments] = false; FlushDisplayIndexChanged(false /*raiseEvent*/); } } private void CorrectColumnDisplayIndexesAfterInsertion(DataGridViewColumn dataGridViewColumn) { Debug.Assert(dataGridViewColumn != null); Debug.Assert(dataGridViewColumn.DataGridView == this); // dataGridViewColumn.DisplayIndex has been set already. Debug.Assert(dataGridViewColumn.DisplayIndex >= 0); Debug.Assert(dataGridViewColumn.DisplayIndex < this.Columns.Count); try { this.dataGridViewOper[DATAGRIDVIEWOPER_inDisplayIndexAdjustments] = true; // All other columns with a DisplayIndex equal or greater than dataGridViewColumn.DisplayIndex need to be incremented foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns) { if (dataGridViewColumnTmp != dataGridViewColumn && dataGridViewColumnTmp.DisplayIndex >= dataGridViewColumn.DisplayIndex) { dataGridViewColumnTmp.DisplayIndexInternal = dataGridViewColumnTmp.DisplayIndex + 1; dataGridViewColumnTmp.DisplayIndexHasChanged = true; // OnColumnDisplayIndexChanged needs to be raised later on } } #if DEBUG Debug.Assert(this.Columns.VerifyColumnDisplayIndexes()); #endif // Now raise all the OnColumnDisplayIndexChanged events FlushDisplayIndexChanged(true /*raiseEvent*/); } finally { this.dataGridViewOper[DATAGRIDVIEWOPER_inDisplayIndexAdjustments] = false; FlushDisplayIndexChanged(false /*raiseEvent*/); } } private void CorrectColumnFrozenState(DataGridViewColumn dataGridViewColumn, int anticipatedColumnIndex) { Debug.Assert(dataGridViewColumn != null); Debug.Assert(anticipatedColumnIndex >= 0 && anticipatedColumnIndex <= this.Columns.Count); int anticipatedColumnDisplayIndex; if (dataGridViewColumn.DisplayIndex == -1 || dataGridViewColumn.DisplayIndex > this.Columns.Count) { anticipatedColumnDisplayIndex = anticipatedColumnIndex; // By default, we pick the Index as the DisplayIndex. } else { Debug.Assert(dataGridViewColumn.DisplayIndex >= 0 && dataGridViewColumn.DisplayIndex <= this.Columns.Count); anticipatedColumnDisplayIndex = dataGridViewColumn.DisplayIndex; // The specified DisplayIndex is just fine. } DataGridViewColumn dataGridViewColumnPrev; int displayIndex = anticipatedColumnDisplayIndex-1; do { dataGridViewColumnPrev = this.Columns.GetColumnAtDisplayIndex(displayIndex); displayIndex--; } while (displayIndex >= 0 && (dataGridViewColumnPrev == null || !dataGridViewColumnPrev.Visible)); if (dataGridViewColumnPrev != null && !dataGridViewColumnPrev.Frozen && dataGridViewColumn.Frozen) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddFrozenColumn)); } else { DataGridViewColumn dataGridViewColumnNext; displayIndex = anticipatedColumnDisplayIndex; do { dataGridViewColumnNext = this.Columns.GetColumnAtDisplayIndex(displayIndex); displayIndex++; } while (displayIndex < this.Columns.Count && (dataGridViewColumnNext == null || !dataGridViewColumnNext.Visible)); if (dataGridViewColumnNext != null && dataGridViewColumnNext.Frozen && !dataGridViewColumn.Frozen) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddNonFrozenColumn)); } } } private void CorrectColumnFrozenStates(DataGridViewColumn[] dataGridViewColumns) { DataGridView dataGridViewTmp = new DataGridView(); DataGridViewColumn dataGridViewColumnClone; foreach (DataGridViewColumn dataGridViewColumn in this.Columns) { dataGridViewColumnClone = (DataGridViewColumn) dataGridViewColumn.Clone(); // DataGridViewColumn.Clone does not replicate the DisplayIndex value. dataGridViewColumnClone.DisplayIndex = dataGridViewColumn.DisplayIndex; dataGridViewTmp.Columns.Add(dataGridViewColumnClone); } foreach (DataGridViewColumn dataGridViewColumn in dataGridViewColumns) { dataGridViewColumnClone = (DataGridViewColumn) dataGridViewColumn.Clone(); dataGridViewColumnClone.DisplayIndex = dataGridViewColumn.DisplayIndex; dataGridViewTmp.Columns.Add(dataGridViewColumnClone); } } private void CorrectColumnFrozenStates(DataGridViewColumn dataGridViewColumn, bool frozenStateChanging) { Debug.Assert(dataGridViewColumn != null); DataGridViewColumn dataGridViewColumnTmp; if ((dataGridViewColumn.Frozen && !frozenStateChanging) || (!dataGridViewColumn.Frozen && frozenStateChanging)) { // make sure the previous visible columns are frozen as well dataGridViewColumnTmp = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen, DataGridViewElementStates.None); if (dataGridViewColumnTmp == null) { DataGridViewColumn dataGridViewColumnFirst = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); if (dataGridViewColumnFirst != dataGridViewColumn) { dataGridViewColumnTmp = dataGridViewColumnFirst; } } while (dataGridViewColumnTmp != null && this.Columns.DisplayInOrder(dataGridViewColumnTmp.Index, dataGridViewColumn.Index)) { dataGridViewColumnTmp.Frozen = true; dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumnTmp, DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); } } else { // make sure the next visible columns are not frozen dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); if (dataGridViewColumnTmp == null) { DataGridViewColumn dataGridViewColumnLast = dataGridViewColumn; do { dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumnLast, DataGridViewElementStates.Visible, DataGridViewElementStates.None); if (dataGridViewColumnTmp != null) { dataGridViewColumnLast = dataGridViewColumnTmp; } } while (dataGridViewColumnTmp != null); if (dataGridViewColumnLast != dataGridViewColumn) { dataGridViewColumnTmp = dataGridViewColumnLast; } } while (dataGridViewColumnTmp != null && this.Columns.DisplayInOrder(dataGridViewColumn.Index, dataGridViewColumnTmp.Index)) { dataGridViewColumnTmp.Frozen = false; dataGridViewColumnTmp = this.Columns.GetPreviousColumn(dataGridViewColumnTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen, DataGridViewElementStates.None); } } } private void CorrectColumnFrozenStatesForMove(DataGridViewColumn dataGridViewColumn, int newDisplayIndex) { Debug.Assert(dataGridViewColumn != null); Debug.Assert(newDisplayIndex != dataGridViewColumn.DisplayIndex); Debug.Assert(!this.dataGridViewOper[DATAGRIDVIEWOPER_inDisplayIndexAdjustments]); // No check necessary when: // - column is invisible. // - DisplayIndex decreases and column is frozen. // - DisplayIndex increases and column is unfrozen. if (!dataGridViewColumn.Visible || (newDisplayIndex < dataGridViewColumn.DisplayIndex && dataGridViewColumn.Frozen) || (newDisplayIndex > dataGridViewColumn.DisplayIndex && !dataGridViewColumn.Frozen)) { return; } int colCount = this.Columns.Count, displayIndex; if (newDisplayIndex < dataGridViewColumn.DisplayIndex) { // DisplayIndex decreases. // Throw an exception if the visible unfrozen column is placed before a frozen column // Get the closest visible column placed after the displaced column DataGridViewColumn dataGridViewColumnNext; displayIndex = newDisplayIndex; do { dataGridViewColumnNext = this.Columns.GetColumnAtDisplayIndex(displayIndex); displayIndex++; } while (displayIndex < colCount && (dataGridViewColumnNext == null || dataGridViewColumnNext == dataGridViewColumn || !dataGridViewColumnNext.Visible)); if (dataGridViewColumnNext != null && dataGridViewColumnNext.Frozen) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotMoveNonFrozenColumn)); } } else { // DisplayIndex increases. // Throw an exception if the visible frozen column is placed after a non-frozen column // Get the closest visible column placed before the displaced column DataGridViewColumn dataGridViewColumnPrev; displayIndex = newDisplayIndex; do { dataGridViewColumnPrev = this.Columns.GetColumnAtDisplayIndex(displayIndex); displayIndex--; } while (displayIndex >= 0 && (dataGridViewColumnPrev == null || !dataGridViewColumnPrev.Visible)); if (dataGridViewColumnPrev != null && !dataGridViewColumnPrev.Frozen) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotMoveFrozenColumn)); } } } private void CorrectColumnIndexesAfterDeletion(DataGridViewColumn dataGridViewColumn) { Debug.Assert(dataGridViewColumn != null); for (int columnIndex = dataGridViewColumn.Index; columnIndex < this.Columns.Count; columnIndex++) { this.Columns[columnIndex].IndexInternal = this.Columns[columnIndex].Index - 1; Debug.Assert(this.Columns[columnIndex].Index == columnIndex); } } private void CorrectColumnIndexesAfterInsertion(DataGridViewColumn dataGridViewColumn, int insertionCount) { Debug.Assert(dataGridViewColumn != null); Debug.Assert(insertionCount > 0); for (int columnIndex = dataGridViewColumn.Index + insertionCount; columnIndex < this.Columns.Count; columnIndex++) { this.Columns[columnIndex].IndexInternal = columnIndex; } } private void CorrectFocus(bool onlyIfGridHasFocus) { if ((!onlyIfGridHasFocus || this.Focused) && this.editingControl != null) { Debug.Assert(this.CurrentCellInternal != null); //Debug.Assert(this.editingControl.CanFocus); this.editingControl.FocusInternal(); } } private void CorrectRowFrozenState(DataGridViewRow dataGridViewRow, DataGridViewElementStates rowState, int anticipatedRowIndex) { Debug.Assert(dataGridViewRow != null); Debug.Assert(anticipatedRowIndex >= 0 && anticipatedRowIndex <= this.Rows.Count); int previousRowIndex = this.Rows.GetPreviousRow(anticipatedRowIndex, DataGridViewElementStates.Visible, DataGridViewElementStates.None); if (previousRowIndex != -1 && (this.Rows.GetRowState(previousRowIndex) & DataGridViewElementStates.Frozen) == 0 && (rowState & DataGridViewElementStates.Frozen) != 0) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddFrozenRow)); } else { int nextRowIndex = this.Rows.GetNextRow((previousRowIndex == -1) ? anticipatedRowIndex - 1 : previousRowIndex, DataGridViewElementStates.Visible, DataGridViewElementStates.None); if (nextRowIndex != -1 && (this.Rows.GetRowState(nextRowIndex) & DataGridViewElementStates.Frozen) != 0 && (rowState & DataGridViewElementStates.Frozen) == 0) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddNonFrozenRow)); } } } private void CorrectRowFrozenStates(DataGridViewRow[] dataGridViewRows, int rowIndexInserted) { bool nextVisibleRowPresent = false, previousRowFrozen = true, nextRowFrozen = false, currentRowFrozen; // Check if there is a visible row before the insertion point, and if it's frozen int rowIndexTmp = this.Rows.GetPreviousRow(rowIndexInserted, DataGridViewElementStates.Visible); if (rowIndexTmp != -1) { previousRowFrozen = (this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Frozen) == DataGridViewElementStates.Frozen; } // Check if there is a visible row at or after the insertion point, and if it's frozen rowIndexTmp = this.Rows.GetNextRow(rowIndexInserted - 1, DataGridViewElementStates.Visible); if (rowIndexTmp != -1) { nextVisibleRowPresent = true; nextRowFrozen = (this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Frozen) == DataGridViewElementStates.Frozen; } for (int arrayIndex = 0; arrayIndex < dataGridViewRows.Length; arrayIndex++) { currentRowFrozen = ((DataGridViewRow)dataGridViewRows[arrayIndex]).Frozen; if (!previousRowFrozen && currentRowFrozen) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddFrozenRow)); } previousRowFrozen = currentRowFrozen; if (arrayIndex == dataGridViewRows.Length - 1 && !currentRowFrozen && nextVisibleRowPresent && nextRowFrozen) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddNonFrozenRow)); } } } private void CorrectRowFrozenStates(DataGridViewRow dataGridViewRow, int rowIndex, bool frozenStateChanging) { Debug.Assert(dataGridViewRow != null); int rowIndexTmp; if (((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Frozen) != 0 && !frozenStateChanging) || ((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Frozen) == 0 && frozenStateChanging)) { // make sure the previous visible rows are frozen as well rowIndexTmp = this.Rows.GetPreviousRow(rowIndex, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); if (rowIndexTmp == -1) { int dataGridViewRowFirst = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); if (dataGridViewRowFirst != rowIndex) { rowIndexTmp = dataGridViewRowFirst; } } while (rowIndexTmp != -1 && rowIndexTmp < rowIndex) { this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Frozen, true); rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); } } else { // make sure the next visible rows are not frozen rowIndexTmp = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); if (rowIndexTmp == -1) { int dataGridViewRowLast = rowIndex; do { rowIndexTmp = this.Rows.GetNextRow(dataGridViewRowLast, DataGridViewElementStates.Visible); if (rowIndexTmp != -1) { dataGridViewRowLast = rowIndexTmp; } } while (rowIndexTmp != -1); if (dataGridViewRowLast != rowIndex) { rowIndexTmp = dataGridViewRowLast; } } while (rowIndexTmp != -1 && rowIndexTmp > rowIndex) { this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Frozen, false); rowIndexTmp = this.Rows.GetPreviousRow(rowIndexTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); } } } private void CorrectRowIndexesAfterDeletion(int rowIndexDeleted) { Debug.Assert(rowIndexDeleted >= 0); int rowsCount = this.Rows.Count; for (int rowIndex = rowIndexDeleted; rowIndex < rowsCount; rowIndex++) { DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex); if (dataGridViewRow.Index >= 0) { dataGridViewRow.IndexInternal = dataGridViewRow.Index - 1; Debug.Assert(dataGridViewRow.Index == rowIndex); } } // Fix 'new' row index if existant if (this.newRowIndex == rowIndexDeleted) { this.newRowIndex = -1; // No more 'new' row. } else if (this.newRowIndex != -1) { this.newRowIndex--; } } private void CorrectRowIndexesAfterInsertion(int rowIndexInserted, int insertionCount) { Debug.Assert(rowIndexInserted >= 0); Debug.Assert(insertionCount > 0); int rowsCount = this.Rows.Count; for (int rowIndex = rowIndexInserted + insertionCount; rowIndex < rowsCount; rowIndex++) { DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex); if (dataGridViewRow.Index >= 0) { dataGridViewRow.IndexInternal = dataGridViewRow.Index + insertionCount; Debug.Assert(dataGridViewRow.Index == rowIndex); } } // Lastly update the 'new' row index if needed. if (this.newRowIndex != -1) { this.newRowIndex += insertionCount; } } ///protected override AccessibleObject CreateAccessibilityInstance() { return new DataGridViewAccessibleObject(this); } /// protected override Control.ControlCollection CreateControlsInstance() { return new DataGridViewControlCollection(this); } /// /// /// Constructs the new instance of the Columns collection objects. Subclasses /// should not call base.CreateColumnsInstance. /// [EditorBrowsable(EditorBrowsableState.Advanced)] protected virtual DataGridViewColumnCollection CreateColumnsInstance() { return new DataGridViewColumnCollection(this); } ////// /// Constructs the new instance of the Rows collection objects. Subclasses /// should not call base.CreateRowsInstance. /// [EditorBrowsable(EditorBrowsableState.Advanced)] protected virtual DataGridViewRowCollection CreateRowsInstance() { return new DataGridViewRowCollection(this); } private NativeMethods.RECT[] CreateScrollableRegion(Rectangle scroll) { if (this.cachedScrollableRegion != null) { return this.cachedScrollableRegion; } using (Region region = new Region(scroll)) { IntPtr handle = IntPtr.Zero; using (Graphics graphics = CreateGraphicsInternal()) { handle = region.GetHrgn(graphics); } if (handle != IntPtr.Zero) { this.cachedScrollableRegion = UnsafeNativeMethods.GetRectsFromRegion(handle); // SECREVIEW : This assert is safe since we created the native region. // IntSecurity.ObjectFromWin32Handle.Assert(); try { region.ReleaseHrgn(handle); } finally { CodeAccessPermission.RevertAssert(); } } } return this.cachedScrollableRegion; } private void DiscardNewRow() { Debug.Assert(this.Rows.Count > 1); Debug.Assert(this.newRowIndex != -1); DataGridViewRowCancelEventArgs dgvrce = new DataGridViewRowCancelEventArgs(this.Rows[this.newRowIndex]); OnUserDeletingRow(dgvrce); if (dgvrce.Cancel) { return; } // Delete the 'new' row Debug.Assert(this.newRowIndex == this.Rows.Count - 1); DataGridViewRow dataGridViewRow = this.Rows[this.newRowIndex]; this.Rows.RemoveAtInternal(this.newRowIndex, false /*force*/); Debug.Assert(dataGridViewRow.Index == -1); DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs(dataGridViewRow); OnUserDeletedRow(dgvre); // CorrectRowIndexesAfterDeletion resets this.newRowIndex to -1. Debug.Assert(this.newRowIndex == -1); if (this.AllowUserToAddRowsInternal) { this.newRowIndex = this.Rows.Count - 1; Debug.Assert((this.Rows.GetRowState(this.newRowIndex) & DataGridViewElementStates.Visible) != 0); Debug.Assert(this.ptCurrentCell.Y == this.newRowIndex); OnDefaultValuesNeeded(new DataGridViewRowEventArgs(this.Rows[this.newRowIndex])); InvalidateRowPrivate(this.newRowIndex); } } private void DiscardZonesInScrollingArea(ref Rectangle rectScrollingArea, int emptyBackgroundWidth, int emptyBackgroundHeight, int frozenVisibleRowsHeight, bool discardFrozenColumns, bool discardFrozenRows) { // Discard empty background rectScrollingArea.Width -= emptyBackgroundWidth; rectScrollingArea.Height -= emptyBackgroundHeight; if (this.RightToLeftInternal) { rectScrollingArea.X += emptyBackgroundWidth; } if (discardFrozenColumns) { // Discard frozen columns int frozenVisibleColumnsWidth = this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); if (!this.RightToLeftInternal) { rectScrollingArea.X += frozenVisibleColumnsWidth; } rectScrollingArea.Width -= frozenVisibleColumnsWidth; } if (discardFrozenRows) { // Discard frozen rows rectScrollingArea.Y += frozenVisibleRowsHeight; rectScrollingArea.Height -= frozenVisibleRowsHeight; } } ///public int DisplayedColumnCount(bool includePartialColumns) { int cxMax = this.layout.Data.Width, cx = 0; int completeColumns = 0, partialColumns = 0; DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); while (dataGridViewColumn != null && cx < cxMax) { partialColumns++; cx += dataGridViewColumn.Thickness; if (cx <= cxMax) { completeColumns++; dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen, DataGridViewElementStates.None); } } if (cx < cxMax && this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0) { if (this.negOffset > 0) { cx -= this.negOffset; completeColumns--; } dataGridViewColumn = (DataGridViewColumn)this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol]; Debug.Assert(dataGridViewColumn.Visible && !dataGridViewColumn.Frozen); while (dataGridViewColumn != null && cx < cxMax) { partialColumns++; cx += dataGridViewColumn.Thickness; if (cx <= cxMax) { completeColumns++; dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); } } } return includePartialColumns ? partialColumns : completeColumns; } /// public int DisplayedRowCount(bool includePartialRow) { return includePartialRow ? (this.displayedBandsInfo.NumDisplayedFrozenRows + this.displayedBandsInfo.NumDisplayedScrollingRows) : (this.displayedBandsInfo.NumTotallyDisplayedFrozenRows + this.displayedBandsInfo.NumTotallyDisplayedScrollingRows); } /// protected override void Dispose(bool disposing) { if (disposing) { this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] = true; try { // Remove any Columns contained in this control for (int i = 0; i < this.Columns.Count; i ++) { this.Columns[i].Dispose(); } this.Columns.Clear(); UnwireScrollBarsEvents(); if (this.vertScrollBar != null) { this.vertScrollBar.Dispose(); this.vertScrollBar = null; } if (this.horizScrollBar != null) { this.horizScrollBar.Dispose(); this.horizScrollBar = null; } if (this.pens != null) { int nPenEntries = this.pens.Count; if (nPenEntries > 0) { foreach (Pen pen in this.pens.Values) { pen.Dispose(); } this.pens.Clear(); } this.pens = null; } if (this.brushes != null) { int nBrushEntries = this.brushes.Count; if (nBrushEntries > 0) { foreach (SolidBrush brush in this.brushes.Values) { brush.Dispose(); } this.brushes.Clear(); } this.brushes = null; } if (this.placeholderStringFormat != null) { this.placeholderStringFormat.Dispose(); this.placeholderStringFormat = null; } if (this.latestEditingControl != null) { this.latestEditingControl.Dispose(); this.latestEditingControl = null; } if (this.editingControl != null) { this.editingControl.Dispose(); this.editingControl = null; } if (this.editingPanel != null) { this.editingPanel.Dispose(); this.editingPanel = null; } Debug.Assert(this.noSelectionChangeCount == 0); if (this.dataConnection != null) { this.dataConnection.Dispose(); } // DGV should dispose the tool tip control before disposing itself. // vsw 559812. this.toolTipControl.Dispose(); } finally { this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] = false; } } base.Dispose(disposing); } private void DrawColHeaderShadow(Graphics g, int mouseX) { Rectangle r = CalcColRelocationFeedbackRect(mouseX); DrawShadowRect(r); if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_showColumnRelocationInsertion]) { Rectangle rectInsertionBar = new Rectangle(0, this.layout.ColumnHeaders.Top, DATAGRIDVIEW_insertionBarWidth, this.layout.ColumnHeaders.Height); // this.trackColumnEdge is the column preceeding the insertion point if (this.trackColumnEdge == -1) { // Insert as first column rectInsertionBar.X = GetColumnXFromIndex(this.Columns.GetFirstColumn(DataGridViewElementStates.Visible).Index); if (this.RightToLeftInternal) { rectInsertionBar.X -= DATAGRIDVIEW_insertionBarWidth; } } else { int offsetFromCenter = 0; if (this.Columns.GetNextColumn(this.Columns[this.trackColumnEdge], DataGridViewElementStates.Visible, DataGridViewElementStates.None) == null) { if (!this.RightToLeftInternal) { offsetFromCenter = DATAGRIDVIEW_insertionBarWidth; } } else { if (this.RightToLeftInternal) { offsetFromCenter = DATAGRIDVIEW_insertionBarWidth / 2 - 1; } else { offsetFromCenter = DATAGRIDVIEW_insertionBarWidth / 2 + 1; } } if (this.RightToLeftInternal) { rectInsertionBar.X = Math.Max(this.layout.ColumnHeaders.X, GetColumnXFromIndex(this.trackColumnEdge) - this.Columns[this.trackColumnEdge].Width - offsetFromCenter); } else { rectInsertionBar.X = Math.Min(GetColumnXFromIndex(this.trackColumnEdge) + this.Columns[this.trackColumnEdge].Width - offsetFromCenter, this.layout.ColumnHeaders.Right - DATAGRIDVIEW_insertionBarWidth); } } if (this.ApplyVisualStylesToHeaderCells) { g.FillRectangle(GetCachedBrush(SystemColors.HotTrack), rectInsertionBar); } else { ControlPaint.FillReversibleRectangle(RectangleToScreen(rectInsertionBar), Color.White); } } } /// /// Draws an XOR region to give UI feedback for Column Resizing. /// This looks just like the Splitter control's UI when resizing. /// private void DrawColSplitBar(int mouseX) { Rectangle r = CalcColResizeFeedbackRect(mouseX); DrawSplitBar(r); } ////// Draws an XOR region to give UI feedback for Row Resizing. /// This looks just like the Splitter control's UI when resizing. /// private void DrawRowSplitBar(int mouseY) { Rectangle r = CalcRowResizeFeedbackRect(mouseY); DrawSplitBar(r); } private void DrawShadowRect(Rectangle r) { const byte DATAGRIDVIEW_shadowEdgeThickness = 3; IntPtr parentHandle = this.Handle; IntPtr dc = UnsafeNativeMethods.GetDCEx(new HandleRef(this, parentHandle), NativeMethods.NullHandleRef, NativeMethods.DCX_CACHE | NativeMethods.DCX_LOCKWINDOWUPDATE); IntPtr halftone = ControlPaint.CreateHalftoneHBRUSH(); IntPtr saveBrush = SafeNativeMethods.SelectObject(new HandleRef(this, dc), new HandleRef(null, halftone)); SafeNativeMethods.PatBlt(new HandleRef(this, dc), r.X, r.Y, r.Width, DATAGRIDVIEW_shadowEdgeThickness, NativeMethods.PATINVERT); SafeNativeMethods.PatBlt(new HandleRef(this, dc), r.X, r.Y + r.Height - DATAGRIDVIEW_shadowEdgeThickness, r.Width, DATAGRIDVIEW_shadowEdgeThickness, NativeMethods.PATINVERT); SafeNativeMethods.PatBlt(new HandleRef(this, dc), r.X, r.Y + DATAGRIDVIEW_shadowEdgeThickness, DATAGRIDVIEW_shadowEdgeThickness, r.Height - 2 * DATAGRIDVIEW_shadowEdgeThickness, NativeMethods.PATINVERT); SafeNativeMethods.PatBlt(new HandleRef(this, dc), r.X + r.Width - DATAGRIDVIEW_shadowEdgeThickness, r.Y + DATAGRIDVIEW_shadowEdgeThickness, DATAGRIDVIEW_shadowEdgeThickness, r.Height - 2 * DATAGRIDVIEW_shadowEdgeThickness, NativeMethods.PATINVERT); SafeNativeMethods.SelectObject(new HandleRef(this, dc), new HandleRef(null, saveBrush)); SafeNativeMethods.DeleteObject(new HandleRef(null, halftone)); UnsafeNativeMethods.ReleaseDC(new HandleRef(this, parentHandle), new HandleRef(this, dc)); } ////// Draws an XOR region to give UI feedback for Column/Row Resizing. /// This looks just like the Splitter control's UI when resizing. /// private void DrawSplitBar(Rectangle r) { IntPtr parentHandle = this.Handle; IntPtr dc = UnsafeNativeMethods.GetDCEx(new HandleRef(this, parentHandle), NativeMethods.NullHandleRef, NativeMethods.DCX_CACHE | NativeMethods.DCX_LOCKWINDOWUPDATE); IntPtr halftone = ControlPaint.CreateHalftoneHBRUSH(); IntPtr saveBrush = SafeNativeMethods.SelectObject(new HandleRef(this, dc), new HandleRef(null, halftone)); SafeNativeMethods.PatBlt(new HandleRef(this, dc), r.X, r.Y, r.Width, r.Height, NativeMethods.PATINVERT); SafeNativeMethods.SelectObject(new HandleRef(this, dc), new HandleRef(null, saveBrush)); SafeNativeMethods.DeleteObject(new HandleRef(null, halftone)); UnsafeNativeMethods.ReleaseDC(new HandleRef(this, parentHandle), new HandleRef(this, dc)); } private void EditingControls_CommonMouseEventHandler(object sender, MouseEventArgs e, DataGridViewMouseEvent dgvme) { Debug.Assert(this.ptCurrentCell.X != -1); int adjustedX = this.editingPanel.Location.X + e.X; int adjustedY = this.editingPanel.Location.Y + e.Y; if (sender == this.editingControl) { adjustedX += this.editingControl.Location.X; adjustedY += this.editingControl.Location.Y; } if (dgvme == DataGridViewMouseEvent.MouseDown && e.Clicks == 1) { // Reset the flag that records single-click exposed as double-click. this.dataGridViewOper[DATAGRIDVIEWOPER_lastEditCtrlClickDoubled] = false; } MouseEventArgs me = new MouseEventArgs(e.Button, e.Clicks, adjustedX, adjustedY, e.Delta); HitTestInfo hti = HitTest(me.X, me.Y); int mouseX = me.X - hti.ColumnX; if (this.RightToLeftInternal) { mouseX += ((hti.col == -1) ? this.RowHeadersWidth : this.Columns[hti.col].Thickness); } DataGridViewCellMouseEventArgs dgvcme = new DataGridViewCellMouseEventArgs(hti.col, hti.row, mouseX, me.Y - hti.RowY, me); try { this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls] = true; // Check to see if this is a CellMouseDoubleClick situation if ((dgvme == DataGridViewMouseEvent.MouseDown || dgvme == DataGridViewMouseEvent.Click || dgvme == DataGridViewMouseEvent.MouseClick) && (DateTime.Now.Ticks - this.lastMouseClickInfo.timeStamp) / 10000 <= SystemInformation.DoubleClickTime && e.Button == this.lastMouseClickInfo.button && e.Clicks == 1 && dgvcme.ColumnIndex == this.lastMouseClickInfo.col && dgvcme.RowIndex == this.lastMouseClickInfo.row) { Size hotDoubleClickZone = SystemInformation.DoubleClickSize; if (Math.Abs(dgvcme.X - this.lastMouseClickInfo.x) <= hotDoubleClickZone.Width / 2 && Math.Abs(dgvcme.Y - this.lastMouseClickInfo.y) <= hotDoubleClickZone.Height / 2) { me = new MouseEventArgs(e.Button, 2, adjustedX, adjustedY, e.Delta); dgvcme = new DataGridViewCellMouseEventArgs(dgvcme.ColumnIndex, dgvcme.RowIndex, dgvcme.X, dgvcme.Y, me); switch (dgvme) { case DataGridViewMouseEvent.MouseDown: { OnMouseDown(me); if (dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count) { OnCellMouseDown(dgvcme); } break; } case DataGridViewMouseEvent.Click: { OnDoubleClick(me); if (e.Button == MouseButtons.Left && dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count) { OnCellDoubleClick(new DataGridViewCellEventArgs(dgvcme.ColumnIndex, dgvcme.RowIndex)); } break; } case DataGridViewMouseEvent.MouseClick: { // Set the flag that prevents the triple-click to be exposed as a double-click this.dataGridViewOper[DATAGRIDVIEWOPER_lastEditCtrlClickDoubled] = true; OnMouseDoubleClick(me); if (dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count) { OnCellMouseDoubleClick(dgvcme); } break; } } return; } } if (this.dataGridViewOper[DATAGRIDVIEWOPER_lastEditCtrlClickDoubled]) { // Make sure that the triple-click is exposed as a single-click and not a double-click. if (e.Clicks == 2) { me = new MouseEventArgs(e.Button, 1, adjustedX, adjustedY, e.Delta); dgvcme = new DataGridViewCellMouseEventArgs(hti.col, hti.row, mouseX, me.Y - hti.RowY, me); } switch (dgvme) { case DataGridViewMouseEvent.DoubleClick: dgvme = DataGridViewMouseEvent.Click; break; case DataGridViewMouseEvent.MouseDoubleClick: dgvme = DataGridViewMouseEvent.MouseClick; break; } } switch (dgvme) { case DataGridViewMouseEvent.Click: OnClick(me); if (e.Button == MouseButtons.Left && dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count) { OnCellClick(new DataGridViewCellEventArgs(dgvcme.ColumnIndex, dgvcme.RowIndex)); } break; case DataGridViewMouseEvent.DoubleClick: OnDoubleClick(me); if (e.Button == MouseButtons.Left && dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count) { OnCellDoubleClick(new DataGridViewCellEventArgs(dgvcme.ColumnIndex, dgvcme.RowIndex)); } break; case DataGridViewMouseEvent.MouseClick: OnMouseClick(me); if (dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count) { OnCellMouseClick(dgvcme); } break; case DataGridViewMouseEvent.MouseDoubleClick: OnMouseDoubleClick(me); if (dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count) { OnCellMouseDoubleClick(dgvcme); } break; case DataGridViewMouseEvent.MouseDown: OnMouseDown(me); if (dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count) { OnCellMouseDown(dgvcme); } break; case DataGridViewMouseEvent.MouseUp: if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_nextMouseUpIsDouble]) { MouseEventArgs meTmp = new MouseEventArgs(e.Button, 2, adjustedX, adjustedY, e.Delta); dgvcme = new DataGridViewCellMouseEventArgs(dgvcme.ColumnIndex, dgvcme.RowIndex, dgvcme.X, dgvcme.Y, meTmp); } OnCellMouseUp(dgvcme); OnMouseUp(me); break; case DataGridViewMouseEvent.MouseMove: OnCellMouseMove(dgvcme); break; } } finally { this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls] = false; } } private void EditingControls_Click(object sender, System.EventArgs e) { Debug.Assert(sender == this.editingControl || sender == this.editingPanel); Debug.Assert(this.ptCurrentCell.X != -1); System.Windows.Forms.MouseEventArgs me = e as System.Windows.Forms.MouseEventArgs; if (me != null) { EditingControls_CommonMouseEventHandler(sender, me, DataGridViewMouseEvent.Click); } } private void EditingControls_DoubleClick(object sender, System.EventArgs e) { Debug.Assert(sender == this.editingControl || sender == this.editingPanel); Debug.Assert(this.ptCurrentCell.X != -1); System.Windows.Forms.MouseEventArgs me = e as System.Windows.Forms.MouseEventArgs; if (me != null) { EditingControls_CommonMouseEventHandler(sender, me, DataGridViewMouseEvent.DoubleClick); } } private void EditingControls_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e) { Debug.Assert(sender == this.editingControl || sender == this.editingPanel); EditingControls_CommonMouseEventHandler(sender, e, DataGridViewMouseEvent.MouseClick); } private void EditingControls_MouseDoubleClick(object sender, System.Windows.Forms.MouseEventArgs e) { Debug.Assert(sender == this.editingControl || sender == this.editingPanel); EditingControls_CommonMouseEventHandler(sender, e, DataGridViewMouseEvent.MouseDoubleClick); } private void EditingControls_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) { Debug.Assert(sender == this.editingControl || sender == this.editingPanel); EditingControls_CommonMouseEventHandler(sender, e, DataGridViewMouseEvent.MouseDown); } private void EditingControls_MouseEnter(object sender, System.EventArgs e) { Debug.Assert(sender == this.editingControl || sender == this.editingPanel); if (sender == this.editingPanel) { Debug.Assert(this.editingControl != null); Debug.Assert(!this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet]); this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet] = true; this.oldCursor = this.Cursor; this.CursorInternal = ((IDataGridViewEditingControl)this.editingControl).EditingPanelCursor; } if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseEnterExpected]) { OnMouseEnter(EventArgs.Empty); } UpdateMouseEnteredCell(null /*HitTestInfo*/, null /*MouseEventArgs*/); } private void EditingControls_MouseLeave(object sender, System.EventArgs e) { Debug.Assert(sender == this.editingControl || sender == this.editingPanel); if (sender == this.editingPanel) { Debug.Assert(this.editingControl != null); if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet]) { this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet] = false; this.CursorInternal = this.oldCursor; } } UpdateMouseEnteredCell(null /*HitTestInfo*/, null /*MouseEventArgs*/); Point ptMouse = PointToClient(Control.MousePosition); if (!this.ClientRectangle.Contains(ptMouse)) { OnMouseLeave(EventArgs.Empty); } } private void EditingControls_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) { Debug.Assert(sender == this.editingControl || sender == this.editingPanel); EditingControls_CommonMouseEventHandler(sender, e, DataGridViewMouseEvent.MouseMove); } private void EditingControls_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) { Debug.Assert(sender == this.editingControl || sender == this.editingPanel); EditingControls_CommonMouseEventHandler(sender, e, DataGridViewMouseEvent.MouseUp); } private void EndColumnHeadersResize(MouseEventArgs e) { try { if (this.currentRowSplitBar != -1) { Invalidate(CalcRowResizeFeedbackRect(this.currentRowSplitBar), true); this.lastRowSplitBar = this.currentRowSplitBar = -1; } int y = Math.Min(e.Y + this.mouseBarOffset, this.layout.Data.Bottom - 1); int delta = y - this.layout.ColumnHeaders.Y - this.ColumnHeadersHeight + 1; if (this.trackRowAnchor != y && delta != 0) { this.ColumnHeadersHeight += delta; } } finally { RealeaseMouse(); } } private void EndColumnRelocation(MouseEventArgs e, HitTestInfo hti) { try { if (this.lastHeaderShadow != -1) { this.dataGridViewState2[DATAGRIDVIEWSTATE2_showColumnRelocationInsertion] = false; this.trackColumnEdge = -1; this.lastHeaderShadow = -1; Invalidate(Rectangle.Union(this.layout.TopLeftHeader, this.layout.ColumnHeaders)); } int previousColumnIndex; if (ColumnRelocationTarget(e, hti, out previousColumnIndex)) { if (previousColumnIndex == -1) { this.Columns[this.trackColumn].DisplayIndex = 0; } else if (this.Columns[this.trackColumn].DisplayIndex > this.Columns[previousColumnIndex].DisplayIndex) { this.Columns[this.trackColumn].DisplayIndex = this.Columns[previousColumnIndex].DisplayIndex + 1; } else { this.Columns[this.trackColumn].DisplayIndex = this.Columns[previousColumnIndex].DisplayIndex; } } } finally { RealeaseMouse(); } } private void EndColumnResize(MouseEventArgs e) { try { if (this.currentColSplitBar != -1) { Invalidate(CalcColResizeFeedbackRect(this.currentColSplitBar), true); this.lastColSplitBar = this.currentColSplitBar = -1; } int x, delta ; if (this.RightToLeftInternal) { x = Math.Max(e.X + this.mouseBarOffset, this.layout.Data.X); delta = GetColumnXFromIndex(this.trackColumn) - this.Columns[this.trackColumn].Thickness - x + 1; } else { x = Math.Min(e.X + this.mouseBarOffset, this.layout.Data.Right - 1); delta = x - (GetColumnXFromIndex(this.trackColumn) + this.Columns[this.trackColumn].Thickness) + 1; } if (this.trackColAnchor != x && delta != 0) { int proposed = this.Columns[this.trackColumn].Thickness + delta; Debug.Assert(proposed >= this.Columns[this.trackColumn].MinimumThickness); Debug.Assert(proposed <= DataGridViewBand.maxBandThickness); this.Columns[this.trackColumn].Thickness = proposed; } } finally { RealeaseMouse(); } } ///public bool EndEdit() { return EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit); } /// public bool EndEdit(DataGridViewDataErrorContexts context) { if (this.EditMode == DataGridViewEditMode.EditOnEnter) { return CommitEdit(context); } else { return EndEdit(context, DataGridViewValidateCellInternal.Never /*validateCell*/, false /*fireCellLeave*/, false /*fireCellEnter*/, false /*fireRowLeave*/, false /*fireRowEnter*/, false /*fireLeave*/, true /*keepFocus*/, true /*resetCurrentCell*/, true /*resetAnchorCell*/); } } private bool EndEdit(DataGridViewDataErrorContexts context, DataGridViewValidateCellInternal validateCell, bool fireCellLeave, bool fireCellEnter, bool fireRowLeave, bool fireRowEnter, bool fireLeave, bool keepFocus, bool resetCurrentCell, bool resetAnchorCell) { if (this.ptCurrentCell.X == -1) { return true; } this.dataGridViewOper[DATAGRIDVIEWOPER_inEndEdit] = true; try { int curRowIndex = this.ptCurrentCell.Y; int curColIndex = this.ptCurrentCell.X; DataGridViewCell dataGridViewCurrentCell = this.CurrentCellInternal; DataGridViewDataErrorEventArgs dgvdee = CommitEdit(ref dataGridViewCurrentCell, context, validateCell, fireCellLeave, fireCellEnter, fireRowLeave, fireRowEnter, fireLeave); if (dgvdee != null) { if (dgvdee.ThrowException) { throw dgvdee.Exception; } if (dgvdee.Cancel) { return false; } dgvdee = CancelEditPrivate(/*ref dataGridViewCurrentCell, context*/); // restore old value if (null != dgvdee) { if (dgvdee.ThrowException) { throw dgvdee.Exception; } if (dgvdee.Cancel) { return false; } } } if (!this.IsCurrentCellInEditMode) { return true; } if (curRowIndex != this.ptCurrentCell.Y || curColIndex != this.ptCurrentCell.X) { return true; } if (this.editingControl != null) { UnwireEditingControlEvents(); this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseOverRemovedEditingCtrl] = this.MouseOverEditingControl; this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseOverRemovedEditingPanel] = this.MouseOverEditingPanel; this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlChanging] = true; try { dataGridViewCurrentCell.DetachEditingControl(); } finally { this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlChanging] = false; } ImeMode editingControlImeMode = this.editingControl.CachedImeMode; // If in restricted mode, ImeMode will be Disable. this.latestEditingControl = this.editingControl; Debug.Assert(this.editingPanel == null || this.editingPanel.Controls.Count == 0); this.editingControl = null; InvalidateCellPrivate(this.ptCurrentCell.X, this.ptCurrentCell.Y); if (this.EditMode == DataGridViewEditMode.EditOnEnter) { if (resetCurrentCell) { bool success = SetCurrentCellAddressCore(-1, -1, resetAnchorCell, false, false); Debug.Assert(success); } } if (keepFocus) { // Debug.Assert(this.CanFocus || this.Focused); // Invalid assertion (VS Whidbey 325154) FocusInternal(); } this.ImeMode = editingControlImeMode; } else { Debug.Assert(this.dataGridViewState1[DATAGRIDVIEWSTATE1_currentCellInEditMode]); this.dataGridViewState1[DATAGRIDVIEWSTATE1_currentCellInEditMode] = false; InvalidateCellPrivate(this.ptCurrentCell.X, this.ptCurrentCell.Y); } if (!IsInnerCellOutOfBounds(curColIndex, curRowIndex)) { DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(curColIndex, curRowIndex); OnCellEndEdit(dgvce); } return true; } finally { this.dataGridViewOper[DATAGRIDVIEWOPER_inEndEdit] = false; } } private void EndRowHeadersResize(MouseEventArgs e) { try { if (this.currentColSplitBar != -1) { Invalidate(CalcColResizeFeedbackRect(this.currentColSplitBar), true); this.lastColSplitBar = this.currentColSplitBar = -1; } int x, delta; if (this.RightToLeftInternal) { x = Math.Max(e.X + this.mouseBarOffset, this.layout.Data.Left - 1); delta = this.layout.RowHeaders.Right - this.RowHeadersWidth - x - 1; } else { x = Math.Min(e.X + this.mouseBarOffset, this.layout.Data.Right - 1); delta = x - this.layout.RowHeaders.X - this.RowHeadersWidth + 1; } if (this.trackColAnchor != x && delta != 0) { this.RowHeadersWidth += delta; } } finally { RealeaseMouse(); } } private void EndRowResize(MouseEventArgs e) { try { if (this.currentRowSplitBar != -1) { Invalidate(CalcRowResizeFeedbackRect(this.currentRowSplitBar), true); this.lastRowSplitBar = this.currentRowSplitBar = -1; } DataGridViewRow dataGridViewRow = this.Rows.SharedRow(this.trackRow); int height, minimumHeight; dataGridViewRow.GetHeightInfo(this.trackRow, out height, out minimumHeight); int y = Math.Min(e.Y + this.mouseBarOffset, this.layout.Data.Bottom - 1); int delta = y - (GetRowYFromIndex(this.trackRow) + height) + 1; if (this.trackRowAnchor != y && delta != 0) { int proposedHeight = height + delta; proposedHeight = Math.Max(proposedHeight, minimumHeight); if (!OnRowHeightInfoPushed(this.trackRow, proposedHeight, minimumHeight)) { if (dataGridViewRow.Index == -1) { dataGridViewRow = this.Rows[this.trackRow]; // Unsharing row } Debug.Assert(this.autoSizeRowsMode == DataGridViewAutoSizeRowsMode.None); dataGridViewRow.ThicknessInternal = proposedHeight; } } } finally { RealeaseMouse(); } } private void ExitBulkLayout(bool invalidInAdjustFillingColumns) { if (this.inBulkLayoutCount > 0) { this.inBulkLayoutCount--; if (this.inBulkLayoutCount == 0) { PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, invalidInAdjustFillingColumns, false /*repositionEditingControl*/); } } } private void ExitBulkPaint(int columnIndex, int rowIndex) { if (this.inBulkPaintCount > 0) { this.inBulkPaintCount--; if (this.inBulkPaintCount == 0) { if (columnIndex >= 0) { InvalidateColumnInternal(columnIndex); } else if (rowIndex >= 0) { InvalidateRowPrivate(rowIndex); } else { Invalidate(); } } } } private void FirstVisibleScrollingRowTempted(int rowIndex) { Debug.Assert(rowIndex >= 0); Debug.Assert(rowIndex < this.Rows.Count); Debug.Assert((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Visible) != 0); Debug.Assert((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Frozen) == 0); int displayHeight = this.layout.Data.Height; if (displayHeight <= 0) { return; } int totalVisibleFrozenHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); if (totalVisibleFrozenHeight < displayHeight) { this.displayedBandsInfo.FirstDisplayedScrollingRow = rowIndex; } } private void FlushDisplayedChanged() { if (this.displayedBandsInfo.Dirty && this.Visible) { // Handle the rows if (!this.RowHeadersVisible && this.Columns.GetColumnCount(DataGridViewElementStates.Visible) == 0) { // All rows are hidden UpdateRowsDisplayedState(false /*displayed*/); } else { Rectangle rectScreen = Screen.FromControl(this).WorkingArea; int maxDisplayedRows = (int) (rectScreen.Height / DataGridViewBand.minBandThickness); // Make sure all displayed scrolling rows have the Displayed state. int rowIndexTmp = this.displayedBandsInfo.FirstDisplayedScrollingRow; if (rowIndexTmp != -1) { int numDisplayedScrollingRows = this.displayedBandsInfo.NumDisplayedScrollingRows; Debug.Assert(numDisplayedScrollingRows > 0); while (numDisplayedScrollingRows > 0) { Debug.Assert(rowIndexTmp != -1); if ((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) == 0) { this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, true); } rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible); numDisplayedScrollingRows--; } int rowIndexTmp2 = rowIndexTmp; // Make sure all scrolling rows before FirstDisplayedScrollingRow have their Displayed state set to false Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow != -1); rowIndexTmp = this.Rows.GetPreviousRow(this.displayedBandsInfo.FirstDisplayedScrollingRow, DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); while (rowIndexTmp != -1 && (this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) != 0) { this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, false); rowIndexTmp = this.Rows.GetPreviousRow(rowIndexTmp, DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); } // Make sure all rows below last displayed scrolling row have Displayed state set to false (next loop) rowIndexTmp = rowIndexTmp2; } else { // No displayed scrolling rows. Make sure all non-frozen rows have their Displayed state set to false (next loop) rowIndexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); } while (rowIndexTmp != -1 && (this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) != 0) { this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, false); rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible); } // Make sure all displayed frozen rows have their Displayed state set to true int numDisplayedFrozenRows = this.displayedBandsInfo.NumDisplayedFrozenRows; rowIndexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); while (numDisplayedFrozenRows > 0) { Debug.Assert(rowIndexTmp != -1); if ((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) == 0) { this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, true); } rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); numDisplayedFrozenRows--; } // Make sure all non-displayed frozen rows have their Displayed state set to false while (rowIndexTmp != -1 && (this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) != 0) { this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, false); rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); } // Treat the cases where the old displayed rows are completely disjoint from the new displayed rows int lastDisplayedFrozenRowIndex = -1; int lastDisplayedScrollingRowIndex = -1; if (this.displayedBandsInfo.NumDisplayedFrozenRows > 0) { int firstDisplayedFrozenRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); Debug.Assert(firstDisplayedFrozenRowIndex != -1); if (this.displayedBandsInfo.NumDisplayedFrozenRows > 1) { lastDisplayedFrozenRowIndex = this.Rows.GetNextRow(firstDisplayedFrozenRowIndex, DataGridViewElementStates.Visible, this.displayedBandsInfo.NumDisplayedFrozenRows-2 /*skipRows*/); } else { lastDisplayedFrozenRowIndex = firstDisplayedFrozenRowIndex; } } if (this.displayedBandsInfo.FirstDisplayedScrollingRow != -1) { if (this.displayedBandsInfo.NumDisplayedScrollingRows > 1) { lastDisplayedScrollingRowIndex = this.Rows.GetNextRow(this.displayedBandsInfo.FirstDisplayedScrollingRow, DataGridViewElementStates.Visible, this.displayedBandsInfo.NumDisplayedScrollingRows - 2 /*skipRows*/); } else { lastDisplayedScrollingRowIndex = this.displayedBandsInfo.FirstDisplayedScrollingRow; } } rowIndexTmp = this.displayedBandsInfo.OldFirstDisplayedScrollingRow; while (rowIndexTmp != -1 && rowIndexTmp < this.displayedBandsInfo.FirstDisplayedScrollingRow && !RowNeedsDisplayedState(rowIndexTmp, lastDisplayedFrozenRowIndex, lastDisplayedScrollingRowIndex)) { if ((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) == 0) { break; } else { this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, false); rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible); } } rowIndexTmp = this.displayedBandsInfo.OldFirstDisplayedScrollingRow; if (rowIndexTmp != -1 && rowIndexTmp < this.Rows.Count && (this.displayedBandsInfo.FirstDisplayedScrollingRow == -1 || this.displayedBandsInfo.FirstDisplayedScrollingRow < rowIndexTmp) && !RowNeedsDisplayedState(rowIndexTmp, lastDisplayedFrozenRowIndex, lastDisplayedScrollingRowIndex)) { while (rowIndexTmp != -1) { if ((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) == 0) { break; } else { this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, false); rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible); } } } if (this.displayedBandsInfo.RowInsertionOccurred) { // Adjust the scrolling rows that were pushed down by the rows insertion rowIndexTmp = this.displayedBandsInfo.OldFirstDisplayedScrollingRow; if (rowIndexTmp != -1) { rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible, this.displayedBandsInfo.OldNumDisplayedScrollingRows - 1); if (rowIndexTmp == -1) { rowIndexTmp = this.Rows.GetLastRow(DataGridViewElementStates.Visible); } int rowCount = 0; while (rowIndexTmp != -1 && rowCount <= maxDisplayedRows && !RowNeedsDisplayedState(rowIndexTmp, lastDisplayedFrozenRowIndex, lastDisplayedScrollingRowIndex)) { if ((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) != 0) { this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, false); } rowIndexTmp = this.Rows.GetPreviousRow(rowIndexTmp, DataGridViewElementStates.Visible); rowCount++; } } // Adjust the frozen rows that were pushed down by the rows insertion rowIndexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); if (rowIndexTmp != -1) { rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen, this.displayedBandsInfo.OldNumDisplayedFrozenRows - 1); if (rowIndexTmp == -1) { rowIndexTmp = this.Rows.GetLastRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); } int rowCount = 0; while (rowIndexTmp != -1 && rowCount <= maxDisplayedRows && !RowNeedsDisplayedState(rowIndexTmp, lastDisplayedFrozenRowIndex, lastDisplayedScrollingRowIndex)) { if ((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) != 0) { this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, false); } rowIndexTmp = this.Rows.GetPreviousRow(rowIndexTmp, DataGridViewElementStates.Visible); rowCount++; } } } #if DEBUG for (rowIndexTmp = 0; rowIndexTmp < this.Rows.Count; rowIndexTmp++) { DataGridViewElementStates rowStateDbg = this.Rows.GetRowState(rowIndexTmp); bool rowNeedsDisplayedState = RowNeedsDisplayedState(rowIndexTmp, lastDisplayedFrozenRowIndex, lastDisplayedScrollingRowIndex); if (((rowStateDbg & DataGridViewElementStates.Displayed) != 0) != rowNeedsDisplayedState) { Debug.Fail("Unexpected Displayed state for row"); } } #endif } // Handle the columns if (!this.ColumnHeadersVisible && this.Rows.GetRowCount(DataGridViewElementStates.Visible) == 0) { // All columns are hidden UpdateColumnsDisplayedState(false /*displayed*/); } else { // Make sure all displayed scrolling columns have the Displayed state. DataGridViewColumn dataGridViewColumnTmp; int columnIndexTmp = this.displayedBandsInfo.FirstDisplayedScrollingCol; if (columnIndexTmp != -1) { int numDisplayedScrollingCols = this.displayedBandsInfo.NumDisplayedScrollingCols; Debug.Assert(numDisplayedScrollingCols > 0); dataGridViewColumnTmp = this.Columns[columnIndexTmp]; while (numDisplayedScrollingCols > 0) { Debug.Assert(dataGridViewColumnTmp != null); if (!dataGridViewColumnTmp.Displayed) { dataGridViewColumnTmp.DisplayedInternal = true; } dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumnTmp, DataGridViewElementStates.Visible, DataGridViewElementStates.None); numDisplayedScrollingCols--; } DataGridViewColumn dataGridViewColumnTmp2 = dataGridViewColumnTmp; // Make sure all scrolling columns before FirstDisplayedScrollingCol have their Displayed state set to false Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingCol != -1); dataGridViewColumnTmp = this.Columns.GetPreviousColumn(this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol], DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); while (dataGridViewColumnTmp != null && dataGridViewColumnTmp.Displayed) { dataGridViewColumnTmp.DisplayedInternal = false; dataGridViewColumnTmp = this.Columns.GetPreviousColumn(dataGridViewColumnTmp, DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); } // Make sure all columns after last displayed scrolling column have Displayed state set to false (next loop) dataGridViewColumnTmp = dataGridViewColumnTmp2; } else { // No displayed scrolling columns. Make sure all non-frozen columns have their Displayed state set to false (next loop) dataGridViewColumnTmp = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); } while (dataGridViewColumnTmp != null && dataGridViewColumnTmp.Displayed) { dataGridViewColumnTmp.DisplayedInternal = false; dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumnTmp, DataGridViewElementStates.Visible, DataGridViewElementStates.None); } // Make sure all displayed frozen columns have their Displayed state set to true int numDisplayedFrozenCols = this.displayedBandsInfo.NumDisplayedFrozenCols; dataGridViewColumnTmp = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); while (numDisplayedFrozenCols > 0) { Debug.Assert(dataGridViewColumnTmp != null); if (!dataGridViewColumnTmp.Displayed) { dataGridViewColumnTmp.DisplayedInternal = true; } dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumnTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen, DataGridViewElementStates.None); numDisplayedFrozenCols--; } // Make sure all non-displayed frozen columns have their Displayed state set to false while (dataGridViewColumnTmp != null && dataGridViewColumnTmp.Displayed) { dataGridViewColumnTmp.DisplayedInternal = false; dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumnTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen, DataGridViewElementStates.None); } // Treat the cases where the old displayed columns are completely disjoint from the new displayed columns columnIndexTmp = this.displayedBandsInfo.OldFirstDisplayedScrollingCol; while (columnIndexTmp != -1 && columnIndexTmp < this.Columns.Count && this.displayedBandsInfo.FirstDisplayedScrollingCol != -1 && columnIndexTmp != this.displayedBandsInfo.FirstDisplayedScrollingCol && this.Columns.DisplayInOrder(columnIndexTmp, this.displayedBandsInfo.FirstDisplayedScrollingCol) && !ColumnNeedsDisplayedState(this.Columns[columnIndexTmp])) { dataGridViewColumnTmp = this.Columns[columnIndexTmp]; if (!dataGridViewColumnTmp.Displayed) { break; } else { dataGridViewColumnTmp.DisplayedInternal = false; dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumnTmp, DataGridViewElementStates.Visible, DataGridViewElementStates.None); columnIndexTmp = (dataGridViewColumnTmp == null) ? -1 : dataGridViewColumnTmp.Index; } } columnIndexTmp = this.displayedBandsInfo.OldFirstDisplayedScrollingCol; if (columnIndexTmp != -1 && columnIndexTmp < this.Columns.Count && (this.displayedBandsInfo.FirstDisplayedScrollingCol == -1 || (this.displayedBandsInfo.FirstDisplayedScrollingCol != columnIndexTmp && this.Columns.DisplayInOrder(this.displayedBandsInfo.FirstDisplayedScrollingCol, columnIndexTmp))) && !ColumnNeedsDisplayedState(this.Columns[columnIndexTmp])) { dataGridViewColumnTmp = this.Columns[columnIndexTmp]; while (dataGridViewColumnTmp != null) { if (!dataGridViewColumnTmp.Displayed) { break; } else { dataGridViewColumnTmp.DisplayedInternal = false; dataGridViewColumnTmp = this.Columns.GetNextColumn(dataGridViewColumnTmp, DataGridViewElementStates.Visible, DataGridViewElementStates.None); } } } if (this.displayedBandsInfo.ColumnInsertionOccurred) { dataGridViewColumnTmp = this.Columns[this.Columns.Count - 1]; while (dataGridViewColumnTmp != null && !ColumnNeedsDisplayedState(dataGridViewColumnTmp)) { if (dataGridViewColumnTmp.Displayed) { dataGridViewColumnTmp.DisplayedInternal = false; } dataGridViewColumnTmp = this.Columns.GetPreviousColumn(dataGridViewColumnTmp, DataGridViewElementStates.Visible, DataGridViewElementStates.None); } } #if DEBUG for (columnIndexTmp = 0; columnIndexTmp < this.Columns.Count; columnIndexTmp++) { DataGridViewElementStates colStateDbg = this.Columns[columnIndexTmp].State; bool columnNeedsDisplayedState = ColumnNeedsDisplayedState(this.Columns[columnIndexTmp]); if (((colStateDbg & DataGridViewElementStates.Displayed) != 0) != columnNeedsDisplayedState) { Debug.Fail("Unexpected Displayed state for column"); } } #endif } this.displayedBandsInfo.Dirty = false; } } private void FlushDisplayIndexChanged(bool raiseEvent) { foreach (DataGridViewColumn dataGridViewColumn in this.Columns) { if (dataGridViewColumn.DisplayIndexHasChanged) { dataGridViewColumn.DisplayIndexHasChanged = false; if (raiseEvent) { OnColumnDisplayIndexChanged(dataGridViewColumn); } } } } private void FlushSelectionChanged() { if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_raiseSelectionChanged]) { OnSelectionChanged(EventArgs.Empty); } } /// protected override AccessibleObject GetAccessibilityObjectById(int objectId) { // decrement the objectId because in our implementation of AccessibilityClient notitification objectId's are 1 - based. // 0 == NativeMethods.CHILDID_SELF corresponds to the AccessibleObject itself return this.AccessibilityObject.GetChild(objectId - 1); } [ResourceExposure(ResourceScope.Process)] [ResourceConsumption(ResourceScope.Process)] internal SolidBrush GetCachedBrush(Color color) { SolidBrush brush = (SolidBrush) this.brushes[color]; if (brush == null) { brush = new SolidBrush(color); this.brushes.Add(color, brush); } return brush; } #if DGV_GDI internal WindowsSolidBrush GetCachedWindowsBrush(Color color) { WindowsSolidBrush brush = (WindowsSolidBrush)this.brushes[color]; if (brush == null) { brush = new WindowsSolidBrush(color); this.brushes.Add(color, brush); } return brush; } #endif // DGV_GDI [ResourceExposure(ResourceScope.Process)] [ResourceConsumption(ResourceScope.Process)] internal Pen GetCachedPen(Color color) { Pen pen = (Pen) this.pens[color]; if (pen == null) { pen = new Pen(color); this.pens.Add(color, pen); } return pen; } #if DGV_GDI internal WindowsPen GetCachedWindowsPen(Color color) { WindowsPen pen = (WindowsPen)this.pens[color]; if (pen == null) { pen = new WindowsPen(color); this.pens.Add(color, pen); } return pen; } #endif // DGV_GDI internal TypeConverter GetCachedTypeConverter(Type type) { if (this.converters.ContainsKey(type)) { return (TypeConverter)this.converters[type]; } TypeConverter converter = TypeDescriptor.GetConverter(type); this.converters.Add(type, converter); return converter; } internal Rectangle GetCellAdjustedDisplayRectangle(int columnIndex, int rowIndex, bool cutOverflow) { Rectangle rect = GetCellDisplayRectangle(columnIndex, rowIndex, cutOverflow); if (!rect.IsEmpty) { if (this.SingleVerticalBorderAdded && columnIndex == this.FirstDisplayedColumnIndex) { if (!this.RightToLeftInternal) { rect.X--; } rect.Width++; } if (this.SingleHorizontalBorderAdded && rowIndex == this.FirstDisplayedRowIndex) { rect.Y--; rect.Height++; } } return rect; } /// [ SuppressMessage("Microsoft.Performance", "CA1808:AvoidCallsThatBoxValueTypes"), // using specialized DataGridViewCellLinkedList class instead of generics ] public int GetCellCount(DataGridViewElementStates includeFilter) { if ((includeFilter & ~(DataGridViewElementStates.Displayed | DataGridViewElementStates.Frozen | DataGridViewElementStates.Resizable | DataGridViewElementStates.ReadOnly | DataGridViewElementStates.Selected | DataGridViewElementStates.Visible)) != 0) { throw new ArgumentException(SR.GetString(SR.DataGridView_InvalidDataGridViewElementStateCombination, "includeFilter")); } int cellCount = 0; bool displayedRequired, frozenRequired, resizableRequired, readOnlyRequired, visibleRequired; if ((includeFilter & DataGridViewElementStates.Selected) == DataGridViewElementStates.Selected) { if (includeFilter == DataGridViewElementStates.Selected) { cellCount = this.individualSelectedCells.Count; switch (this.SelectionMode) { case DataGridViewSelectionMode.CellSelect: { // If we change the design and decide that SelectAll() should use band selection, // we need to take the bands into account. return cellCount; } case DataGridViewSelectionMode.FullColumnSelect: case DataGridViewSelectionMode.ColumnHeaderSelect: { return cellCount + this.selectedBandIndexes.Count * this.Rows.Count; } case DataGridViewSelectionMode.FullRowSelect: case DataGridViewSelectionMode.RowHeaderSelect: { return cellCount + this.selectedBandIndexes.Count * this.Columns.Count; } } } displayedRequired = (includeFilter & DataGridViewElementStates.Displayed) == DataGridViewElementStates.Displayed; frozenRequired = (includeFilter & DataGridViewElementStates.Frozen) == DataGridViewElementStates.Frozen; resizableRequired = (includeFilter & DataGridViewElementStates.Resizable) == DataGridViewElementStates.Resizable; readOnlyRequired = (includeFilter & DataGridViewElementStates.ReadOnly) == DataGridViewElementStates.ReadOnly; visibleRequired = (includeFilter & DataGridViewElementStates.Visible) == DataGridViewElementStates.Visible; foreach (DataGridViewCell dataGridViewCell in this.individualSelectedCells) { if (GetCellCount_CellIncluded(dataGridViewCell, dataGridViewCell.RowIndex, displayedRequired, frozenRequired, resizableRequired, readOnlyRequired, visibleRequired)) { cellCount++; } } switch (this.SelectionMode) { case DataGridViewSelectionMode.CellSelect: { // If we change the design and decide that SelectAll() should use band selection, // we need to take the bands into account. return cellCount; } case DataGridViewSelectionMode.FullColumnSelect: case DataGridViewSelectionMode.ColumnHeaderSelect: { for (int rowIndex = 0; rowIndex < this.Rows.Count; rowIndex++) { DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex); foreach (int columnIndex in this.selectedBandIndexes) { DataGridViewCell dataGridViewCell = dataGridViewRow.Cells[columnIndex]; if (GetCellCount_CellIncluded(dataGridViewCell, rowIndex, displayedRequired, frozenRequired, resizableRequired, readOnlyRequired, visibleRequired)) { cellCount++; } } } return cellCount; } case DataGridViewSelectionMode.FullRowSelect: case DataGridViewSelectionMode.RowHeaderSelect: { foreach (int rowIndex in this.selectedBandIndexes) { DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex); foreach (DataGridViewCell dataGridViewCell in dataGridViewRow.Cells) { if (GetCellCount_CellIncluded(dataGridViewCell, rowIndex, displayedRequired, frozenRequired, resizableRequired, readOnlyRequired, visibleRequired)) { cellCount++; } } } return cellCount; } } } if ((includeFilter == DataGridViewElementStates.ReadOnly && this.ReadOnly) || includeFilter == DataGridViewElementStates.None) { return this.Rows.Count * this.Columns.Count; } displayedRequired = (includeFilter & DataGridViewElementStates.Displayed) == DataGridViewElementStates.Displayed; frozenRequired = (includeFilter & DataGridViewElementStates.Frozen) == DataGridViewElementStates.Frozen; resizableRequired = (includeFilter & DataGridViewElementStates.Resizable) == DataGridViewElementStates.Resizable; readOnlyRequired = (includeFilter & DataGridViewElementStates.ReadOnly) == DataGridViewElementStates.ReadOnly; visibleRequired = (includeFilter & DataGridViewElementStates.Visible) == DataGridViewElementStates.Visible; for (int rowIndex = 0; rowIndex < this.Rows.Count; rowIndex++) { DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex); if (!visibleRequired || (this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Visible) != 0) { foreach (DataGridViewCell dataGridViewCell in dataGridViewRow.Cells) { if (GetCellCount_CellIncluded(dataGridViewCell, rowIndex, displayedRequired, frozenRequired, resizableRequired, readOnlyRequired, visibleRequired)) { cellCount++; } } } } return cellCount; } private bool GetCellCount_CellIncluded(DataGridViewCell dataGridViewCell, int rowIndex, bool displayedRequired, bool frozenRequired, bool resizableRequired, bool readOnlyRequired, bool visibleRequired) { Debug.Assert(dataGridViewCell != null); Debug.Assert(rowIndex >= 0); DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex); if (displayedRequired) { bool cellDisplayed = (rowState & DataGridViewElementStates.Displayed) != 0 && dataGridViewCell.OwningColumn.Displayed; if (!cellDisplayed) { return false; } } if (frozenRequired) { bool cellFrozen = (rowState & DataGridViewElementStates.Frozen) != 0 || dataGridViewCell.OwningColumn.Frozen || dataGridViewCell.StateIncludes(DataGridViewElementStates.Frozen); if (!cellFrozen) { return false; } } if (resizableRequired) { if (!RowIsResizable(rowIndex) && dataGridViewCell.OwningColumn.Resizable != DataGridViewTriState.True) { return false; } } if (readOnlyRequired) { bool cellReadOnly = this.ReadOnly || (rowState & DataGridViewElementStates.ReadOnly) != 0 || dataGridViewCell.OwningColumn.ReadOnly || dataGridViewCell.StateIncludes(DataGridViewElementStates.ReadOnly); if (!cellReadOnly) { return false; } } if (visibleRequired) { bool cellVisible = (rowState & DataGridViewElementStates.Visible) != 0 && dataGridViewCell.OwningColumn.Visible; if (!cellVisible) { return false; } } return true; } /// public Rectangle GetCellDisplayRectangle(int columnIndex, int rowIndex, bool cutOverflow) { Rectangle rowRect; Rectangle columnRect; if (columnIndex >= 0) { if (columnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("columnIndex"); } columnRect = GetColumnDisplayRectanglePrivate(columnIndex, cutOverflow); } else { if (columnIndex != -1) { throw new ArgumentOutOfRangeException("columnIndex"); } if (rowIndex >= 0) { columnRect = this.layout.RowHeaders; } else { columnRect = this.layout.TopLeftHeader; } } if (rowIndex >= 0) { if (rowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("rowIndex"); } rowRect = GetRowDisplayRectanglePrivate(rowIndex, cutOverflow); } else { if (rowIndex != -1) { throw new ArgumentOutOfRangeException("rowIndex"); } if (columnIndex >= 0) { rowRect = this.layout.ColumnHeaders; } else { rowRect = this.layout.TopLeftHeader; } } if (!cutOverflow) { int height = rowRect.Bottom - columnRect.Bottom; if (height > 0) { columnRect.Height += height; } int width; if (this.RightToLeftInternal) { width = rowRect.X - columnRect.X; if (width > 0) { rowRect.Width += width; rowRect.X -= width; } } else { width = columnRect.Right - rowRect.Right; if (width > 0) { rowRect.Width += width; } } } rowRect.Intersect(columnRect); return rowRect; } internal DataGridViewCell GetCellInternal(int columnIndex, int rowIndex) { Debug.Assert(columnIndex >= -1 && columnIndex < this.Columns.Count); Debug.Assert(rowIndex >= -1 && rowIndex < this.Rows.Count); if (rowIndex >= 0) { DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex); Debug.Assert(dataGridViewRow != null); if (columnIndex >= 0) { return dataGridViewRow.Cells[columnIndex]; } else { return dataGridViewRow.HeaderCell; } } else { if (columnIndex >= 0) { return this.Columns[columnIndex].HeaderCell; } else { return this.TopLeftHeaderCell; } } } /// [ SuppressMessage("Microsoft.Performance", "CA1808:AvoidCallsThatBoxValueTypes"), // using specialized DataGridViewCellLinkedList class instead of generics ] public virtual DataObject GetClipboardContent() { if (this.ClipboardCopyMode == DataGridViewClipboardCopyMode.Disable) { throw new NotSupportedException(SR.GetString(SR.DataGridView_DisabledClipboardCopy)); } if (this.CurrentCellIsEditedAndOnlySelectedCell) { return null; } string[] formats = new string[] { DataFormats.Html, DataFormats.Text, DataFormats.UnicodeText, DataFormats.CommaSeparatedValue }; DataObject dataObject = new DataObject(); bool includeColumnHeaders = false, includeRowHeaders = false; string cellContent = null; StringBuilder sbContent = null; DataGridViewColumn dataGridViewColumn, prevDataGridViewColumn, nextDataGridViewColumn; switch (this.SelectionMode) { case DataGridViewSelectionMode.FullRowSelect: if (this.Rows.GetRowCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected) == 0) { return null; } if (clipboardCopyMode == DataGridViewClipboardCopyMode.EnableWithAutoHeaderText) { includeColumnHeaders = (this.Rows.GetFirstRow(DataGridViewElementStates.Visible, DataGridViewElementStates.Selected) == -1); includeRowHeaders = true; } else { includeColumnHeaders = includeRowHeaders = (clipboardCopyMode == DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText); } includeColumnHeaders &= this.ColumnHeadersVisible; includeRowHeaders &= this.RowHeadersVisible; foreach (string format in formats) { /* if (!String.Equals(format, DataFormats.Html, StringComparison.OrdinalIgnoreCase) && !String.Equals(format, DataFormats.Text, StringComparison.OrdinalIgnoreCase) && !String.Equals(format, DataFormats.UnicodeText, StringComparison.OrdinalIgnoreCase) && !String.Equals(format, DataFormats.CommaSeparatedValue, StringComparison.OrdinalIgnoreCase)) { continue; }*/ if (sbContent == null) { sbContent = new StringBuilder(1024); } else { sbContent.Length = 0; } if (includeColumnHeaders) { if (this.RightToLeftInternal) { // Cycle through the visible columns in their reverse display order dataGridViewColumn = this.Columns.GetLastColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.None); if (dataGridViewColumn != null) { prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1, true /*firstCell*/, !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/, true /*inFirstRow*/, false /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } while (prevDataGridViewColumn != null) { dataGridViewColumn = prevDataGridViewColumn; prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1, false /*firstCell*/, !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/, true /*inFirstRow*/, false /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } } } if (includeRowHeaders) { cellContent = this.TopLeftHeaderCell.GetClipboardContentInternal(-1, this.Columns.GetColumnCount(DataGridViewElementStates.Visible) == 0 /*firstCell*/, true /*lastCell*/, true /*inFirstRow*/, false /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } } } else { if (includeRowHeaders) { cellContent = this.TopLeftHeaderCell.GetClipboardContentInternal(-1, true /*firstCell*/, this.Columns.GetColumnCount(DataGridViewElementStates.Visible) == 0 /*lastCell*/, true /*inFirstRow*/, false /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } } // Cycle through the visible columns in their display order dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); if (dataGridViewColumn != null) { nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1, !includeRowHeaders /*firstCell*/, nextDataGridViewColumn == null /*lastCell*/, true /*inFirstRow*/, false /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } while (nextDataGridViewColumn != null) { dataGridViewColumn = nextDataGridViewColumn; nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1, false /*firstCell*/, nextDataGridViewColumn == null /*lastCell*/, true /*inFirstRow*/, false /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } } } } } // Cycle through the visible selected rows. bool firstRowIndex = true; int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected); Debug.Assert(rowIndex != -1); int nextRowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected); while (rowIndex != -1) { if (this.RightToLeftInternal) { dataGridViewColumn = this.Columns.GetLastColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.None); // Cycle through the visible columns in their reverse display order if (dataGridViewColumn != null) { prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex, true /*firstCell*/, !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/, !includeColumnHeaders && firstRowIndex /*inFirstRow*/, nextRowIndex == -1 /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } while (prevDataGridViewColumn != null) { dataGridViewColumn = prevDataGridViewColumn; prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex, false /*firstCell*/, !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/, !includeColumnHeaders && firstRowIndex /*inFirstRow*/, nextRowIndex == -1 /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } } } // Get the row header clipboard content if (includeRowHeaders) { cellContent = this.Rows.SharedRow(rowIndex).HeaderCell.GetClipboardContentInternal(rowIndex, this.Columns.GetColumnCount(DataGridViewElementStates.Visible) == 0 /*firstCell*/, true /*lastCell*/, !includeColumnHeaders && firstRowIndex /*inFirstRow*/, nextRowIndex == -1 /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } } } else { dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); // Get the row header clipboard content if (includeRowHeaders) { cellContent = this.Rows.SharedRow(rowIndex).HeaderCell.GetClipboardContentInternal(rowIndex, true /*firstCell*/, dataGridViewColumn == null /*lastCell*/, !includeColumnHeaders && firstRowIndex /*inFirstRow*/, nextRowIndex == -1 /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } } // Cycle through the visible columns in their display order if (dataGridViewColumn != null) { nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex, !includeRowHeaders /*firstCell*/, nextDataGridViewColumn == null /*lastCell*/, !includeColumnHeaders && firstRowIndex /*inFirstRow*/, nextRowIndex == -1 /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } while (nextDataGridViewColumn != null) { dataGridViewColumn = nextDataGridViewColumn; nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex, false /*firstCell*/, nextDataGridViewColumn == null /*lastCell*/, !includeColumnHeaders && firstRowIndex /*inFirstRow*/, nextRowIndex == -1 /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } } } } rowIndex = nextRowIndex; if (rowIndex != -1) { nextRowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected); } firstRowIndex = false; } if (String.Equals(format, DataFormats.Html, StringComparison.OrdinalIgnoreCase)) { System.IO.MemoryStream utf8Stream = null; GetClipboardContentForHtml(sbContent, out utf8Stream); dataObject.SetData(format, false /*autoConvert*/, utf8Stream); } else { dataObject.SetData(format, false /*autoConvert*/, sbContent.ToString()); } } break; case DataGridViewSelectionMode.FullColumnSelect: if (this.Columns.GetColumnCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected) == 0) { return null; } if (clipboardCopyMode == DataGridViewClipboardCopyMode.EnableWithAutoHeaderText) { includeColumnHeaders = true; includeRowHeaders = (this.Columns.GetFirstColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.Selected) == null); } else { includeColumnHeaders = includeRowHeaders = (clipboardCopyMode == DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText); } includeColumnHeaders &= this.ColumnHeadersVisible; includeRowHeaders &= this.RowHeadersVisible; int firstVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); foreach (string format in formats) { /* if (!String.Equals(format, DataFormats.Html, StringComparison.OrdinalIgnoreCase) && !String.Equals(format, DataFormats.Text, StringComparison.OrdinalIgnoreCase) && !String.Equals(format, DataFormats.UnicodeText, StringComparison.OrdinalIgnoreCase) && !String.Equals(format, DataFormats.CommaSeparatedValue, StringComparison.OrdinalIgnoreCase)) { continue; }*/ if (sbContent == null) { sbContent = new StringBuilder(1024); } else { sbContent.Length = 0; } if (includeColumnHeaders) { if (this.RightToLeftInternal) { // Cycle through the visible & selected columns in their display order DataGridViewColumn lastDataGridViewColumn = this.Columns.GetLastColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None); dataGridViewColumn = lastDataGridViewColumn; Debug.Assert(dataGridViewColumn != null); if (dataGridViewColumn != null) { prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None); cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1, true /*firstCell*/, !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/, true /*inFirstRow*/, firstVisibleRowIndex == -1 /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } while (prevDataGridViewColumn != null) { dataGridViewColumn = prevDataGridViewColumn; prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None); cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1, false /*firstCell*/, !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/, true /*inFirstRow*/, firstVisibleRowIndex == -1 /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } } } if (includeRowHeaders) { cellContent = this.TopLeftHeaderCell.GetClipboardContentInternal(-1, lastDataGridViewColumn == null /*firstCell*/, true /*lastCell*/, true /*inFirstRow*/, firstVisibleRowIndex == -1 /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } } } else { dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected); if (includeRowHeaders) { cellContent = this.TopLeftHeaderCell.GetClipboardContentInternal(-1, true /*firstCell*/, dataGridViewColumn == null /*lastCell*/, true /*inFirstRow*/, firstVisibleRowIndex == -1 /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } } // Cycle through the visible & selected columns in their display order Debug.Assert(dataGridViewColumn != null); if (dataGridViewColumn != null) { nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None); cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1, !includeRowHeaders /*firstCell*/, nextDataGridViewColumn == null /*lastCell*/, true /*inFirstRow*/, firstVisibleRowIndex == -1 /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } while (nextDataGridViewColumn != null) { dataGridViewColumn = nextDataGridViewColumn; nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None); cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1, false /*firstCell*/, nextDataGridViewColumn == null /*lastCell*/, true /*inFirstRow*/, firstVisibleRowIndex == -1 /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } } } } } // Cycle through the visible rows. bool firstRowIndex = true; int rowIndex = firstVisibleRowIndex; int nextRowIndex = -1; if (rowIndex != -1) { nextRowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible); } while (rowIndex != -1) { if (this.RightToLeftInternal) { DataGridViewColumn lastDataGridViewColumn = this.Columns.GetLastColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None); // Cycle through the visible & selected columns in their reverse display order dataGridViewColumn = lastDataGridViewColumn; if (dataGridViewColumn != null) { prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None); cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex, true /*firstCell*/, !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/, !includeColumnHeaders && firstRowIndex /*inFirstRow*/, nextRowIndex == -1 /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } while (prevDataGridViewColumn != null) { dataGridViewColumn = prevDataGridViewColumn; prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None); cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex, false /*firstCell*/, !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/, !includeColumnHeaders && firstRowIndex /*inFirstRow*/, nextRowIndex == -1 /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } } } // Get the row header clipboard content if (includeRowHeaders) { cellContent = this.Rows.SharedRow(rowIndex).HeaderCell.GetClipboardContentInternal(rowIndex, lastDataGridViewColumn == null /*firstCell*/, true /*lastCell*/, !includeColumnHeaders && firstRowIndex /*inFirstRow*/, nextRowIndex == -1 /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } } } else { dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected); // Get the row header clipboard content if (includeRowHeaders) { cellContent = this.Rows.SharedRow(rowIndex).HeaderCell.GetClipboardContentInternal(rowIndex, true /*firstCell*/, dataGridViewColumn == null /*lastCell*/, !includeColumnHeaders && firstRowIndex /*inFirstRow*/, nextRowIndex == -1 /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } } // Cycle through the visible & selected columns in their display order if (dataGridViewColumn != null) { nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None); cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex, !includeRowHeaders /*firstCell*/, nextDataGridViewColumn == null /*lastCell*/, !includeColumnHeaders && firstRowIndex /*inFirstRow*/, nextRowIndex == -1 /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } while (nextDataGridViewColumn != null) { dataGridViewColumn = nextDataGridViewColumn; nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Selected, DataGridViewElementStates.None); cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex, false /*firstCell*/, nextDataGridViewColumn == null /*lastCell*/, !includeColumnHeaders && firstRowIndex /*inFirstRow*/, nextRowIndex == -1 /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } } } } rowIndex = nextRowIndex; if (rowIndex != -1) { nextRowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible); } firstRowIndex = false; } if (String.Equals(format, DataFormats.Html, StringComparison.OrdinalIgnoreCase)) { System.IO.MemoryStream utf8Stream = null; GetClipboardContentForHtml(sbContent, out utf8Stream); dataObject.SetData(format, false /*autoConvert*/, utf8Stream); } else { dataObject.SetData(format, false /*autoConvert*/, sbContent.ToString()); } } break; case DataGridViewSelectionMode.CellSelect: case DataGridViewSelectionMode.RowHeaderSelect: case DataGridViewSelectionMode.ColumnHeaderSelect: bool selectedVisibleCellExists = false; bool selectedVisibleColumnExists = false; bool selectedVisibleRowExists = false; if (this.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect) { selectedVisibleRowExists = this.Rows.GetRowCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected) != 0; selectedVisibleCellExists = selectedVisibleRowExists && this.Columns.GetColumnCount(DataGridViewElementStates.Visible) != 0; } else if (this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect) { selectedVisibleColumnExists = this.Columns.GetColumnCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Selected) != 0; selectedVisibleCellExists = selectedVisibleColumnExists && this.Rows.GetRowCount(DataGridViewElementStates.Visible) != 0; } if (!selectedVisibleCellExists && this.individualSelectedCells.Count > 0) { foreach (DataGridViewCell dataGridViewCell in this.individualSelectedCells) { if (dataGridViewCell.Visible) { selectedVisibleCellExists = true; break; } } } if (!selectedVisibleCellExists) { return null; } // There is at least one selected visible cell. if (this.SelectionMode == DataGridViewSelectionMode.CellSelect) { includeColumnHeaders = includeRowHeaders = (clipboardCopyMode == DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText); includeColumnHeaders &= this.ColumnHeadersVisible; includeRowHeaders &= this.RowHeadersVisible; } else { includeColumnHeaders = includeRowHeaders = false; if (this.ColumnHeadersVisible) { if (clipboardCopyMode == DataGridViewClipboardCopyMode.EnableWithAutoHeaderText) { if (selectedVisibleColumnExists) { includeColumnHeaders = true; } /* Use this code if column headers should be included when all cells are selected in a visible column. else { // Include column headers if there is a column where all visible cells are selected DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); Debug.Assert(dataGridViewColumn != null); while (dataGridViewColumn != null) { // Cycle through the visible rows, see if the cell in that column is selected int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); while (rowIndex != -1) { if (!this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].Selected) { break; } rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible); } if (rowIndex == -1) { // All visible cells in column are selected includeColumnHeaders = true; break; } dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); } } */ } else { includeColumnHeaders = (clipboardCopyMode == DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText); } } if (this.RowHeadersVisible) { if (clipboardCopyMode == DataGridViewClipboardCopyMode.EnableWithAutoHeaderText) { if (selectedVisibleRowExists) { includeRowHeaders = true; } /* Use this code if row headers should be included when all cells are selected in a visible row. else { // Include row headers if there is a row where all visible cells are selected int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); Debug.Assert(rowIndex != -1); while (rowIndex != -1) { // Cycle through the visible columns, see if the cell in that row is selected DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); Debug.Assert(dataGridViewColumn != null); while (dataGridViewColumn != null) { if (!this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].Selected) { break; } dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); } if (dataGridViewColumn == null) { // All visible cells in row are selected includeRowHeaders = true; break; } rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible); } } */ } else { includeRowHeaders = (clipboardCopyMode == DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText); } } } // Get the four corners of the 'selected table' int lRowIndex = int.MaxValue; int uRowIndex = -1; DataGridViewColumn lColumn = null, uColumn = null; if (this.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect) { DataGridViewColumn firstVisibleColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); DataGridViewColumn lastVisibleColumn = this.Columns.GetLastColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.None); Debug.Assert(firstVisibleColumn != null); Debug.Assert(lastVisibleColumn != null); foreach (int rowIndex in this.selectedBandIndexes) { if ((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Visible) != 0) { if (rowIndex < lRowIndex) { lRowIndex = rowIndex; } if (rowIndex > uRowIndex) { uRowIndex = rowIndex; } lColumn = firstVisibleColumn; uColumn = lastVisibleColumn; } } } else if (this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect) { firstVisibleRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); int lastVisibleRowIndex = this.Rows.GetLastRow(DataGridViewElementStates.Visible); Debug.Assert(firstVisibleRowIndex != -1); Debug.Assert(lastVisibleRowIndex != -1); foreach (int columnIndex in this.selectedBandIndexes) { if (this.Columns[columnIndex].Visible) { if (lColumn == null || this.Columns.DisplayInOrder(columnIndex, lColumn.Index)) { lColumn = this.Columns[columnIndex]; } if (uColumn == null || this.Columns.DisplayInOrder(uColumn.Index, columnIndex)) { uColumn = this.Columns[columnIndex]; } lRowIndex = firstVisibleRowIndex; uRowIndex = lastVisibleRowIndex; } } } // Go through the individually selected cells to potentially stretch the current 'selected table'. foreach (DataGridViewCell dataGridViewCell in this.individualSelectedCells) { if (dataGridViewCell.Visible) { if (dataGridViewCell.RowIndex < lRowIndex) { lRowIndex = dataGridViewCell.RowIndex; } if (dataGridViewCell.RowIndex > uRowIndex) { uRowIndex = dataGridViewCell.RowIndex; } if (lColumn == null || this.Columns.DisplayInOrder(dataGridViewCell.ColumnIndex, lColumn.Index)) { lColumn = dataGridViewCell.OwningColumn; } if (uColumn == null || this.Columns.DisplayInOrder(uColumn.Index, dataGridViewCell.ColumnIndex)) { uColumn = dataGridViewCell.OwningColumn; } } } Debug.Assert(lRowIndex != -1); Debug.Assert(uRowIndex != -1); Debug.Assert(lColumn != null); Debug.Assert(uColumn != null); Debug.Assert(lColumn.Index == uColumn.Index || this.Columns.DisplayInOrder(lColumn.Index, uColumn.Index)); Debug.Assert(lRowIndex <= uRowIndex); foreach (string format in formats) { /* if (!String.Equals(format, DataFormats.Html, StringComparison.OrdinalIgnoreCase) && !String.Equals(format, DataFormats.Text, StringComparison.OrdinalIgnoreCase) && !String.Equals(format, DataFormats.UnicodeText, StringComparison.OrdinalIgnoreCase) && !String.Equals(format, DataFormats.CommaSeparatedValue, StringComparison.OrdinalIgnoreCase)) { continue; }*/ if (sbContent == null) { sbContent = new StringBuilder(1024); } else { sbContent.Length = 0; } if (includeColumnHeaders) { if (this.RightToLeftInternal) { // Cycle through the visible columns from uColumn to lColumn dataGridViewColumn = uColumn; Debug.Assert(dataGridViewColumn != null); while (dataGridViewColumn != null) { if (dataGridViewColumn != lColumn) { prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); Debug.Assert(prevDataGridViewColumn != null); } else { prevDataGridViewColumn = null; } cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1, dataGridViewColumn == uColumn /*firstCell*/, !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/, true /*inFirstRow*/, false /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } dataGridViewColumn = prevDataGridViewColumn; } if (includeRowHeaders) { cellContent = this.TopLeftHeaderCell.GetClipboardContentInternal(-1, false /*firstCell*/, true /*lastCell*/, true /*inFirstRow*/, false /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } } } else { if (includeRowHeaders) { cellContent = this.TopLeftHeaderCell.GetClipboardContentInternal(-1, true /*firstCell*/, false /*lastCell*/, true /*inFirstRow*/, false /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } } // Cycle through the visible columns from lColumn to uColumn dataGridViewColumn = lColumn; Debug.Assert(dataGridViewColumn != null); while (dataGridViewColumn != null) { if (dataGridViewColumn != uColumn) { nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); Debug.Assert(nextDataGridViewColumn != null); } else { nextDataGridViewColumn = null; } cellContent = dataGridViewColumn.HeaderCell.GetClipboardContentInternal(-1, !includeRowHeaders && dataGridViewColumn == lColumn /*firstCell*/, nextDataGridViewColumn == null /*lastCell*/, true /*inFirstRow*/, false /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } dataGridViewColumn = nextDataGridViewColumn; } } } // Cycle through the visible rows from lRowIndex to uRowIndex. bool firstRowIndex = true; int rowIndex = lRowIndex; int nextRowIndex = -1; Debug.Assert(rowIndex != -1); while (rowIndex != -1) { if (rowIndex != uRowIndex) { nextRowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible); Debug.Assert(nextRowIndex != -1); } else { nextRowIndex = -1; } if (this.RightToLeftInternal) { // Cycle through the visible columns from uColumn to lColumn dataGridViewColumn = uColumn; Debug.Assert(dataGridViewColumn != null); while (dataGridViewColumn != null) { if (dataGridViewColumn != lColumn) { prevDataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); Debug.Assert(prevDataGridViewColumn != null); } else { prevDataGridViewColumn = null; } cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex, dataGridViewColumn == uColumn /*firstCell*/, !includeRowHeaders && prevDataGridViewColumn == null /*lastCell*/, !includeColumnHeaders && firstRowIndex /*inFirstRow*/, nextRowIndex == -1 /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } dataGridViewColumn = prevDataGridViewColumn; } if (includeRowHeaders) { // Get the row header clipboard content cellContent = this.Rows.SharedRow(rowIndex).HeaderCell.GetClipboardContentInternal(rowIndex, false /*firstCell*/, true /*lastCell*/, !includeColumnHeaders && firstRowIndex /*inFirstRow*/, nextRowIndex == -1 /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } } } else { if (includeRowHeaders) { // Get the row header clipboard content cellContent = this.Rows.SharedRow(rowIndex).HeaderCell.GetClipboardContentInternal(rowIndex, true /*firstCell*/, false /*lastCell*/, !includeColumnHeaders && firstRowIndex /*inFirstRow*/, nextRowIndex == -1 /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } } // Cycle through the visible columns from lColumn to uColumn dataGridViewColumn = lColumn; Debug.Assert(dataGridViewColumn != null); while (dataGridViewColumn != null) { if (dataGridViewColumn != uColumn) { nextDataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); Debug.Assert(nextDataGridViewColumn != null); } else { nextDataGridViewColumn = null; } cellContent = this.Rows.SharedRow(rowIndex).Cells[dataGridViewColumn.Index].GetClipboardContentInternal(rowIndex, !includeRowHeaders && dataGridViewColumn == lColumn /*firstCell*/, nextDataGridViewColumn == null /*lastCell*/, !includeColumnHeaders && firstRowIndex /*inFirstRow*/, nextRowIndex == -1 /*inLastRow*/, format) as string; if (cellContent != null) { sbContent.Append(cellContent); } dataGridViewColumn = nextDataGridViewColumn; } } rowIndex = nextRowIndex; firstRowIndex = false; } if (String.Equals(format, DataFormats.Html, StringComparison.OrdinalIgnoreCase)) { System.IO.MemoryStream utf8Stream = null; GetClipboardContentForHtml(sbContent, out utf8Stream); dataObject.SetData(format, false /*autoConvert*/, utf8Stream); } else { dataObject.SetData(format, false /*autoConvert*/, sbContent.ToString()); } } break; } return dataObject; } private static void GetClipboardContentForHtml(StringBuilder sbContent, out System.IO.MemoryStream utf8Stream) { byte[] sourceBytes = Encoding.Unicode.GetBytes(sbContent.ToString()); byte[] destinationBytes = Encoding.Convert(Encoding.Unicode, Encoding.UTF8, sourceBytes); // Marshal.SystemDefaultCharSize is 2 on WinXP Pro - so the offsets seem to be in character counts instead of bytes. // Test on JPN and Win9x machines. int bytecountEndOfFragment = 135 + destinationBytes.Length; int bytecountEndOfHtml = bytecountEndOfFragment + 36; string prefix = string.Format(CultureInfo.InvariantCulture, DATAGRIDVIEW_htmlPrefix, bytecountEndOfHtml.ToString("00000000", CultureInfo.InvariantCulture), bytecountEndOfFragment.ToString("00000000", CultureInfo.InvariantCulture)) + DATAGRIDVIEW_htmlStartFragment; sbContent.Insert(0, prefix); sbContent.Append(DATAGRIDVIEW_htmlEndFragment); sourceBytes = Encoding.Unicode.GetBytes(sbContent.ToString()); destinationBytes = Encoding.Convert(Encoding.Unicode, Encoding.UTF8, sourceBytes); utf8Stream = new System.IO.MemoryStream(bytecountEndOfHtml + 1); utf8Stream.Write(destinationBytes, 0, bytecountEndOfHtml); utf8Stream.WriteByte((byte)0); #if DEBUG Debug.Assert(destinationBytes[97] == '<'); Debug.Assert(destinationBytes[bytecountEndOfHtml-1] == '>'); Debug.Assert(destinationBytes[133] == '<'); Debug.Assert(destinationBytes[bytecountEndOfFragment] == '<'); #endif } /// // Rectangle returned includes the potential column header public Rectangle GetColumnDisplayRectangle(int columnIndex, bool cutOverflow) { if (columnIndex < 0 || columnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("columnIndex"); } return GetColumnDisplayRectanglePrivate(columnIndex, cutOverflow); } private Rectangle GetColumnDisplayRectanglePrivate(int columnIndex, bool cutOverflow) { Debug.Assert(columnIndex >= 0 && columnIndex < this.Columns.Count); if (!this.Columns[columnIndex].Displayed) { return Rectangle.Empty; } Rectangle data = this.layout.Data; int cx; bool columnFound = false; DataGridViewColumn dataGridViewColumn; if (this.RightToLeftInternal) { cx = data.Right; } else { cx = data.X; } for (dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); dataGridViewColumn != null && !columnFound; ) { if ((this.RightToLeftInternal && cx < data.X) || (!this.RightToLeftInternal && cx > data.Right)) { break; } if (dataGridViewColumn.Index == columnIndex) { columnFound = true; } else { if (this.RightToLeftInternal) { cx -= dataGridViewColumn.Thickness; } else { cx += dataGridViewColumn.Thickness; } dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen, DataGridViewElementStates.None); } } if (!columnFound && this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0) { for (dataGridViewColumn = this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol]; dataGridViewColumn != null && !columnFound; ) { if ((this.RightToLeftInternal && cx < data.X) || (!this.RightToLeftInternal && cx > data.Right)) { break; } if (dataGridViewColumn.Index == columnIndex) { columnFound = true; } else { if (this.RightToLeftInternal) { cx -= dataGridViewColumn.Thickness; } else { cx += dataGridViewColumn.Thickness; } if (dataGridViewColumn.Index == this.displayedBandsInfo.FirstDisplayedScrollingCol) { if (this.RightToLeftInternal) { cx += this.negOffset; } else { cx -= this.negOffset; } } dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); } } } if (columnFound) { Debug.Assert(dataGridViewColumn != null); int displayWidth, viewedColumnWidth = dataGridViewColumn.Thickness; if (dataGridViewColumn.Index == this.displayedBandsInfo.FirstDisplayedScrollingCol) { viewedColumnWidth -= this.negOffset; } if (cutOverflow && ((!this.RightToLeftInternal && cx + viewedColumnWidth > data.Right) || (this.RightToLeftInternal && cx - viewedColumnWidth < data.X))) { if (this.RightToLeftInternal) { displayWidth = cx - data.X; } else { displayWidth = data.Right - cx; } } else { displayWidth = viewedColumnWidth; } Rectangle columnRect; if (this.RightToLeftInternal) { columnRect = new Rectangle(cx - displayWidth, data.Y, displayWidth, data.Height); } else { columnRect = new Rectangle(cx, data.Y, displayWidth, data.Height); } if (this.layout.ColumnHeadersVisible) { columnRect.Height += this.layout.ColumnHeaders.Height; columnRect.Y -= this.layout.ColumnHeaders.Height; } return columnRect; } return Rectangle.Empty; } // xColumnLeftEdge returns the left edge of the column when RightToLeft is false. // xColumnLeftEdge returns the right edge of the column when RightToLeft is true. private int GetColumnIndexFromX(int x, out int xColumnLeftEdge) { Rectangle data = this.layout.Data; Debug.Assert(this.RightToLeftInternal || (x >= data.X - 1 && x < data.Right), "x must be inside the horizontal bounds of this.layout.Data"); Debug.Assert(!this.RightToLeftInternal || (x >= data.X && x <= data.Right), "x must be inside the horizontal bounds of this.layout.Data"); if (!this.RightToLeftInternal && x == data.X - 1) { x++; } else if (this.RightToLeftInternal && x == data.Right) { x--; } int cx; if (this.RightToLeftInternal) { cx = data.Right-1; } else { cx = data.X; } // first try to match x against a frozen column DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); while (dataGridViewColumn != null && ((!this.RightToLeftInternal && cx < data.Right) || (this.RightToLeftInternal && cx >= data.X))) { if (this.RightToLeftInternal) { cx -= dataGridViewColumn.Thickness; } else { cx += dataGridViewColumn.Thickness; } if (!this.RightToLeftInternal && cx > x) { xColumnLeftEdge = cx - dataGridViewColumn.Thickness; return dataGridViewColumn.Index; } else if (this.RightToLeftInternal && cx < x) { xColumnLeftEdge = cx + dataGridViewColumn.Thickness; return dataGridViewColumn.Index; } dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen, DataGridViewElementStates.None); } if (this.RightToLeftInternal) { cx += this.negOffset; } else { cx -= this.negOffset; } // second try to match x against a scrolling column if (this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0) { dataGridViewColumn = this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol]; while (dataGridViewColumn != null && ((!this.RightToLeftInternal && cx < data.Right) || (this.RightToLeftInternal && cx >= data.X))) { Debug.Assert(dataGridViewColumn.Visible && !dataGridViewColumn.Frozen); if (this.RightToLeftInternal) { cx -= dataGridViewColumn.Thickness; } else { cx += dataGridViewColumn.Thickness; } if (!this.RightToLeftInternal && cx > x) { xColumnLeftEdge = cx - dataGridViewColumn.Thickness; return dataGridViewColumn.Index; } else if (this.RightToLeftInternal && cx < x) { xColumnLeftEdge = cx + dataGridViewColumn.Thickness; return dataGridViewColumn.Index; } dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); } } xColumnLeftEdge = -1; return -1; } private static int GetColumnScrollRate(int xOffset) { Debug.Assert(xOffset > 0); // Counting 20ms for executing the actual column scrolling if (xOffset <= 10) { return 480; // Two columns per second } if (xOffset <= 15) { return 313; // Three columns per second } if (xOffset <= 25) { return 180; // Five columns per second } if (xOffset <= 35) { return 123; // Seven columns per second } return Math.Max(1, 4000 / xOffset); } /// /// Returns the coordinate of the left edge of the given column. Note that /// the column does not need to be completely visible on the display area. /// Value returned is not necessarily within layout.Data because of the /// this.negOffset value, or because the column may start to the right of /// data area, or behind the frozen area, or completely on the left of the control. /// The right edge is returned in RightToLeft mode. /// internal int GetColumnXFromIndex(int index) { Debug.Assert(index < this.Columns.Count); Debug.Assert(this.Columns[index].Visible); int x; if (this.RightToLeftInternal) { x = this.layout.Data.Right-1; } else { x = this.layout.Data.X; } DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); while (dataGridViewColumn != null) { if (index == dataGridViewColumn.Index) { return x; } if (this.RightToLeftInternal) { x -= dataGridViewColumn.Thickness; } else { x += dataGridViewColumn.Thickness; } dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen, DataGridViewElementStates.None); } if (this.RightToLeftInternal) { x += this.negOffset; } else { x -= this.negOffset; } int xFirstVisibleScrollingCol = x; if (this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0) { dataGridViewColumn = this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol]; } else { dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); } Debug.Assert(dataGridViewColumn.Visible && !dataGridViewColumn.Frozen); while (dataGridViewColumn != null) { if (index == dataGridViewColumn.Index) { return x; } if (this.RightToLeftInternal) { x -= dataGridViewColumn.Thickness; } else { x += dataGridViewColumn.Thickness; } dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); } // The column is completely hidden on the left/right of the dataGridView x = xFirstVisibleScrollingCol; dataGridViewColumn = this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol]; dataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); while (dataGridViewColumn != null) { if (this.RightToLeftInternal) { x += dataGridViewColumn.Thickness; } else { x -= dataGridViewColumn.Thickness; } if (index == dataGridViewColumn.Index) { return x; } dataGridViewColumn = this.Columns.GetPreviousColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); } Debug.Fail("Could not find column in GetColumnXFromIndex"); return 0; } private int GetNegOffsetFromHorizontalOffset(int horizontalOffset) { DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); while (dataGridViewColumn != null && dataGridViewColumn.Thickness <= horizontalOffset) { horizontalOffset -= dataGridViewColumn.Thickness; dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); } return horizontalOffset; } private bool GetOutOfBoundCorrectedHitTestInfo(ref HitTestInfo hti, ref int mouseX, ref int mouseY, out int xOffset, out int yOffset) { xOffset = yOffset = 0; Rectangle rectScrollingArea = this.layout.Data; int visibleRowsHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible); int frozenVisibleRowsHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); int fittingTrailingScrollingRowsHeight = ComputeHeightOfFittingTrailingScrollingRows(frozenVisibleRowsHeight); int trailingScrollingRowsHeight = ComputeHeightOfTrailingScrollingRows(); int emptyBackgroundWidth = Math.Max(0, this.layout.Data.Width - this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible)); int emptyBackgroundHeight = Math.Max(0, this.layout.Data.Height - frozenVisibleRowsHeight - trailingScrollingRowsHeight); Debug.Assert(!this.vertScrollBar.Enabled || !this.vertScrollBar.Visible || this.vertScrollBar.Maximum == visibleRowsHeight - frozenVisibleRowsHeight); //VSWhidbey 525671 //Debug.Assert(!this.vertScrollBar.Enabled || // !this.vertScrollBar.Visible || // this.vertScrollBar.Value >= this.verticalOffset); if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect]) { if (this.layout.RowHeadersVisible) { // Include row headers rectScrollingArea = Rectangle.Union(rectScrollingArea, this.layout.RowHeaders); } // Discard frozen rows DiscardZonesInScrollingArea(ref rectScrollingArea, emptyBackgroundWidth, emptyBackgroundHeight, frozenVisibleRowsHeight, false /*discardFrozenColumns*/, true /*discardFrozenRows*/); if (mouseY >= rectScrollingArea.Top && mouseY <= rectScrollingArea.Bottom) { // Mouse's Y is in-bound -- correct X value hti = HitTest(this.RightToLeftInternal ? rectScrollingArea.Right-1 : rectScrollingArea.Left, mouseY); if (this.ptAnchorCell.Y != -1 && (this.Rows.GetRowState(this.ptAnchorCell.Y) & DataGridViewElementStates.Frozen) != 0 && this.trackRowEdge != -1 && (this.Rows.GetRowState(this.trackRowEdge) & DataGridViewElementStates.Frozen) != 0 && hti.row >= 0 && (this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Frozen) == 0) { // Anchor cell is in frozen row and target cell is in unfrozen row. Make sure no row is scrolled off. Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0); int firstUnfrozenRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); int firstColumnIndex; if (hti.col >= 0) { firstColumnIndex = hti.col; } else { DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); firstColumnIndex = (dataGridViewColumn == null) ? -1 : dataGridViewColumn.Index; } if (firstColumnIndex >= 0 && firstUnfrozenRowIndex >= 0) { if (!ScrollIntoView(firstColumnIndex, firstUnfrozenRowIndex, false /*forCurrentCellChange*/)) { return false; } hti = HitTest(this.RightToLeftInternal ? rectScrollingArea.Right : rectScrollingArea.Left, mouseY); } } return true; } // Mouse's Y is outside of scrolling bands if (mouseY < rectScrollingArea.Top) { if (this.ptAnchorCell.Y != -1 && ((this.Rows.GetRowState(this.ptAnchorCell.Y) & DataGridViewElementStates.Frozen) == 0 || (this.trackRowEdge != -1 && (this.Rows.GetRowState(this.trackRowEdge) & DataGridViewElementStates.Frozen) == 0)) && this.verticalOffset != 0) { // Up scrolling is required because the anchor's row is unfrozen Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0); yOffset = mouseY - rectScrollingArea.Top; // yOffset strictly negative if (this.RightToLeftInternal) { mouseX = rectScrollingArea.Right-1; } else { mouseX = rectScrollingArea.Left+1; } } else { hti = HitTest(this.RightToLeftInternal ? rectScrollingArea.Right : rectScrollingArea.Left, mouseY); } } else { Debug.Assert(mouseY > rectScrollingArea.Bottom); if (this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0) { if (this.verticalOffset + this.Rows.SharedRow(this.displayedBandsInfo.FirstDisplayedScrollingRow).GetHeight(this.displayedBandsInfo.FirstDisplayedScrollingRow) <= visibleRowsHeight - frozenVisibleRowsHeight - fittingTrailingScrollingRowsHeight) { // Down scrolling is required yOffset = mouseY - rectScrollingArea.Bottom; // yOffset strictly positive if (this.RightToLeftInternal) { mouseX = rectScrollingArea.Right-1; } else { mouseX = rectScrollingArea.Left+1; } } } } return true; } if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect]) { if (this.layout.ColumnHeadersVisible) { // Include column headers rectScrollingArea = Rectangle.Union(rectScrollingArea, this.layout.ColumnHeaders); } // Discard frozen columns DiscardZonesInScrollingArea(ref rectScrollingArea, emptyBackgroundWidth, emptyBackgroundHeight, frozenVisibleRowsHeight, true /*discardFrozenColumns*/, false /*discardFrozenRows*/); if (mouseX >= rectScrollingArea.Left && mouseX <= rectScrollingArea.Right) { // Mouse's X is in-bound -- correct Y value hti = HitTest(mouseX, rectScrollingArea.Top); if (this.ptAnchorCell.X != -1 && this.Columns[this.ptAnchorCell.X].Frozen && this.trackColumnEdge != -1 && this.Columns[this.trackColumnEdge].Frozen && hti.col >= 0 && !this.Columns[hti.col].Frozen) { // Anchor cell is in frozen column and target cell is in unfrozen column. Make sure no column is scrolled off. Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0); int firstUnfrozenColumnIndex = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen).Index; int firstRowIndex; if (hti.row >= 0) { firstRowIndex = hti.row; } else { firstRowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); } if (firstRowIndex >= 0 && firstUnfrozenColumnIndex >= 0) { if (!ScrollIntoView(firstUnfrozenColumnIndex, firstRowIndex, false /*forCurrentCellChange*/)) { return false; } hti = HitTest(mouseX, rectScrollingArea.Top); } } return true; } // Mouse's X is outside of scrolling bands if ((!this.RightToLeftInternal && mouseX < rectScrollingArea.Left) || (this.RightToLeftInternal && mouseX > rectScrollingArea.Right)) { if (this.ptAnchorCell.X != -1 && (!this.Columns[this.ptAnchorCell.X].Frozen || (this.trackColumnEdge != -1 && !this.Columns[this.trackColumnEdge].Frozen)) && this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0 && (this.negOffset > 0 || this.Columns.GetPreviousColumn(this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol], DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen) != null)) { // xOffset strictly negative if (this.RightToLeftInternal) { // Right scrolling is required xOffset = rectScrollingArea.Right - mouseX; } else { // Left scrolling is required xOffset = mouseX - rectScrollingArea.Left; } mouseY = rectScrollingArea.Top+1; } else { hti = HitTest(mouseX, rectScrollingArea.Top); } } else { Debug.Assert((!this.RightToLeftInternal && mouseX > rectScrollingArea.Right) || (this.RightToLeftInternal && mouseX < rectScrollingArea.Left)); if (this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0) { if (this.displayedBandsInfo.LastTotallyDisplayedScrollingCol != -1 && this.Columns.GetNextColumn(this.Columns[this.displayedBandsInfo.LastTotallyDisplayedScrollingCol], DataGridViewElementStates.Visible, DataGridViewElementStates.None) == null) { // No more columns to scroll return true; } DataGridViewColumn newFirstVisibleScrollingCol = this.Columns.GetNextColumn(this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol], DataGridViewElementStates.Visible, DataGridViewElementStates.None); int newColOffset = 0; for (DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); dataGridViewColumn != newFirstVisibleScrollingCol; dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None)) { newColOffset += dataGridViewColumn.Thickness; } if (this.HorizontalOffset != newColOffset) { // xOffset strictly positive if (this.RightToLeftInternal) { // Left scrolling is required xOffset = rectScrollingArea.Left - mouseX; } else { // Right scrolling is required xOffset = mouseX - rectScrollingArea.Right; } mouseY = rectScrollingArea.Top+1; } } } return true; } if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect]) { bool recomputeHitTestInfo = false; // Discard frozen columns and rows DiscardZonesInScrollingArea(ref rectScrollingArea, emptyBackgroundWidth, emptyBackgroundHeight, frozenVisibleRowsHeight, true /*discardFrozenColumns*/, true /*discardFrozenRows*/); if (mouseY < rectScrollingArea.Top) { // Mouse's Y is above scrolling bands if ( ( (this.ptAnchorCell.Y != -1 && (this.Rows.GetRowState(this.ptAnchorCell.Y) & DataGridViewElementStates.Frozen) == 0) || (this.ptCurrentCell.Y != -1 && (this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.Frozen) == 0) ) && this.verticalOffset != 0 ) { // Up scrolling is required - the anchor's row is unfrozen Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0); yOffset = mouseY - rectScrollingArea.Top; // yOffset strictly negative } else { // Correct mouse's Y - no scrolling can be performed if (mouseY < this.layout.Data.Top) { mouseY = this.layout.Data.Top+1; recomputeHitTestInfo = true; } } } else if (mouseY > rectScrollingArea.Bottom) { // Mouse's Y is below scrolling bands if (this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0) { if (this.verticalOffset + this.Rows.SharedRow(this.displayedBandsInfo.FirstDisplayedScrollingRow).GetHeight(this.displayedBandsInfo.FirstDisplayedScrollingRow) <= visibleRowsHeight - frozenVisibleRowsHeight - fittingTrailingScrollingRowsHeight) { // Down scrolling is required yOffset = mouseY - rectScrollingArea.Bottom; // yOffset strictly positive } else { // Correct mouse's Y - no scrolling can be performed mouseY = rectScrollingArea.Bottom-1; recomputeHitTestInfo = true; } } else { // Correct mouse's Y - no scrolling can be performed mouseY = rectScrollingArea.Bottom-1; recomputeHitTestInfo = true; } } #if DEBUG else { // Mouse's Y is in-bound Debug.Assert(mouseY >= rectScrollingArea.Top && mouseY <= rectScrollingArea.Bottom); } #endif if ((!this.RightToLeftInternal && mouseX < rectScrollingArea.Left) || (this.RightToLeftInternal && mouseX > rectScrollingArea.Right)) { // Mouse's X is on the left of scrolling bands (LTR) if ( ( (this.ptAnchorCell.X != -1 && !this.Columns[this.ptAnchorCell.X].Frozen) || (this.ptCurrentCell.X != -1 && !this.Columns[this.ptCurrentCell.X].Frozen) ) && this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0 && (this.negOffset > 0 || this.Columns.GetPreviousColumn(this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol], DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen) != null) ) { // xOffset strictly negative if (this.RightToLeftInternal) { // Right scrolling is required - anchor's column is unfrozen xOffset = rectScrollingArea.Right - mouseX; } else { // Left scrolling is required - anchor's column is unfrozen xOffset = mouseX - rectScrollingArea.Left; } } else { // Correct mouse's X - no scrolling can be performed if (!this.RightToLeftInternal && mouseX < this.layout.Data.Left) { mouseX = this.layout.Data.Left+1; recomputeHitTestInfo = true; } else if (this.RightToLeftInternal && mouseX > this.layout.Data.Right) { mouseX = this.layout.Data.Right-1; recomputeHitTestInfo = true; } } } else if ((!this.RightToLeftInternal && mouseX > rectScrollingArea.Right) || (this.RightToLeftInternal && mouseX < rectScrollingArea.Left)) { // Mouse's X is on the right of scrolling bands (LTR) if (this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0 && (this.displayedBandsInfo.LastTotallyDisplayedScrollingCol == -1 || this.Columns.GetNextColumn(this.Columns[this.displayedBandsInfo.LastTotallyDisplayedScrollingCol], DataGridViewElementStates.Visible, DataGridViewElementStates.None) != null)) { DataGridViewColumn newFirstVisibleScrollingCol = this.Columns.GetNextColumn(this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol], DataGridViewElementStates.Visible, DataGridViewElementStates.None); int newColOffset = 0; for (DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); dataGridViewColumn != newFirstVisibleScrollingCol; dataGridViewColumn = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None)) { newColOffset += dataGridViewColumn.Thickness; } if (this.HorizontalOffset != newColOffset) { // xOffset strictly positive if (this.RightToLeftInternal) { // Left scrolling is required xOffset = rectScrollingArea.Left - mouseX; } else { // Right scrolling is required xOffset = mouseX - rectScrollingArea.Right; } } else { // Correct mouse's X - no scrolling can be performed if (this.RightToLeftInternal) { mouseX = rectScrollingArea.Left+1; } else { mouseX = rectScrollingArea.Right-1; } recomputeHitTestInfo = true; } } else { // Correct mouse's X - no scrolling can be performed if (this.RightToLeftInternal) { mouseX = rectScrollingArea.Left+1; } else { mouseX = rectScrollingArea.Right-1; } recomputeHitTestInfo = true; } } #if DEBUG else { // Mouse's X is in-bound Debug.Assert(mouseX >= rectScrollingArea.Left && mouseX <= rectScrollingArea.Right); } #endif if (recomputeHitTestInfo) { hti = HitTest(mouseX, mouseY); } } return true; } internal override Size GetPreferredSizeCore(Size proposedConstraints) { int bordersAndPaddingWidth = 2*(this.BorderWidth + this.Padding.Size.Width); int bordersAndPaddingHeight = 2*(this.BorderWidth + this.Padding.Size.Height); bool allowHorizScrollbar = (this.scrollBars == ScrollBars.Both) || (this.scrollBars == ScrollBars.Horizontal); bool allowVertScrollbar = (this.scrollBars == ScrollBars.Both) || (this.scrollBars == ScrollBars.Vertical); int minimumWidth = 16 + bordersAndPaddingWidth; if (allowVertScrollbar) { minimumWidth += this.vertScrollBar.Width; } if (this.RowHeadersVisible) { minimumWidth += this.RowHeadersWidth; } int preferredWidth = Math.Min(minimumWidth + this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible), proposedConstraints.Width); if (preferredWidth < minimumWidth) { preferredWidth = minimumWidth; } int minimumHeight = 16 + bordersAndPaddingHeight; if (allowHorizScrollbar) { minimumHeight += this.horizScrollBar.Height; } if (this.ColumnHeadersVisible) { minimumHeight += this.ColumnHeadersHeight; } int preferredHeight = Math.Min(minimumHeight + this.Rows.GetRowsHeight(DataGridViewElementStates.Visible), proposedConstraints.Height); if (preferredHeight < minimumHeight) { preferredHeight = minimumHeight; } return new Size(preferredWidth, preferredHeight); } ///// Rectangle returned includes the potential row header public Rectangle GetRowDisplayRectangle(int rowIndex, bool cutOverflow) { if (rowIndex < 0 || rowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("rowIndex"); } return GetRowDisplayRectanglePrivate(rowIndex, cutOverflow); } private Rectangle GetRowDisplayRectanglePrivate(int rowIndex, bool cutOverflow) { Debug.Assert(rowIndex >= 0 && rowIndex < this.Rows.Count); if ((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Displayed) == 0) { return Rectangle.Empty; } Rectangle data = this.layout.Data; int cy = data.Y; bool rowFound = false; int indexTmp; for (indexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); indexTmp != -1 && !rowFound; ) { if (cy > data.Bottom) { break; } if (indexTmp == rowIndex) { rowFound = true; } else { cy += this.Rows.SharedRow(indexTmp).GetHeight(indexTmp); indexTmp = this.Rows.GetNextRow(indexTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); } } if (!rowFound && this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0) { for (indexTmp = this.displayedBandsInfo.FirstDisplayedScrollingRow; indexTmp != -1 && !rowFound; ) { if (cy > data.Bottom) { break; } if (indexTmp == rowIndex) { rowFound = true; } else { cy += this.Rows.SharedRow(indexTmp).GetHeight(indexTmp); indexTmp = this.Rows.GetNextRow(indexTmp, DataGridViewElementStates.Visible); } } } if (rowFound) { int displayHeight; if (cutOverflow && cy + this.Rows.SharedRow(indexTmp).GetHeight(indexTmp) > data.Bottom) { displayHeight = data.Bottom - cy; } else { displayHeight = this.Rows.SharedRow(indexTmp).GetHeight(indexTmp); } Rectangle rowRect = new Rectangle(data.X, cy, data.Width, displayHeight); if (this.layout.RowHeadersVisible) { rowRect.Width += this.layout.RowHeaders.Width; if (!this.RightToLeftInternal) { rowRect.X -= this.layout.RowHeaders.Width; } } return rowRect; } return Rectangle.Empty; } private int GetRowIndexFromY(int y, out int yRowTopEdge) { Rectangle data = this.layout.Data; Debug.Assert(y >= data.Y-1 && y < data.Bottom, "y must be inside the vertical bounds of the data area."); if (y == data.Y-1) { y++; } int rowHeight; int cy = data.Y; // first try to match y against a frozen rows int indexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); while (indexTmp != -1 && cy < data.Bottom) { rowHeight = this.Rows.SharedRow(indexTmp).GetHeight(indexTmp); cy += rowHeight; if (cy > y) { yRowTopEdge = cy - rowHeight; return indexTmp; } indexTmp = this.Rows.GetNextRow(indexTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); } // second try to match y against a scrolling row if (this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0) { indexTmp = this.displayedBandsInfo.FirstDisplayedScrollingRow; Debug.Assert((this.Rows.GetRowState(indexTmp) & DataGridViewElementStates.Visible) != 0 && (this.Rows.GetRowState(indexTmp) & DataGridViewElementStates.Frozen) == 0); while (indexTmp != -1 && cy < data.Bottom) { rowHeight = this.Rows.SharedRow(indexTmp).GetHeight(indexTmp); cy += rowHeight; if (cy > y) { yRowTopEdge = cy - rowHeight; return indexTmp; } indexTmp = this.Rows.GetNextRow(indexTmp, DataGridViewElementStates.Visible); } } yRowTopEdge = -1; return -1; } private static int GetRowScrollRate(int yOffset) { Debug.Assert(yOffset > 0); // Counting 10ms for executing the actual row scrolling if (yOffset <= 10) { return 90; // Ten rows per second } if (yOffset <= 15) { return 57; // Fifteen rows per second } if (yOffset <= 25) { return 30; // Twenty-five rows per second } if (yOffset <= 35) { return 18; // Thirty-five rows per second } return Math.Max(1, 600 / yOffset); } /// /// Returns the coordinate of the upper edge of the given row. Note that /// the row does not need to be completely visible on the display area. /// Value returned is not necessarily within layout.Data because the row /// may start below the data area. /// internal int GetRowYFromIndex(int index) { Debug.Assert(index >= 0 && index < this.Rows.Count); Debug.Assert((this.Rows.GetRowState(index) & DataGridViewElementStates.Visible) != 0); int y = this.layout.Data.Y; int indexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); while (indexTmp != -1) { if (index == indexTmp) { return y; } y += this.Rows.SharedRow(indexTmp).GetHeight(indexTmp); indexTmp = this.Rows.GetNextRow(indexTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); } int yFirstVisibleScrollingRow = y; if (this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0) { if (index >= this.displayedBandsInfo.FirstDisplayedScrollingRow) { // index is part of the scrolling rows below the frozen rows indexTmp = this.displayedBandsInfo.FirstDisplayedScrollingRow; } else { // index is part of the rows hidden behind the frozen rows or on top of the control indexTmp = -1; } } else { // frozen rows cover all the rows real-estate. Look for index starting at the first visible non-frozen row. indexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); Debug.Assert(indexTmp != -1); } if (indexTmp != -1) { Debug.Assert((this.Rows.GetRowState(indexTmp) & DataGridViewElementStates.Visible) != 0 && (this.Rows.GetRowState(indexTmp) & DataGridViewElementStates.Frozen) == 0); while (indexTmp != -1) { if (index == indexTmp) { return y; } y += this.Rows.SharedRow(indexTmp).GetHeight(indexTmp); indexTmp = this.Rows.GetNextRow(indexTmp, DataGridViewElementStates.Visible); } } // Row is completely hidden behind frozen rows or on top of control y = yFirstVisibleScrollingRow; Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow != -1); indexTmp = this.Rows.GetPreviousRow(this.displayedBandsInfo.FirstDisplayedScrollingRow, DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); while (indexTmp != -1) { y -= this.Rows.SharedRow(indexTmp).GetHeight(indexTmp); if (index == indexTmp) { return y; } indexTmp = this.Rows.GetPreviousRow(indexTmp, DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); } Debug.Fail("Could not find row in GetRowYFromIndex"); return 0; } private bool GetTabKeyEffective(bool shift, bool ctrl) { if (this.StandardTab) { return ctrl && !((!shift && (!this.VisibleCellExists || this.CurrentCellIsLastVisibleCell)) || (shift && (!this.VisibleCellExists || this.CurrentCellIsFirstVisibleCell))); } else { return !ctrl && !((!shift && (!this.VisibleCellExists || this.CurrentCellIsLastVisibleCell)) || (shift && (!this.VisibleCellExists || this.CurrentCellIsFirstVisibleCell))); } } ///public HitTestInfo HitTest(int x, int y) { HitTestInfo hti = new HitTestInfo(); if (!this.layout.Inside.Contains(x, y)) { return hti; } if (this.horizScrollBar != null && this.horizScrollBar.Visible && this.horizScrollBar.Bounds.Contains(x, y)) { hti.type = DataGridViewHitTestType.HorizontalScrollBar; return hti; } if (this.vertScrollBar != null && this.vertScrollBar.Visible && this.vertScrollBar.Bounds.Contains(x, y)) { hti.type = DataGridViewHitTestType.VerticalScrollBar; return hti; } if (this.layout.TopLeftHeader.Contains(x, y)) { hti.type = DataGridViewHitTestType.TopLeftHeader; hti.typeInternal = DataGridViewHitTestTypeInternal.TopLeftHeader; if (this.RightToLeftInternal) { hti.colStart = this.layout.TopLeftHeader.Right-1; } else { hti.colStart = this.layout.TopLeftHeader.Left; } hti.rowStart = this.layout.TopLeftHeader.Top; if ((!this.RightToLeftInternal && this.layout.TopLeftHeader.Right - x < DATAGRIDVIEW_columnSizingHotZone) || (this.RightToLeftInternal && x - this.layout.TopLeftHeader.Left < DATAGRIDVIEW_columnSizingHotZone)) { //hti.edge = DataGridViewHitTestTypeCloseEdge.Right; if (this.RowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing) { hti.typeInternal = DataGridViewHitTestTypeInternal.TopLeftHeaderResizeLeft; if (this.RightToLeftInternal) { hti.mouseBarOffset = this.layout.TopLeftHeader.Left - x - 1; } else { hti.mouseBarOffset = this.layout.TopLeftHeader.Right - x - 1; } } } else if (this.layout.TopLeftHeader.Top + this.layout.TopLeftHeader.Height - y < DATAGRIDVIEW_rowSizingHotZone) { //hti.edge = DataGridViewHitTestTypeCloseEdge.Bottom; if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.EnableResizing) { hti.typeInternal = DataGridViewHitTestTypeInternal.TopLeftHeaderResizeTop; hti.mouseBarOffset = this.layout.TopLeftHeader.Top + this.layout.TopLeftHeader.Height - y - 1; } } return hti; } // check for column resize / insertion if (this.layout.ColumnHeaders.Contains(x, y)) { int xColumnLeftEdge; // this is actually the right edge in RTL mode hti.col = GetColumnIndexFromX(x, out xColumnLeftEdge); if (hti.col < 0) { return HitTestInfo.Nowhere; } Debug.Assert(xColumnLeftEdge == GetColumnXFromIndex(hti.col)); hti.type = DataGridViewHitTestType.ColumnHeader; hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnHeader; hti.rowStart = this.layout.ColumnHeaders.Top; hti.colStart = xColumnLeftEdge; int columnWidth = this.Columns[hti.col].Thickness; if ((!this.RightToLeftInternal && xColumnLeftEdge + columnWidth - x < DATAGRIDVIEW_columnSizingHotZone) || (this.RightToLeftInternal && x - xColumnLeftEdge + columnWidth < DATAGRIDVIEW_columnSizingHotZone)) { //hti.edge = DataGridViewHitTestTypeCloseEdge.Right; if (this.RightToLeftInternal) { hti.mouseBarOffset = xColumnLeftEdge - columnWidth - x + 1; } else { hti.mouseBarOffset = xColumnLeftEdge + columnWidth - x - 1; } DataGridViewColumn dataGridViewColumn = this.Columns[hti.col]; if (dataGridViewColumn.Resizable == DataGridViewTriState.True && (dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.None || dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)) { hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnResizeRight; } else { hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnHeaderRight; } } else if ((!this.RightToLeftInternal && x - xColumnLeftEdge < DATAGRIDVIEW_columnSizingHotZone) || (this.RightToLeftInternal && xColumnLeftEdge - x < DATAGRIDVIEW_columnSizingHotZone)) { //hti.edge = DataGridViewHitTestTypeCloseEdge.Left; DataGridViewColumn dataGridViewColumn = null; // VS Whidbey bug 317105 - Condition unnecessary //if (hti.col != this.displayedBandsInfo.FirstDisplayedScrollingCol || this.displayedBandsInfo.LastTotallyDisplayedScrollingCol >= 0) //{ dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[hti.col], DataGridViewElementStates.Visible, DataGridViewElementStates.None); //} if (dataGridViewColumn != null) { hti.adjacentCol = dataGridViewColumn.Index; if (this.RightToLeftInternal) { hti.mouseBarOffset = xColumnLeftEdge - x + 1; } else { hti.mouseBarOffset = xColumnLeftEdge - x - 1; } if (dataGridViewColumn.Resizable == DataGridViewTriState.True && (dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.None || dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)) { hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnResizeLeft; } else { hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnHeaderLeft; } } else { if (this.RowHeadersVisible && this.RowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing) { hti.typeInternal = DataGridViewHitTestTypeInternal.TopLeftHeaderResizeRight; if (this.RightToLeftInternal) { hti.mouseBarOffset = xColumnLeftEdge - x; } else { hti.mouseBarOffset = xColumnLeftEdge - x - 1; } } else { hti.typeInternal = DataGridViewHitTestTypeInternal.FirstColumnHeaderLeft; } } } else if (this.layout.ColumnHeaders.Bottom - y < DATAGRIDVIEW_rowSizingHotZone) { //hti.edge = DataGridViewHitTestTypeCloseEdge.Bottom; if (/*!this.RowHeadersVisible &&*/ this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.EnableResizing) { hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnHeadersResizeBottom; hti.mouseBarOffset = this.layout.ColumnHeaders.Bottom - y - 1; } } } // check for row resize if (this.layout.RowHeaders.Contains(x, y)) { int yRowTopEdge; hti.row = GetRowIndexFromY(y, out yRowTopEdge); if (hti.row < 0) { return HitTestInfo.Nowhere; } Debug.Assert(yRowTopEdge == GetRowYFromIndex(hti.row)); hti.type = DataGridViewHitTestType.RowHeader; hti.typeInternal = DataGridViewHitTestTypeInternal.RowHeader; hti.rowStart = yRowTopEdge; if (this.RightToLeftInternal) { hti.colStart = this.layout.RowHeaders.Right-1; } else { hti.colStart = this.layout.RowHeaders.Left; } int rowHeight = this.Rows.SharedRow(hti.row).GetHeight(hti.row); if (yRowTopEdge + rowHeight - y < DATAGRIDVIEW_rowSizingHotZone) { //hti.edge = DataGridViewHitTestTypeCloseEdge.Bottom; if (RowIsResizable(hti.row) && this.AutoSizeRowsMode == DataGridViewAutoSizeRowsMode.None) { hti.typeInternal = DataGridViewHitTestTypeInternal.RowResizeBottom; hti.mouseBarOffset = yRowTopEdge + rowHeight - y - 1; } } else if (y - yRowTopEdge < DATAGRIDVIEW_rowSizingHotZone) { //hti.edge = DataGridViewHitTestTypeCloseEdge.Top; int indexTmp = -1; if (hti.row != this.displayedBandsInfo.FirstDisplayedScrollingRow || this.displayedBandsInfo.NumDisplayedFrozenRows > 0) { indexTmp = this.Rows.GetPreviousRow(hti.row, DataGridViewElementStates.Visible); } if (indexTmp != -1) { if (RowIsResizable(indexTmp) && this.AutoSizeRowsMode == DataGridViewAutoSizeRowsMode.None) { hti.typeInternal = DataGridViewHitTestTypeInternal.RowResizeTop; hti.adjacentRow = indexTmp; hti.mouseBarOffset = yRowTopEdge - y - 1; } } else { if (this.ColumnHeadersVisible && this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.EnableResizing) { hti.typeInternal = DataGridViewHitTestTypeInternal.TopLeftHeaderResizeBottom; hti.mouseBarOffset = yRowTopEdge - y - 1; } } } else if ((!this.RightToLeftInternal && this.layout.RowHeaders.Right - x < DATAGRIDVIEW_columnSizingHotZone) || (this.RightToLeftInternal && x - this.layout.RowHeaders.Left < DATAGRIDVIEW_columnSizingHotZone)) { //hti.edge = DataGridViewHitTestTypeCloseEdge.Right; if (this.RowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing) { hti.typeInternal = DataGridViewHitTestTypeInternal.RowHeadersResizeRight; if (this.RightToLeftInternal) { hti.mouseBarOffset = this.layout.RowHeaders.Left - x - 1; } else { hti.mouseBarOffset = this.layout.RowHeaders.Right - x - 1; } } } } if (this.layout.Data.Contains(x, y)) { int xColumnLeftEdge, yRowTopEdge; hti.col = GetColumnIndexFromX(x, out xColumnLeftEdge); hti.row = GetRowIndexFromY(y, out yRowTopEdge); if (hti.col < 0 || hti.row < 0) { return HitTestInfo.Nowhere; } Debug.Assert(xColumnLeftEdge == GetColumnXFromIndex(hti.col)); Debug.Assert(yRowTopEdge == GetRowYFromIndex(hti.row)); hti.type = DataGridViewHitTestType.Cell; hti.typeInternal = DataGridViewHitTestTypeInternal.Cell; hti.rowStart = yRowTopEdge; hti.colStart = xColumnLeftEdge; if (!this.ColumnHeadersVisible) { int columnWidth = this.Columns[hti.col].Thickness; if ((!this.RightToLeftInternal && xColumnLeftEdge + columnWidth - x < DATAGRIDVIEW_columnSizingHotZone) || (this.RightToLeftInternal && x - xColumnLeftEdge + columnWidth < DATAGRIDVIEW_columnSizingHotZone)) { if (this.RightToLeftInternal) { hti.mouseBarOffset = xColumnLeftEdge - columnWidth - x + 1; } else { hti.mouseBarOffset = xColumnLeftEdge + columnWidth - x - 1; } DataGridViewColumn dataGridViewColumn = this.Columns[hti.col]; if (dataGridViewColumn.Resizable == DataGridViewTriState.True && (dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.None || dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)) { hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnResizeRight; } return hti; } else if ((!this.RightToLeftInternal && x - xColumnLeftEdge < DATAGRIDVIEW_columnSizingHotZone) || (this.RightToLeftInternal && xColumnLeftEdge - x < DATAGRIDVIEW_columnSizingHotZone)) { DataGridViewColumn dataGridViewColumn = null; if (hti.col != this.displayedBandsInfo.FirstDisplayedScrollingCol || this.displayedBandsInfo.LastTotallyDisplayedScrollingCol >= 0) { dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[hti.col], DataGridViewElementStates.Visible, DataGridViewElementStates.None); } if (dataGridViewColumn != null) { hti.adjacentCol = dataGridViewColumn.Index; if (this.RightToLeftInternal) { hti.mouseBarOffset = xColumnLeftEdge - x + 1; } else { hti.mouseBarOffset = xColumnLeftEdge - x - 1; } if (dataGridViewColumn.Resizable == DataGridViewTriState.True && (dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.None || dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill)) { hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnResizeLeft; } return hti; } else { if (this.RowHeadersVisible && this.RowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing) { hti.typeInternal = DataGridViewHitTestTypeInternal.RowHeadersResizeLeft; if (this.RightToLeftInternal) { hti.mouseBarOffset = xColumnLeftEdge - x; } else { hti.mouseBarOffset = xColumnLeftEdge - x - 1; } return hti; } } } } else if ((!this.RightToLeftInternal && x - xColumnLeftEdge < DATAGRIDVIEW_columnSizingHotZone) || (this.RightToLeftInternal && xColumnLeftEdge - x < DATAGRIDVIEW_columnSizingHotZone)) { DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); Debug.Assert(dataGridViewColumn != null); if (hti.col == dataGridViewColumn.Index && this.RowHeadersVisible && this.RowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing) { hti.typeInternal = DataGridViewHitTestTypeInternal.RowHeadersResizeLeft; if (this.RightToLeftInternal) { hti.mouseBarOffset = xColumnLeftEdge - x; } else { hti.mouseBarOffset = xColumnLeftEdge - x - 1; } return hti; } } if (!this.RowHeadersVisible) { int rowHeight = this.Rows.SharedRow(hti.row).GetHeight(hti.row); if (yRowTopEdge + rowHeight - y < DATAGRIDVIEW_rowSizingHotZone) { if (RowIsResizable(hti.row) && this.AutoSizeRowsMode == DataGridViewAutoSizeRowsMode.None) { hti.typeInternal = DataGridViewHitTestTypeInternal.RowResizeBottom; hti.mouseBarOffset = yRowTopEdge + rowHeight - y - 1; } } else if (y - yRowTopEdge < DATAGRIDVIEW_rowSizingHotZone) { int indexTmp = -1; if (hti.row != this.displayedBandsInfo.FirstDisplayedScrollingRow || this.displayedBandsInfo.NumDisplayedFrozenRows > 0) { indexTmp = this.Rows.GetPreviousRow(hti.row, DataGridViewElementStates.Visible); } if (indexTmp != -1) { if (RowIsResizable(indexTmp) && this.AutoSizeRowsMode == DataGridViewAutoSizeRowsMode.None) { hti.typeInternal = DataGridViewHitTestTypeInternal.RowResizeTop; hti.adjacentRow = indexTmp; hti.mouseBarOffset = yRowTopEdge - y - 1; } } else { if (this.ColumnHeadersVisible && this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.EnableResizing) { hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnHeadersResizeTop; hti.mouseBarOffset = yRowTopEdge - y - 1; } } } } else if (y - yRowTopEdge < DATAGRIDVIEW_rowSizingHotZone) { int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); Debug.Assert(rowIndex >= 0); if (hti.row == rowIndex && this.ColumnHeadersVisible && this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.EnableResizing) { hti.typeInternal = DataGridViewHitTestTypeInternal.ColumnHeadersResizeTop; hti.mouseBarOffset = yRowTopEdge - y - 1; } } } return hti; } private void HorizScrollTimer_Tick(object sender, System.EventArgs e) { BeginInvoke(new MethodInvoker(HorizScrollTimerHandler)); } private void HorizScrollTimerHandler() { Debug.Assert(this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] || this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect]); Point ptMouse = PointToClient(Control.MousePosition); HitTestInfo hti = HitTest(ptMouse.X, ptMouse.Y); int xOffset, yOffset, mouseX = ptMouse.X, mouseY = ptMouse.Y; if (GetOutOfBoundCorrectedHitTestInfo(ref hti, ref mouseX, ref mouseY, out xOffset, out yOffset)) { if (xOffset != 0) { int absXOffset = Math.Abs(xOffset), normOffset = xOffset / absXOffset; ScrollColumns(normOffset); this.horizScrollTimer.Interval = GetColumnScrollRate(absXOffset); if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect]) { hti = HitTest(ptMouse.X+(this.RightToLeftInternal?1:-1)*(xOffset+normOffset), mouseY); if (hti.col >= 0) { OnColumnSelectMouseMove(hti); } } else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect]) { if (yOffset != 0) { hti = HitTest(ptMouse.X+(this.RightToLeftInternal?1:-1)*(xOffset+normOffset), ptMouse.Y-yOffset-(yOffset/Math.Abs(yOffset))); } else { hti = HitTest(ptMouse.X+(this.RightToLeftInternal?1:-1)*(xOffset+normOffset), mouseY); } if (hti.col >= 0 && hti.row >= 0) { OnCellSelectMouseMove(hti); } } } else { if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] && hti.col >= 0) { OnColumnSelectMouseMove(hti); } else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect] && hti.col >= 0 && hti.row >= 0) { OnCellSelectMouseMove(hti); } this.HorizScrollTimer.Enabled = false; } } } // Returns true for success, returns false when the OnDataError event cancels the operation. private bool InitializeEditingCellValue(ref DataGridViewCellStyle dataGridViewCellStyle, ref DataGridViewCell dataGridViewCell) { DataGridViewDataErrorEventArgs dgvdee = null; // Save unedited value so we can restore it later if parsing of new value fails this.uneditedFormattedValue = dataGridViewCell.GetFormattedValue(this.ptCurrentCell.Y, ref dataGridViewCellStyle, DataGridViewDataErrorContexts.Formatting); this.dataGridViewState1[DATAGRIDVIEWSTATE1_ignoringEditingChanges] = true; try { IDataGridViewEditingCell dataGridViewEditingCell = dataGridViewCell as IDataGridViewEditingCell; Debug.Assert(dataGridViewEditingCell != null); object currentFormattedValue = dataGridViewEditingCell.GetEditingCellFormattedValue(DataGridViewDataErrorContexts.Formatting); if ((currentFormattedValue == null && this.uneditedFormattedValue != null) || (currentFormattedValue != null && this.uneditedFormattedValue == null) || (currentFormattedValue != null && !this.uneditedFormattedValue.Equals(currentFormattedValue))) { Debug.Assert(this.ptCurrentCell.X == dataGridViewCell.ColumnIndex); dataGridViewCell = this.Rows[this.ptCurrentCell.Y].Cells[this.ptCurrentCell.X]; // unshare the edited cell dataGridViewEditingCell = dataGridViewCell as IDataGridViewEditingCell; dataGridViewEditingCell.EditingCellFormattedValue = this.uneditedFormattedValue; dataGridViewEditingCell.EditingCellValueChanged = false; } } catch (Exception exception) { if (ClientUtils.IsCriticalException(exception)) { throw; } dgvdee = new DataGridViewDataErrorEventArgs(exception, this.ptCurrentCell.X, this.ptCurrentCell.Y, DataGridViewDataErrorContexts.InitialValueRestoration); OnDataErrorInternal(dgvdee); } finally { this.dataGridViewState1[DATAGRIDVIEWSTATE1_ignoringEditingChanges] = false; } if (dgvdee != null) { if (dgvdee.ThrowException) { throw dgvdee.Exception; } return !dgvdee.Cancel; } return true; } // Returns true for success, returns false when the OnDataError event cancels the operation. private bool InitializeEditingControlValue(ref DataGridViewCellStyle dataGridViewCellStyle, DataGridViewCell dataGridViewCell) { Debug.Assert(dataGridViewCell != null); Debug.Assert(this.editingControl != null); DataGridViewDataErrorEventArgs dgvdee = null; object initialFormattedValue = dataGridViewCell.GetFormattedValue(this.ptCurrentCell.Y, ref dataGridViewCellStyle, DataGridViewDataErrorContexts.Formatting); this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlChanging] = true; this.dataGridViewState1[DATAGRIDVIEWSTATE1_ignoringEditingChanges] = true; try { dataGridViewCell.InitializeEditingControl(this.ptCurrentCell.Y, initialFormattedValue, dataGridViewCellStyle); ((IDataGridViewEditingControl)this.editingControl).EditingControlValueChanged = false; } catch (Exception exception) { if (ClientUtils.IsCriticalException(exception)) { throw; } dgvdee = new DataGridViewDataErrorEventArgs(exception, this.ptCurrentCell.X, this.ptCurrentCell.Y, DataGridViewDataErrorContexts.InitialValueRestoration); OnDataErrorInternal(dgvdee); } finally { this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlChanging] = false; this.dataGridViewState1[DATAGRIDVIEWSTATE1_ignoringEditingChanges] = false; } if (dgvdee != null) { if (dgvdee.ThrowException) { throw dgvdee.Exception; } return !dgvdee.Cancel; } // Save unedited value so we can restore it later if parsing of new value fails this.uneditedFormattedValue = initialFormattedValue; return true; } /// public void InvalidateCell(DataGridViewCell dataGridViewCell) { if (dataGridViewCell == null) { throw new ArgumentNullException("dataGridViewCell"); } if (dataGridViewCell.DataGridView != this) { throw new ArgumentException(SR.GetString(SR.DataGridView_CellDoesNotBelongToDataGridView)); } InvalidateCellPrivate(dataGridViewCell); } private void InvalidateCellPrivate(DataGridViewCell dataGridViewCell) { Debug.Assert(dataGridViewCell != null); Debug.Assert(dataGridViewCell.DataGridView == this); InvalidateCell(dataGridViewCell.ColumnIndex, dataGridViewCell.RowIndex); } /// public void InvalidateCell(int columnIndex, int rowIndex) { if (columnIndex < -1 || columnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("columnIndex"); } if (rowIndex < -1 || rowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("rowIndex"); } InvalidateCellPrivate(columnIndex, rowIndex); } private void InvalidateCellPrivate(int columnIndex, int rowIndex) { if (this.IsHandleCreated) { Rectangle cellDisplayRect = GetCellAdjustedDisplayRectangle(columnIndex, rowIndex, true); if (!cellDisplayRect.IsEmpty) { Invalidate(cellDisplayRect); } } } /// /// /// Invalidate the painting region for the column specified. /// public void InvalidateColumn(int columnIndex) { if (columnIndex < 0 || columnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("columnIndex"); } InvalidateColumnInternal(columnIndex); } internal void InvalidateColumnInternal(int columnIndex) { Debug.Assert(columnIndex >= 0 && columnIndex < this.Columns.Count); if (this.IsHandleCreated) { Rectangle columnDisplayRect = GetColumnDisplayRectanglePrivate(columnIndex, true); if (!columnDisplayRect.IsEmpty) { Invalidate(columnDisplayRect); } } } private void InvalidateData() { if (this.IsHandleCreated) { Invalidate(this.layout.Data); } } ////// Invalidates the scrollable area of the DataGridView. /// private void InvalidateInside() { if (this.IsHandleCreated) { Invalidate(this.layout.Inside); } } ////// /// Invalidate the painting region for the row specified. /// public void InvalidateRow(int rowIndex) { if (rowIndex < 0 || rowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("rowIndex"); } InvalidateRowPrivate(rowIndex); } private void InvalidateRowPrivate(int rowIndex) { Debug.Assert(rowIndex >= 0 && rowIndex < this.Rows.Count); if (this.IsHandleCreated) { Rectangle rowDisplayRect = GetRowDisplayRectanglePrivate(rowIndex, true); if (!rowDisplayRect.IsEmpty) { Invalidate(rowDisplayRect); } } } private void InvalidateRowHeights() { this.Rows.InvalidateCachedRowsHeights(); if (this.IsHandleCreated) { PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); Invalidate(); } } private void InvalidateRows(int lo, int hi) { Debug.Assert(lo <= hi); Debug.Assert(lo < this.Rows.Count); Debug.Assert(hi < this.Rows.Count); if (this.Rows.GetRowCount(DataGridViewElementStates.Visible) == 0) { return; } Rectangle rowDisplayRect, data; int top, bottom; data = this.layout.Data; // If "lo" is not visible, then get the next visible row if ((this.Rows.GetRowState(lo) & DataGridViewElementStates.Visible) == 0) { lo = this.Rows.GetNextRow(lo, DataGridViewElementStates.Visible); } if (lo == -1) { // there are no visible rows below "lo" so there is nothing to invalidate. return; } // If "hi" is not visible, then get the previous visible row if ((this.Rows.GetRowState(hi) & DataGridViewElementStates.Visible) == 0) { hi = this.Rows.GetPreviousRow(hi, DataGridViewElementStates.Visible); } Debug.Assert(lo <= hi); Debug.Assert(lo > -1); rowDisplayRect = this.GetRowDisplayRectangle(lo, true /*cutOverflow*/); if (rowDisplayRect.IsEmpty) { // The top row is offscreen if ((this.Rows.GetRowState(lo) & DataGridViewElementStates.Frozen) != 0) { // "lo" is a frozen row which is offscreen. // This means that "lo" and any other row below it are offscreen. return; } else if (this.displayedBandsInfo.NumDisplayedScrollingRows == 0) { // "lo" and all the rows below are scrolling rows but no scrolling rows are displayed. return; } else if (lo >= this.displayedBandsInfo.FirstDisplayedScrollingRow && this.Rows.GetRowCount(DataGridViewElementStates.Visible, this.displayedBandsInfo.FirstDisplayedScrollingRow, lo) >= this.displayedBandsInfo.NumDisplayedScrollingRows) { // "lo" is a scrolling row whose coordinates are below the last visible row. return; } else { // "lo" is a scrolling row "behind" frozen rows. // Start invalidating at the top of the first displayed scrolling row. top = this.GetRowDisplayRectangle(this.displayedBandsInfo.FirstDisplayedScrollingRow, true /*cutOverflow*/).Top; } } else { top = rowDisplayRect.Top; } rowDisplayRect = this.GetRowDisplayRectangle(hi, true /*cutOverflow*/); if (rowDisplayRect.IsEmpty) { // The bottom row is offscreen. if ((this.Rows.GetRowState(hi) & DataGridViewElementStates.Frozen) == DataGridViewElementStates.Frozen) { // "hi" is a frozen row offscreen and "lo" is a frozen row on screen. // Invalidate all the way to the bottom bottom = data.Bottom; } else if (hi > this.displayedBandsInfo.FirstDisplayedScrollingRow) { // "hi" is a scrolling row offscreen which is beyond the firstDisplayedScrollingRow // Invalidate all the way to the bottom again. bottom = data.Bottom; } else if (this.Rows.GetRowCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen) == 0) { // "hi" is a scrolling row above the first displayed scrolling row and there are no frozen rows. // There is nothing to invalidate. return; } else { // "hi" is a scrolling row which is "behind" the frozen rows. // Invalidate all the way to the bottom of the frozen rows // Compute the bottom of the last displayed frozen row. // There may be invisible rows between the frozen rows. bottom = 0; for (int i = 0; i < this.displayedBandsInfo.NumDisplayedFrozenRows;) { if ((this.Rows.GetRowState(i) & DataGridViewElementStates.Visible) == 0) { continue; } if (i == this.displayedBandsInfo.NumDisplayedFrozenRows - 1) { bottom = this.GetRowDisplayRectangle(i, true /*cutOverflow*/).Bottom; break; } i ++; } if (bottom <= top) { // In this case both "lo" and "hi" are two scrolling rows behind the frozen rows. // Nothing to invalidate. return; } } } else { bottom = rowDisplayRect.Bottom; } Invalidate(new Rectangle(data.X, top, data.Width, bottom - top)); } private void InvalidateScrollBars() { // invalidate the horizontal and the vertical scrollbars // note that the scrollbars can be null - this happens when // the control has been disposed. if (this.horizScrollBar != null && this.horizScrollBar.Visible) { this.horizScrollBar.Invalidate(); } if (this.vertScrollBar != null && this.vertScrollBar.Visible) { this.vertScrollBar.Invalidate(); } } private bool IsColumnOutOfBounds(int columnIndex) { return columnIndex >= this.Columns.Count || columnIndex == -1; } private bool IsInnerCellOutOfBounds(int columnIndex, int rowIndex) { return columnIndex >= this.Columns.Count || rowIndex >= this.Rows.Count || columnIndex == -1 || rowIndex == -1; } private bool IsRowOutOfBounds(int rowIndex) { return rowIndex >= this.Rows.Count || rowIndex == -1; } ///protected override bool IsInputChar(char charCode) { if (this.editingControl != null && this.dataGridViewState1[DATAGRIDVIEWSTATE1_forwardCharMessage]) { // Do not process key press in ProcessDialogChar. return true; } else { return base.IsInputChar(charCode); } } /// protected override bool IsInputKey(Keys keyData) { if ((keyData & Keys.Alt) == Keys.Alt) { return false; } switch (keyData & Keys.KeyCode) { case Keys.Escape: { return this.IsEscapeKeyEffective; } case Keys.Tab: { return GetTabKeyEffective((keyData & Keys.Shift) == Keys.Shift, (keyData & Keys.Control) == Keys.Control); } case Keys.A: { if ((keyData & (Keys.Control | Keys.Shift | Keys.Alt)) == Keys.Control) { return true; } break; } case Keys.C: case Keys.Insert: { if ((keyData & (Keys.Control | Keys.Shift | Keys.Alt)) == Keys.Control) { return true; } break; } case Keys.Space: { if ((keyData & (Keys.Control | Keys.Shift | Keys.Alt)) == Keys.Shift && (this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect || this.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect) && this.ptCurrentCell.X != -1) { return true; } break; } case Keys.Up: case Keys.Down: case Keys.Left: case Keys.Right: case Keys.Home: case Keys.End: case Keys.Next: case Keys.Prior: case Keys.Enter: case Keys.Delete: case Keys.D0: case Keys.NumPad0: case Keys.F2: { return true; } } return base.IsInputKey(keyData); } /// /// Determines if Scrollbars should be visible, /// updates their bounds and the bounds of all /// other regions in the dataGridView's Layout. /// private void LayoutScrollBars() { SuspendLayout(); try { // Scrollbars are a tricky issue. // We need to see if we can cram our columns and rows // in without scrollbars and if they don't fit, we make // scrollbars visible and then fixup our regions for the // data. bool allowHorizScrollbar = ((this.scrollBars == ScrollBars.Both) || (this.scrollBars == ScrollBars.Horizontal)) && this.dataGridViewState2[DATAGRIDVIEWSTATE2_allowHorizontalScrollbar]; bool allowVertScrollbar = (this.scrollBars == ScrollBars.Both) || (this.scrollBars == ScrollBars.Vertical); bool needHorizScrollbarWithoutVertScrollbar = false; bool needHorizScrollbar = false; bool needVertScrollbar = false; bool rightToLeftInternal = this.RightToLeftInternal; int oldfirstDisplayedScrollingRow; int totalVisibleColCount = this.Columns.GetColumnCount(DataGridViewElementStates.Visible); int totalVisibleRowCount = this.Rows.GetRowCount(DataGridViewElementStates.Visible); int totalVisibleWidth = this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible); int totalVisibleFrozenWidth = this.Columns.GetColumnsWidth(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); // Expensive call - dataGridView could have a mode where no row is resizable which would result in better perfs int totalVisibleHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible); int totalVisibleFrozenHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); int horizScrollBarHeight = this.horizScrollBar.Height = SystemInformation.HorizontalScrollBarHeight; int vertScrollBarWidth = this.vertScrollBar.Width = SystemInformation.VerticalScrollBarWidth; if (allowHorizScrollbar && totalVisibleWidth > this.layout.Data.Width && totalVisibleFrozenWidth < this.layout.Data.Width && horizScrollBarHeight <= this.layout.Data.Height) { int oldDataHeight = this.layout.Data.Height; this.layout.Data.Height -= horizScrollBarHeight; Debug.Assert(this.layout.Data.Height >= 0); needHorizScrollbarWithoutVertScrollbar = needHorizScrollbar = true; if (totalVisibleWidth - this.layout.Data.Width <= vertScrollBarWidth || this.layout.Data.Width - totalVisibleFrozenWidth <= vertScrollBarWidth) { // Would we still need a horizontal scrollbar if there were a vertical one? oldfirstDisplayedScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow; ComputeVisibleRows(); if (this.displayedBandsInfo.NumTotallyDisplayedFrozenRows == this.Rows.GetRowCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen) && this.displayedBandsInfo.NumTotallyDisplayedScrollingRows != totalVisibleRowCount - this.Rows.GetRowCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen) && (totalVisibleHeight - totalVisibleFrozenHeight != ComputeHeightOfFittingTrailingScrollingRows(totalVisibleFrozenHeight))) { needHorizScrollbar = (totalVisibleFrozenWidth < this.layout.Data.Width - vertScrollBarWidth); } this.displayedBandsInfo.FirstDisplayedScrollingRow = oldfirstDisplayedScrollingRow; } if (needHorizScrollbar) { if (this.layout.RowHeadersVisible) { this.layout.RowHeaders.Height -= horizScrollBarHeight; Debug.Assert(this.layout.RowHeaders.Height >= 0); } } else { // Restore old data height because turns out a horizontal scroll bar wouldn't make sense this.layout.Data.Height = oldDataHeight; } } oldfirstDisplayedScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow; ComputeVisibleRows(); if (allowVertScrollbar && this.displayedBandsInfo.NumTotallyDisplayedFrozenRows == this.Rows.GetRowCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen) && this.displayedBandsInfo.NumTotallyDisplayedScrollingRows != totalVisibleRowCount - this.Rows.GetRowCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen) && (totalVisibleHeight - totalVisibleFrozenHeight != ComputeHeightOfFittingTrailingScrollingRows(totalVisibleFrozenHeight)) && this.layout.Data.Height > totalVisibleFrozenHeight && vertScrollBarWidth <= this.layout.Data.Width) { this.layout.Data.Width -= vertScrollBarWidth; Debug.Assert(this.layout.Data.Width >= 0); if (rightToLeftInternal) { this.layout.Data.X += vertScrollBarWidth; } if (this.layout.ColumnHeadersVisible) { this.layout.ColumnHeaders.Width -= vertScrollBarWidth; Debug.Assert(this.layout.ColumnHeaders.Width >= 0); if (rightToLeftInternal) { this.layout.ColumnHeaders.X += vertScrollBarWidth; } } needVertScrollbar = true; } this.displayedBandsInfo.FirstDisplayedScrollingCol = ComputeFirstVisibleScrollingColumn(); // we compute the number of visible columns only after we set up the vertical scroll bar. ComputeVisibleColumns(); if (allowHorizScrollbar && needVertScrollbar && !needHorizScrollbar && totalVisibleWidth > this.layout.Data.Width && totalVisibleFrozenWidth < this.layout.Data.Width && horizScrollBarHeight <= this.layout.Data.Height) { this.displayedBandsInfo.FirstDisplayedScrollingRow = oldfirstDisplayedScrollingRow; if (this.layout.ColumnHeadersVisible) { this.layout.ColumnHeaders.Width += vertScrollBarWidth; if (rightToLeftInternal) { this.layout.ColumnHeaders.X -= vertScrollBarWidth; } } this.layout.Data.Width += vertScrollBarWidth; if (rightToLeftInternal) { this.layout.Data.X -= vertScrollBarWidth; } this.layout.Data.Height -= horizScrollBarHeight; Debug.Assert(this.layout.Data.Height >= 0); needVertScrollbar = false; ComputeVisibleRows(); if (this.displayedBandsInfo.NumTotallyDisplayedFrozenRows == this.Rows.GetRowCount(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen) && this.displayedBandsInfo.NumTotallyDisplayedScrollingRows != totalVisibleRowCount && (totalVisibleHeight - totalVisibleFrozenHeight != ComputeHeightOfFittingTrailingScrollingRows(totalVisibleFrozenHeight)) && this.layout.Data.Height > totalVisibleFrozenHeight && vertScrollBarWidth <= this.layout.Data.Width) { this.layout.Data.Width -= vertScrollBarWidth; Debug.Assert(this.layout.Data.Width >= 0); if (rightToLeftInternal) { this.layout.Data.X += vertScrollBarWidth; } if (this.layout.ColumnHeadersVisible) { this.layout.ColumnHeaders.Width -= vertScrollBarWidth; Debug.Assert(this.layout.ColumnHeaders.Width >= 0); if (rightToLeftInternal) { this.layout.ColumnHeaders.X += vertScrollBarWidth; } } needVertScrollbar = true; } if (needVertScrollbar) { needHorizScrollbar = true; } else { needHorizScrollbar = needHorizScrollbarWithoutVertScrollbar; } } this.layout.ResizeBoxRect = new Rectangle(); if (needVertScrollbar && needHorizScrollbar) { this.layout.ResizeBoxRect = new Rectangle( rightToLeftInternal ? this.layout.Data.X - this.vertScrollBar.Width : this.layout.Data.Right, this.layout.Data.Bottom, this.vertScrollBar.Width, this.horizScrollBar.Height); } if (needHorizScrollbar && totalVisibleColCount > 0) { int widthNotVisible = totalVisibleWidth - this.layout.Data.Width; this.horizScrollBar.Minimum = 0; this.horizScrollBar.Maximum = totalVisibleWidth - totalVisibleFrozenWidth; Debug.Assert(this.horizScrollBar.Maximum > 0); this.horizScrollBar.SmallChange = 1; this.horizScrollBar.LargeChange = Math.Max(totalVisibleWidth - totalVisibleFrozenWidth - widthNotVisible, 0); this.horizScrollBar.Enabled = this.Enabled; this.horizScrollBar.Bounds = new Rectangle( rightToLeftInternal ? this.layout.Inside.X + this.layout.ResizeBoxRect.Width : this.layout.Inside.X, this.layout.Data.Bottom, this.layout.Inside.Width - this.layout.ResizeBoxRect.Width, this.horizScrollBar.Height); this.horizScrollBar.Visible = true; this.horizScrollBar.Invalidate(); } else { this.horizScrollBar.Visible = false; this.HorizontalOffset = 0; this.horizScrollBar.Enabled = false; this.horizScrollBar.Minimum = 0; this.horizScrollBar.Maximum = 1; this.horizScrollBar.SmallChange = 1; this.horizScrollBar.LargeChange = 1; this.horizScrollBar.Value = 0; } if (needVertScrollbar) { int vertScrollBarTop = this.layout.Data.Y; int vertScrollBarHeight = this.layout.Data.Height; if (this.layout.ColumnHeadersVisible) { vertScrollBarTop = this.layout.ColumnHeaders.Y; vertScrollBarHeight += this.layout.ColumnHeaders.Height; } else if (this.SingleHorizontalBorderAdded) { vertScrollBarTop--; vertScrollBarHeight++; } this.vertScrollBar.Minimum = 0; this.vertScrollBar.Maximum = totalVisibleHeight - totalVisibleFrozenHeight; Debug.Assert(this.vertScrollBar.Maximum > 0); this.vertScrollBar.Value = ComputeHeightOfScrolledOffRows(); this.vertScrollBar.LargeChange = this.layout.Data.Height - totalVisibleFrozenHeight; this.vertScrollBar.Bounds = new Rectangle( rightToLeftInternal ? this.layout.Data.X - this.vertScrollBar.Width : this.layout.Data.Right, vertScrollBarTop, this.vertScrollBar.Width, vertScrollBarHeight); this.vertScrollBar.Enabled = this.Enabled; this.vertScrollBar.Visible = true; this.vertScrollBar.Invalidate(); this.verticalOffset = this.vertScrollBar.Value; } else { this.vertScrollBar.Visible = false; this.verticalOffset = ComputeHeightOfScrolledOffRows(); this.vertScrollBar.Enabled = false; this.vertScrollBar.Minimum = 0; this.vertScrollBar.Maximum = 1; this.vertScrollBar.LargeChange = 1; this.vertScrollBar.Value = 0; } } finally { ResumeLayout(false); } } private void MakeFirstDisplayedCellCurrentCell(bool includeNewRow) { // No current cell - try to set the first displayed cell to be the current one. Point firstDisplayedCellAddress = this.FirstDisplayedCellAddress; if (firstDisplayedCellAddress.X != -1 && (includeNewRow || !this.AllowUserToAddRowsInternal || firstDisplayedCellAddress.Y != this.Rows.Count - 1)) { bool success = SetAndSelectCurrentCellAddress(firstDisplayedCellAddress.X, firstDisplayedCellAddress.Y, true /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false /*throughMouseClick*/, true /*clearSelection*/, false /*forceCurrentCellSelection (unused)*/); Debug.Assert(success); } } private static DataGridViewAutoSizeRowMode MapAutoSizeRowsModeToRowMode(DataGridViewAutoSizeRowsMode autoSizeRowsMode) { switch (autoSizeRowsMode) { case DataGridViewAutoSizeRowsMode.AllHeaders: return DataGridViewAutoSizeRowMode.RowHeader; case DataGridViewAutoSizeRowsMode.DisplayedHeaders: return DataGridViewAutoSizeRowMode.RowHeader; case DataGridViewAutoSizeRowsMode.AllCellsExceptHeaders: return DataGridViewAutoSizeRowMode.AllCellsExceptHeader; case DataGridViewAutoSizeRowsMode.DisplayedCellsExceptHeaders: return DataGridViewAutoSizeRowMode.AllCellsExceptHeader; case DataGridViewAutoSizeRowsMode.AllCells: return DataGridViewAutoSizeRowMode.AllCells; case DataGridViewAutoSizeRowsMode.DisplayedCells: return DataGridViewAutoSizeRowMode.AllCells; default: Debug.Fail("Unexpected autoSizeRowsMode value in MapAutoSizeRowsModeToRowMode"); return DataGridViewAutoSizeRowMode.RowHeader; } } private void MoveColumnHeadersOrRowResize(MouseEventArgs e) { this.lastRowSplitBar = this.currentRowSplitBar; this.currentRowSplitBar = e.Y; Rectangle lastSplitBarRect = CalcRowResizeFeedbackRect(this.lastRowSplitBar); if (this.editingControl != null && !this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlHidden] && this.editingPanel.Bounds.IntersectsWith(lastSplitBarRect)) { this.editingPanel.Invalidate(); this.editingPanel.Update(); this.editingControl.Invalidate(); this.editingControl.Update(); } Invalidate(lastSplitBarRect); Invalidate(CalcRowResizeFeedbackRect(this.currentRowSplitBar)); } private void MapDataGridViewColumnToDataBoundField(DataGridViewColumn dataGridViewColumn) { Debug.Assert(this.DataSource != null, "this method should only be called when we have a data connection"); Debug.Assert(dataGridViewColumn.DataPropertyName.Length != 0, "this method should be called only for columns which have DataPropertyName set"); DataGridViewDataConnection conn = this.DataConnection; int boundColumnIndex = ((conn == null) ? -1 : conn.BoundColumnIndex(dataGridViewColumn.DataPropertyName)); if (boundColumnIndex != -1) { dataGridViewColumn.IsDataBoundInternal = true; dataGridViewColumn.BoundColumnIndex = boundColumnIndex; dataGridViewColumn.BoundColumnConverter = conn.BoundColumnConverter(boundColumnIndex); dataGridViewColumn.ValueType = conn.BoundColumnValueType(boundColumnIndex); dataGridViewColumn.ReadOnly = conn.DataFieldIsReadOnly(dataGridViewColumn.BoundColumnIndex) || dataGridViewColumn.ReadOnly; InvalidateColumnInternal(dataGridViewColumn.Index); // Set the Sorting information on the data grid view according to the new DataPropertyName. // RefreshColumns() has its own routine for setting the Sorting information so don't do this step // if we are in RefreshColumns(); if (dataGridViewColumn.SortMode != DataGridViewColumnSortMode.NotSortable && !this.dataGridViewOper[DATAGRIDVIEWOPER_inRefreshColumns]) { dataGridViewColumn.HeaderCell.SortGlyphDirection = conn.BoundColumnSortOrder(boundColumnIndex); if (this.sortedColumn == null && dataGridViewColumn.HeaderCell.SortGlyphDirection != SortOrder.None) { this.sortedColumn = dataGridViewColumn; this.sortOrder = dataGridViewColumn.HeaderCell.SortGlyphDirection; // no need to sort because the back end is already sorted.... } } } else { dataGridViewColumn.IsDataBoundInternal = false; dataGridViewColumn.BoundColumnIndex = -1; dataGridViewColumn.BoundColumnConverter = null; InvalidateColumnInternal(dataGridViewColumn.Index); } } private void MoveColumnRelocation(MouseEventArgs e, HitTestInfo hti) { this.lastHeaderShadow = e.X; this.dataGridViewState2[DATAGRIDVIEWSTATE2_showColumnRelocationInsertion] = ColumnRelocationTarget(e, hti, out this.trackColumnEdge); Invalidate(Rectangle.Union(this.layout.TopLeftHeader, this.layout.ColumnHeaders)); } private void MoveRowHeadersOrColumnResize(MouseEventArgs e) { this.lastColSplitBar = this.currentColSplitBar; this.currentColSplitBar = e.X; Rectangle lastSplitBarRect = CalcColResizeFeedbackRect(this.lastColSplitBar); if (this.editingControl != null && !this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlHidden] && this.editingPanel.Bounds.IntersectsWith(lastSplitBarRect)) { this.editingPanel.Invalidate(); this.editingPanel.Update(); this.editingControl.Invalidate(); this.editingControl.Update(); } Invalidate(lastSplitBarRect); Invalidate(CalcColResizeFeedbackRect(this.currentColSplitBar)); } ///public virtual void NotifyCurrentCellDirty(bool dirty) { Debug.Assert(this.ptCurrentCell.X >= 0 && this.ptCurrentCell.X < this.Columns.Count); Debug.Assert(this.ptCurrentCell.Y >= 0 && this.ptCurrentCell.Y < this.Rows.Count); if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_ignoringEditingChanges] == false) { // autosizing has no effect since edited value hasn't been committed // and autosizing code only looks at committed values. this.IsCurrentCellDirtyInternal = dirty; if (dirty && this.editingControl != null && ((IDataGridViewEditingControl) this.editingControl).RepositionEditingControlOnValueChange) { PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/); } } } internal void OnAddedColumn(DataGridViewColumn dataGridViewColumn) { Debug.Assert(dataGridViewColumn.Index >= 0); Debug.Assert(dataGridViewColumn.Index < this.Columns.Count); Debug.Assert(dataGridViewColumn.DataGridView == this); if (dataGridViewColumn.DisplayIndex == -1 || dataGridViewColumn.DisplayIndex >= this.Columns.Count) { // Developer did not assign a DisplayIndex or picked a large number. // Choose the Index as the DisplayIndex. dataGridViewColumn.DisplayIndexInternal = dataGridViewColumn.Index; this.Columns.InvalidateCachedColumnsOrder(); } CorrectColumnDisplayIndexesAfterInsertion(dataGridViewColumn); if (dataGridViewColumn.HasHeaderCell) { dataGridViewColumn.HeaderCell.DataGridViewInternal = this; } AdjustExpandingRows(dataGridViewColumn.Index, false /*fixedWidth*/); DataGridViewAutoSizeColumnMode autoSizeColumnMode = dataGridViewColumn.InheritedAutoSizeMode; Debug.Assert(autoSizeColumnMode != DataGridViewAutoSizeColumnMode.NotSet); bool fixedColumnWidth = autoSizeColumnMode == DataGridViewAutoSizeColumnMode.None || autoSizeColumnMode == DataGridViewAutoSizeColumnMode.Fill; if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) { AutoResizeColumnHeadersHeight(dataGridViewColumn.Index, true /*fixedRowHeadersWidth*/, fixedColumnWidth); } if (!fixedColumnWidth) { // This is the first time the column autosizes. Save current column width for later reuse. dataGridViewColumn.CachedThickness = dataGridViewColumn.Thickness; AutoResizeColumnInternal(dataGridViewColumn.Index, (DataGridViewAutoSizeColumnCriteriaInternal)autoSizeColumnMode, true /*fixedHeight*/); if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) { // Second round of column headers autosizing AutoResizeColumnHeadersHeight(dataGridViewColumn.Index, true /*fixedRowHeadersWidth*/, true /*fixedColumnWidth*/); } } // Raise the ColumnAdded event OnColumnAdded(new DataGridViewColumnEventArgs(dataGridViewColumn)); } internal void OnAddedRow_PreNotification(int rowIndex) { Debug.Assert(rowIndex >= 0); if (this.AllowUserToAddRowsInternal && this.newRowIndex == -1) { // The added row is necessarily the 'new row' // Set the this.newRowIndex variable as early as possible. Debug.Assert(rowIndex == this.Rows.Count - 1); this.newRowIndex = rowIndex; } DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex); #if DEBUG DataGridViewRow dataGridViewRowDebug = this.Rows.SharedRow(rowIndex); foreach (DataGridViewCell dataGridViewCell in dataGridViewRowDebug.Cells) { Debug.Assert(!dataGridViewCell.Selected); Debug.Assert(dataGridViewRowDebug.Index != -1 || !dataGridViewCell.HasValue); } #endif // Update this.individualReadOnlyCells if ((rowState & DataGridViewElementStates.ReadOnly) == 0 && !this.ReadOnly) { DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex); foreach (DataGridViewCell dataGridViewCell in dataGridViewRow.Cells) { if (!dataGridViewCell.OwningColumn.ReadOnly && IsSharedCellReadOnly(dataGridViewCell, rowIndex)) { this.individualReadOnlyCells.Add(dataGridViewCell); } } } } internal void OnAddedRow_PostNotification(int rowIndex) { Debug.Assert(rowIndex >= 0); DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex); if ((rowState & DataGridViewElementStates.Visible) != 0) { bool rowDisplayed = (rowState & DataGridViewElementStates.Displayed) != 0; DataGridViewAutoSizeRowsModeInternal autoSizeRowsModeInternal = (DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode; bool autoSizeRow = false; // Auto size row if needed if (autoSizeRowsModeInternal != DataGridViewAutoSizeRowsModeInternal.None && !((autoSizeRowsModeInternal & DataGridViewAutoSizeRowsModeInternal.DisplayedRows) != 0 && !rowDisplayed)) { // this call may unshare the row. int rowHeight = this.Rows.SharedRow(rowIndex).GetHeight(rowIndex); this.Rows.SharedRow(rowIndex).CachedThickness = rowHeight; AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), false /*fixedWidth*/, true /*internalAutosizing*/); autoSizeRow = true; } // Auto size columms also if needed DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFilter = DataGridViewAutoSizeColumnCriteriaInternal.AllRows; if (rowDisplayed) { autoSizeColumnCriteriaFilter |= DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows; } bool columnAutoSized; if (this.Rows.GetRowCount(DataGridViewElementStates.Visible) > 1) { // Columns can only expand, and not collapse. columnAutoSized = AdjustExpandingColumns(autoSizeColumnCriteriaFilter, rowIndex); } else { columnAutoSized = AutoResizeAllVisibleColumnsInternal(autoSizeColumnCriteriaFilter, true /*fixedHeight*/); } bool fixedColumnHeadersHeight = this.ColumnHeadersHeightSizeMode != DataGridViewColumnHeadersHeightSizeMode.AutoSize; bool rowHeadersAutoSize = this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.EnableResizing && this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.DisableResizing; if (!rowHeadersAutoSize && !columnAutoSized) { // No need to autosize the column headers when the row headers and columns don't change. fixedColumnHeadersHeight = true; } // Auto size row headers if (rowHeadersAutoSize) { AutoResizeRowHeadersWidth(rowIndex, this.rowHeadersWidthSizeMode, fixedColumnHeadersHeight, true /*fixedRowsHeight*/); } // Auto size column headers if (!fixedColumnHeadersHeight) { AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/); } if (autoSizeRow) { // Second round of row autosizing AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), true /*fixedWidth*/, true /*internalAutosizing*/); } if (rowHeadersAutoSize && !fixedColumnHeadersHeight) { // Second round of row headers autosizing AutoResizeRowHeadersWidth(rowIndex, this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, true /*fixedRowsHeight*/); } } } internal void OnAddedRows_PreNotification(DataGridViewRow[] dataGridViewRows) { // Note: no row can be added that breaks the frozen row packing on the top foreach(DataGridViewRow dataGridViewRow in dataGridViewRows) { OnAddedRow_PreNotification(dataGridViewRow.Index); } } internal void OnAddedRows_PostNotification(DataGridViewRow[] dataGridViewRows) { foreach (DataGridViewRow dataGridViewRow in dataGridViewRows) { OnAddedRow_PostNotification(dataGridViewRow.Index); } } internal void OnAddingColumn(DataGridViewColumn dataGridViewColumn) { // throw an exception if the column to be added breaks the rules if (dataGridViewColumn == null) { throw new ArgumentNullException("dataGridViewColumn"); } if (dataGridViewColumn.DataGridView != null) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_ColumnAlreadyBelongsToDataGridView)); } if (!this.InInitialization && dataGridViewColumn.SortMode == DataGridViewColumnSortMode.Automatic && (this.SelectionMode == DataGridViewSelectionMode.FullColumnSelect || this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect)) { throw new InvalidOperationException(SR.GetString(SR.DataGridViewColumn_SortModeAndSelectionModeClash, DataGridViewColumnSortMode.Automatic.ToString(), this.SelectionMode.ToString())); } if (dataGridViewColumn.Visible) { // Note that dataGridViewColumn.DataGridView is set later on, so dataGridViewColumn.InheritedAutoSizeMode should not be used // Make sure the column does not autosize based only on header while column headers are invisible if (!this.ColumnHeadersVisible && (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.ColumnHeader || (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.NotSet && this.AutoSizeColumnsMode == DataGridViewAutoSizeColumnsMode.ColumnHeader))) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddAutoSizedColumn)); } // Make sure the column is not frozen and auto fills if (dataGridViewColumn.Frozen && (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.Fill || (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.NotSet && this.AutoSizeColumnsMode == DataGridViewAutoSizeColumnsMode.Fill))) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddAutoFillColumn)); } // UsedFillWeight values need to be updated this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = true; } // Make sure the sum of the column weights does not exceed ushort.MaxValue float weightSum = this.Columns.GetColumnsFillWeight(DataGridViewElementStates.None) + dataGridViewColumn.FillWeight; if (weightSum > (float)ushort.MaxValue) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_WeightSumCannotExceedLongMaxValue, (ushort.MaxValue).ToString(CultureInfo.CurrentCulture))); } // check for correctness of frozen state - throws exception if state is incorrect. CorrectColumnFrozenState(dataGridViewColumn, this.Columns.Count); // prepare the existing rows by appending cells of correct type if (this.Rows.Count > 0) { // Only require a default cell type when there are rows to fill if (dataGridViewColumn.CellType == null) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddUntypedColumn)); } if (dataGridViewColumn.CellTemplate.DefaultNewRowValue != null && this.newRowIndex != -1) { // New row needs to be unshared before addition of new cell with a Value != null DataGridViewRow newRow = this.Rows[this.newRowIndex]; } int newColumnCount = this.Columns.Count + 1; try { for (int rowIndex = 0; rowIndex < this.Rows.Count; rowIndex++) { DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex); if (dataGridViewRow.Cells.Count < newColumnCount) { DataGridViewCell dataGridViewCellNew = (DataGridViewCell)dataGridViewColumn.CellTemplate.Clone(); dataGridViewRow.Cells.AddInternal(dataGridViewCellNew); if (rowIndex == this.newRowIndex) { dataGridViewCellNew.SetValueInternal(rowIndex, dataGridViewCellNew.DefaultNewRowValue); } dataGridViewCellNew.DataGridViewInternal = this; dataGridViewCellNew.OwningRowInternal = dataGridViewRow; dataGridViewCellNew.OwningColumnInternal = dataGridViewColumn; } } } catch { for (int rowIndex = 0; rowIndex < this.Rows.Count; rowIndex++) { DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex); if (dataGridViewRow.Cells.Count == newColumnCount) { dataGridViewRow.Cells.RemoveAtInternal(newColumnCount - 1); } else { Debug.Assert(dataGridViewRow.Cells.Count < newColumnCount); break; } } throw; } } } [ SuppressMessage("Microsoft.Performance", "CA1817:DoNotCallPropertiesThatCloneValuesInLoops") // not legitimate ] internal void OnAddingColumns(DataGridViewColumn[] dataGridViewColumns) { // Make sure the sum of the column weights does not exceed ushort.MaxValue float weightSum = this.Columns.GetColumnsFillWeight(DataGridViewElementStates.None); Debug.Assert(weightSum <= (float)ushort.MaxValue); // throw an exception if any of the columns to be added breaks the rules Debug.Assert(dataGridViewColumns != null); foreach (DataGridViewColumn dataGridViewColumn in dataGridViewColumns) { if (dataGridViewColumn == null) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_AtLeastOneColumnIsNull)); } if (dataGridViewColumn.DataGridView != null) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_ColumnAlreadyBelongsToDataGridView)); } // Only require a default cell type when there are rows to fill if (this.Rows.Count > 0 && dataGridViewColumn.CellType == null) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddUntypedColumn)); } if (!this.InInitialization && dataGridViewColumn.SortMode == DataGridViewColumnSortMode.Automatic && (this.SelectionMode == DataGridViewSelectionMode.FullColumnSelect || this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect)) { throw new InvalidOperationException(SR.GetString(SR.DataGridViewColumn_SortModeAndSelectionModeClash, DataGridViewColumnSortMode.Automatic.ToString(), this.SelectionMode.ToString())); } if (dataGridViewColumn.Visible) { // Note that dataGridViewColumn.DataGridView is set later on, so dataGridViewColumn.InheritedAutoSizeMode should not be used // Make sure the column does not autosize based only on header while column headers are invisible if (!this.ColumnHeadersVisible && (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.ColumnHeader || (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.NotSet && this.AutoSizeColumnsMode == DataGridViewAutoSizeColumnsMode.ColumnHeader))) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddAutoSizedColumn)); } // Make sure the column is not frozen and auto fills if (dataGridViewColumn.Frozen && (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.Fill || (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.NotSet && this.AutoSizeColumnsMode == DataGridViewAutoSizeColumnsMode.Fill))) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddAutoFillColumn)); } // UsedFillWeight values need to be updated this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = true; } weightSum += dataGridViewColumn.FillWeight; if (weightSum > (float)ushort.MaxValue) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_WeightSumCannotExceedLongMaxValue, (ushort.MaxValue).ToString(CultureInfo.CurrentCulture))); } } Debug.Assert(weightSum <= (float)ushort.MaxValue); // make sure no two columns are identical int columnCount = dataGridViewColumns.Length; for (int column1 = 0; column1 < columnCount - 1; column1++) { for (int column2 = column1 + 1; column2 < columnCount; column2++) { if (dataGridViewColumns[column1] == dataGridViewColumns[column2]) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddIdenticalColumns)); } } } // check for correctness of frozen states - throws exception if any state is incorrect. CorrectColumnFrozenStates(dataGridViewColumns); // prepare the existing rows by appending cells of correct type if (this.Rows.Count > 0) { foreach (DataGridViewColumn dataGridViewColumn in dataGridViewColumns) { Debug.Assert(dataGridViewColumn.CellType != null); if (dataGridViewColumn.CellTemplate.DefaultNewRowValue != null && this.newRowIndex != -1) { // New row needs to be unshared before addition of new cell with a Value != null DataGridViewRow newRow = this.Rows[this.newRowIndex]; break; } } int previousColumnCount = this.Columns.Count; int addedColumnCount = 0; try { foreach (DataGridViewColumn dataGridViewColumn in dataGridViewColumns) { addedColumnCount++; Debug.Assert(dataGridViewColumn.CellType != null); for (int rowIndex = 0; rowIndex < this.Rows.Count; rowIndex++) { DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex); if (dataGridViewRow.Cells.Count < previousColumnCount + addedColumnCount) { DataGridViewCell dataGridViewCellNew = (DataGridViewCell)dataGridViewColumn.CellTemplate.Clone(); int indexCell = dataGridViewRow.Cells.AddInternal(dataGridViewCellNew); if (rowIndex == this.newRowIndex) { dataGridViewCellNew.Value = dataGridViewCellNew.DefaultNewRowValue; } dataGridViewCellNew.DataGridViewInternal = this; dataGridViewCellNew.OwningRowInternal = dataGridViewRow; dataGridViewCellNew.OwningColumnInternal = dataGridViewColumn; } } } } catch { for (int rowIndex = 0; rowIndex < this.Rows.Count; rowIndex++) { DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex); while (dataGridViewRow.Cells.Count > previousColumnCount) { dataGridViewRow.Cells.RemoveAtInternal(dataGridViewRow.Cells.Count - 1); } } throw; } } } internal void OnAddingRow(DataGridViewRow dataGridViewRow, DataGridViewElementStates rowState, bool checkFrozenState) { // Note dataGridViewRow.DataGridView != null for duplication of shared rows. // throw an exception if the row to be added breaks the rules if (dataGridViewRow == null) { throw new ArgumentNullException("dataGridViewRow"); } // !Do not check for dataGridViewRow.Selected flag. Caller does it instead! // !Do not check for dataGridViewRow.DataGridView != null. Caller does it instead! if (checkFrozenState) { // check for correctness of frozen state - throws exception if state is incorrect. CorrectRowFrozenState(dataGridViewRow, rowState, this.Rows.Count); } if (this.ReadOnly && dataGridViewRow.DataGridView == null && dataGridViewRow.ReadOnly) { // Clear the superfluous flag since the whole dataGridView is read-only dataGridViewRow.ReadOnly = false; } int columnIndex = 0; foreach (DataGridViewColumn dataGridViewColumn in this.Columns) { DataGridViewCell dataGridViewCell = dataGridViewRow.Cells[columnIndex]; if ((this.ReadOnly || dataGridViewColumn.ReadOnly) && dataGridViewCell.StateIncludes(DataGridViewElementStates.ReadOnly)) { // Clear superfluous flag since the whole dataGridView or column is ReadOnly dataGridViewCell.ReadOnlyInternal = false; } columnIndex++; } } internal void OnAddingRows(DataGridViewRow[] dataGridViewRows, bool checkFrozenStates) { // throw an exception if any of the rows to be added breaks the rules Debug.Assert(dataGridViewRows != null); foreach (DataGridViewRow dataGridViewRow in dataGridViewRows) { if (dataGridViewRow == null) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_AtLeastOneRowIsNull)); } if (dataGridViewRow.DataGridView != null) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_RowAlreadyBelongsToDataGridView)); } if (dataGridViewRow.Selected) { throw new InvalidOperationException(SR.GetString(SR.DataGridViewRowCollection_CannotAddOrInsertSelectedRow)); } if (dataGridViewRow.Cells.Count > this.Columns.Count) { throw new InvalidOperationException(SR.GetString(SR.DataGridViewRowCollection_TooManyCells)); } } // make sure no two rows are identical int rowCount = dataGridViewRows.Length; for (int row1 = 0; row1 < rowCount - 1; row1++) { for (int row2 = row1 + 1; row2 < rowCount; row2++) { if (dataGridViewRows[row1] == dataGridViewRows[row2]) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddIdenticalRows)); } } } if (checkFrozenStates) { Debug.Assert(!this.AllowUserToAddRowsInternal); CorrectRowFrozenStates(dataGridViewRows, this.Rows.Count /*rowIndexInserted*/); } foreach (DataGridViewRow dataGridViewRow in dataGridViewRows) { CompleteCellsCollection(dataGridViewRow); OnAddingRow(dataGridViewRow, dataGridViewRow.State, false /*checkFrozenState*/); } } internal void OnAdvancedBorderStyleChanged(DataGridViewAdvancedBorderStyle dgvabs) { if (!this.dataGridViewOper[DATAGRIDVIEWOPER_inBorderStyleChange]) { if (dgvabs == this.advancedCellBorderStyle) { OnCellBorderStyleChanged(EventArgs.Empty); } else if (dgvabs == this.advancedColumnHeadersBorderStyle) { OnColumnHeadersBorderStyleChanged(EventArgs.Empty); } else if (dgvabs == this.advancedRowHeadersBorderStyle) { OnRowHeadersBorderStyleChanged(EventArgs.Empty); } } } /// protected virtual void OnAllowUserToAddRowsChanged(EventArgs e) { PushAllowUserToAddRows(); EventHandler eh = this.Events[EVENT_DATAGRIDVIEWALLOWUSERTOADDROWSCHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnAllowUserToDeleteRowsChanged(EventArgs e) { EventHandler eh = this.Events[EVENT_DATAGRIDVIEWALLOWUSERTODELETEROWSCHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnAllowUserToOrderColumnsChanged(EventArgs e) { EventHandler eh = this.Events[EVENT_DATAGRIDVIEWALLOWUSERTOORDERCOLUMNSCHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnAllowUserToResizeColumnsChanged(EventArgs e) { EventHandler eh = this.Events[EVENT_DATAGRIDVIEWALLOWUSERTORESIZECOLUMNSCHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnAllowUserToResizeRowsChanged(EventArgs e) { EventHandler eh = this.Events[EVENT_DATAGRIDVIEWALLOWUSERTORESIZEROWSCHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnAlternatingRowsDefaultCellStyleChanged(EventArgs e) { DataGridViewCellStyleChangedEventArgs dgvcsce = e as DataGridViewCellStyleChangedEventArgs; if (dgvcsce != null && !dgvcsce.ChangeAffectsPreferredSize) { InvalidateData(); } else { OnRowsGlobalAutoSize(); if (this.editingControl != null) { PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/); } } EventHandler eh = this.Events[EVENT_DATAGRIDVIEWALTERNATINGROWSDEFAULTCELLSTYLECHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnAutoGenerateColumnsChanged(EventArgs e) { if (this.AutoGenerateColumns && this.DataSource != null) { // refresh the list of columns and the rows RefreshColumnsAndRows(); } EventHandler eh = this.Events[EVENT_DATAGRIDVIEWAUTOGENERATECOLUMNSCHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal void OnAutoSizeColumnModeChanged(DataGridViewColumn dataGridViewColumn, DataGridViewAutoSizeColumnMode previousInheritedMode) { Debug.Assert(dataGridViewColumn != null); DataGridViewAutoSizeColumnModeEventArgs dgvascme = new DataGridViewAutoSizeColumnModeEventArgs(dataGridViewColumn, previousInheritedMode); OnAutoSizeColumnModeChanged(dgvascme); } /// protected virtual void OnAutoSizeColumnModeChanged(DataGridViewAutoSizeColumnModeEventArgs e) { DataGridViewColumn dataGridViewColumn = e.Column; if (e.Column == null) { throw new InvalidOperationException(SR.GetString(SR.InvalidNullArgument, "e.Column")); } DataGridViewAutoSizeColumnMode autoSizeColumnMode = dataGridViewColumn.InheritedAutoSizeMode; Debug.Assert(autoSizeColumnMode != DataGridViewAutoSizeColumnMode.NotSet); DataGridViewAutoSizeColumnMode previousInheritedMode = e.PreviousMode; bool previousInheritedModeAutoSized = previousInheritedMode != DataGridViewAutoSizeColumnMode.Fill && previousInheritedMode != DataGridViewAutoSizeColumnMode.None && previousInheritedMode != DataGridViewAutoSizeColumnMode.NotSet; if (autoSizeColumnMode == DataGridViewAutoSizeColumnMode.Fill || previousInheritedMode == DataGridViewAutoSizeColumnMode.Fill) { // UsedFillWeight values need to be updated this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = true; } bool fixedHeight = (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) == 0; if (autoSizeColumnMode != DataGridViewAutoSizeColumnMode.None) { if (autoSizeColumnMode != DataGridViewAutoSizeColumnMode.Fill) { if (!previousInheritedModeAutoSized) { // Save current column width for later reuse dataGridViewColumn.CachedThickness = dataGridViewColumn.Thickness; } AutoResizeColumnInternal(dataGridViewColumn.Index, (DataGridViewAutoSizeColumnCriteriaInternal) autoSizeColumnMode, fixedHeight); } } else if (dataGridViewColumn.Thickness != dataGridViewColumn.CachedThickness && previousInheritedModeAutoSized) { // Restoring cached column width dataGridViewColumn.ThicknessInternal = Math.Max(dataGridViewColumn.MinimumWidth, dataGridViewColumn.CachedThickness); } // Auto fill columns if needed PerformLayoutPrivate(false /*useRowShortcut*/, true /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); // Autosize rows and column headers if needed if (!fixedHeight) { AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) { AutoResizeColumnHeadersHeight(dataGridViewColumn.Index, true /*fixedRowHeadersWidth*/, true /*fixedColumnWidth*/); } // Column gets autosized with 1 degree of freedom this time. if (autoSizeColumnMode != DataGridViewAutoSizeColumnMode.None && autoSizeColumnMode != DataGridViewAutoSizeColumnMode.Fill) { AutoResizeColumnInternal(dataGridViewColumn.Index, (DataGridViewAutoSizeColumnCriteriaInternal)autoSizeColumnMode, true /*fixedHeight*/); } } DataGridViewAutoSizeColumnModeEventHandler eh = this.Events[EVENT_DATAGRIDVIEWAUTOSIZECOLUMNMODECHANGED] as DataGridViewAutoSizeColumnModeEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.PreviousModes is more precise than just e protected virtual void OnAutoSizeColumnsModeChanged(DataGridViewAutoSizeColumnsModeEventArgs e) { DataGridViewAutoSizeColumnMode[] previousModes = e.PreviousModes; if (previousModes == null) { throw new ArgumentNullException("e.PreviousModes"); } if (previousModes.Length != this.Columns.Count) { throw new ArgumentException(SR.GetString(SR.DataGridView_PreviousModesHasWrongLength)); } foreach (DataGridViewColumn dataGridViewColumn in this.Columns) { if (dataGridViewColumn.Visible) { DataGridViewAutoSizeColumnMode autoSizeColumnMode = dataGridViewColumn.InheritedAutoSizeMode; Debug.Assert(autoSizeColumnMode != DataGridViewAutoSizeColumnMode.NotSet); DataGridViewAutoSizeColumnMode previousInheritedMode = previousModes[dataGridViewColumn.Index]; bool previousInheritedModeAutoSized = previousInheritedMode != DataGridViewAutoSizeColumnMode.Fill && previousInheritedMode != DataGridViewAutoSizeColumnMode.None && previousInheritedMode != DataGridViewAutoSizeColumnMode.NotSet; if (autoSizeColumnMode == DataGridViewAutoSizeColumnMode.Fill || previousInheritedMode == DataGridViewAutoSizeColumnMode.Fill) { // UsedFillWeight values need to be updated this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = true; } if (autoSizeColumnMode != DataGridViewAutoSizeColumnMode.None) { if (autoSizeColumnMode != DataGridViewAutoSizeColumnMode.Fill) { if (!previousInheritedModeAutoSized) { // Save current column width for later reuse dataGridViewColumn.CachedThickness = dataGridViewColumn.Thickness; } AutoResizeColumnInternal(dataGridViewColumn.Index, (DataGridViewAutoSizeColumnCriteriaInternal)autoSizeColumnMode, (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) == 0 /*fixedHeight*/); } } else if (dataGridViewColumn.Thickness != dataGridViewColumn.CachedThickness && previousInheritedModeAutoSized) { // Restoring cached column width dataGridViewColumn.ThicknessInternal = Math.Max(dataGridViewColumn.MinimumWidth, dataGridViewColumn.CachedThickness); } } } // Auto fill columns if needed PerformLayoutPrivate(false /*useRowShortcut*/, true /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); // Autosize rows and column headers if needed if ((((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0) { AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) { AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnWidth*/); } // Second pass of column autosizing with 1 degree of freedom foreach (DataGridViewColumn dataGridViewColumn in this.Columns) { DataGridViewAutoSizeColumnMode autoSizeColumnMode = dataGridViewColumn.InheritedAutoSizeMode; Debug.Assert(autoSizeColumnMode != DataGridViewAutoSizeColumnMode.NotSet); if (autoSizeColumnMode != DataGridViewAutoSizeColumnMode.None && autoSizeColumnMode != DataGridViewAutoSizeColumnMode.Fill) { AutoResizeColumnInternal(dataGridViewColumn.Index, (DataGridViewAutoSizeColumnCriteriaInternal)autoSizeColumnMode, true /*fixedHeight*/); } } } DataGridViewAutoSizeColumnsModeEventHandler eh = this.Events[EVENT_DATAGRIDVIEWAUTOSIZECOLUMNSMODECHANGED] as DataGridViewAutoSizeColumnsModeEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnAutoSizeRowsModeChanged(DataGridViewAutoSizeModeEventArgs e) { if (this.autoSizeRowsMode == DataGridViewAutoSizeRowsMode.None) { // restore cached rows thickness RestoreRowsCachedThickness(); } else { if (!e.PreviousModeAutoSized) { // Save the rows thickness for later reuse // Note that only visible rows are affected, contrary to columns in OnAutoSizeColumnsModeChanged where all columns are affected. for (int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); rowIndex != -1; rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible)) { // this call may unshare the row. int rowHeight = this.Rows.SharedRow(rowIndex).GetHeight(rowIndex); this.Rows.SharedRow(rowIndex).CachedThickness = rowHeight; } } AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); } DataGridViewAutoSizeModeEventHandler eh = this.Events[EVENT_DATAGRIDVIEWAUTOSIZEROWSMODECHANGED] as DataGridViewAutoSizeModeEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnBackgroundColorChanged(EventArgs e) { InvalidateInside(); EventHandler eh = this.Events[EVENT_DATAGRIDVIEWBACKGROUNDCOLORCHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal void OnBandContextMenuStripChanged(DataGridViewBand dataGridViewBand) { DataGridViewColumn dataGridViewColumn = dataGridViewBand as DataGridViewColumn; if (dataGridViewColumn != null) { DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn); OnColumnContextMenuStripChanged(dgvce); } else { DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs((DataGridViewRow) dataGridViewBand); OnRowContextMenuStripChanged(dgvre); } } internal void OnBandDefaultCellStyleChanged(DataGridViewBand dataGridViewBand) { DataGridViewColumn dataGridViewColumn = dataGridViewBand as DataGridViewColumn; if (dataGridViewColumn != null) { DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn); OnColumnDefaultCellStyleChanged(dgvce); } else { DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs((DataGridViewRow) dataGridViewBand); OnRowDefaultCellStyleChanged(dgvre); } } internal void OnBandDividerThicknessChanged(DataGridViewBand dataGridViewBand) { DataGridViewColumn dataGridViewColumn = dataGridViewBand as DataGridViewColumn; if (dataGridViewColumn != null) { DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn); OnColumnDividerWidthChanged(dgvce); } else { DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs((DataGridViewRow) dataGridViewBand); OnRowDividerHeightChanged(dgvre); } } internal void OnBandHeaderCellChanged(DataGridViewBand dataGridViewBand) { DataGridViewColumn dataGridViewColumn = dataGridViewBand as DataGridViewColumn; if (dataGridViewColumn != null) { DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn); OnColumnHeaderCellChanged(dgvce); } else { DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs((DataGridViewRow) dataGridViewBand); OnRowHeaderCellChanged(dgvre); } } internal void OnBandMinimumThicknessChanged(DataGridViewBand dataGridViewBand) { DataGridViewColumn dataGridViewColumn = dataGridViewBand as DataGridViewColumn; if (dataGridViewColumn != null) { DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn); OnColumnMinimumWidthChanged(dgvce); } else { DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs((DataGridViewRow) dataGridViewBand); OnRowMinimumHeightChanged(dgvre); } } internal void OnBandThicknessChanged(DataGridViewBand dataGridViewBand) { DataGridViewColumn dataGridViewColumn = dataGridViewBand as DataGridViewColumn; if (dataGridViewColumn != null) { DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn); OnColumnWidthChanged(dgvce); } else { DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs((DataGridViewRow) dataGridViewBand); OnRowHeightChanged(dgvre); } } internal void OnBandThicknessChanging() { if (this.InAdjustFillingColumns) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAlterAutoFillColumnParameter)); } } /// protected override void OnBindingContextChanged(EventArgs e) { if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_inBindingContextChanged]) { return; } this.dataGridViewState2[DATAGRIDVIEWSTATE2_inBindingContextChanged] = true; try { if (this.dataConnection != null) { this.CurrentCell = null; try { this.dataConnection.SetDataConnection(this.DataSource, this.DataMember); } catch (ArgumentException) { if (this.DesignMode) { // This is the minimal fix for vsw 527646. // If the DataMember became invalid at DesignTime then set it to String.Empty, // regenerate the column collection and DO NOT send BindingContextChanged event. this.DataMember = String.Empty; RefreshColumnsAndRows(); return; } else { throw; } } RefreshColumnsAndRows(); base.OnBindingContextChanged(e); if (this.dataConnection.CurrencyManager != null) { OnDataBindingComplete(ListChangedType.Reset); } } else { base.OnBindingContextChanged(e); } } finally { this.dataGridViewState2[DATAGRIDVIEWSTATE2_inBindingContextChanged] = false; } } /// protected virtual void OnBorderStyleChanged(EventArgs e) { EventHandler eh = this.Events[EVENT_DATAGRIDVIEWBORDERSTYLECHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnCancelRowEdit(QuestionEventArgs e) { QuestionEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCANCELROWEDIT] as QuestionEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); CorrectFocus(true /*onlyIfGridHasFocus*/); } } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellBeginEdit(DataGridViewCellCancelEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } DataGridViewCellCancelEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLBEGINEDIT] as DataGridViewCellCancelEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnCellBorderStyleChanged(EventArgs e) { PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); Invalidate(); EventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLBORDERSTYLECHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal void OnCellClickInternal(DataGridViewCellEventArgs e) { OnCellClick(e); } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellClick(DataGridViewCellEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex); Debug.Assert(dataGridViewCell != null); if (e.RowIndex >= 0 && dataGridViewCell.ClickUnsharesRowInternal(e)) { DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex]; GetCellInternal(e.ColumnIndex, e.RowIndex).OnClickInternal(e); } else { dataGridViewCell.OnClickInternal(e); } DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLCLICK] as DataGridViewCellEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal void OnCellCommonChange(int columnIndex, int rowIndex) { if (columnIndex == -1) { // row or topleft header characteristic has changed OnRowHeaderGlobalAutoSize(rowIndex); } else { if (rowIndex == -1) { // column header characteristic has changed OnColumnHeaderGlobalAutoSize(columnIndex); } else { // regular cell characteristic changed InvalidateCellPrivate(columnIndex, rowIndex); bool rowDisplayed = false; if (rowIndex != -1) { rowDisplayed = (this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Displayed) != 0; } DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaInternal = (DataGridViewAutoSizeColumnCriteriaInternal)this.Columns[columnIndex].InheritedAutoSizeMode; bool autoSizeColumn = (autoSizeColumnCriteriaInternal & DataGridViewAutoSizeColumnCriteriaInternal.AllRows) != 0; if (rowDisplayed) { autoSizeColumn |= (autoSizeColumnCriteriaInternal & DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows) != 0; } bool autoSizeRow = (((DataGridViewAutoSizeRowsModeInternal) this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0; if (autoSizeRow) { AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), !autoSizeColumn /*fixedWidth*/, true /*internalAutosizing*/); } if (autoSizeColumn) { AutoResizeColumnInternal(columnIndex, autoSizeColumnCriteriaInternal, true /*fixedHeight*/); if (autoSizeRow) { // Second round of row autosizing with 1 degree of freedom. AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), true /*fixedWidth*/, true /*internalAutosizing*/); } } } } } internal void OnCellContentClickInternal(DataGridViewCellEventArgs e) { OnCellContentClick(e); } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellContentClick(DataGridViewCellEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex); Debug.Assert(dataGridViewCell != null); if (e.RowIndex >= 0 && dataGridViewCell.ContentClickUnsharesRowInternal(e)) { DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex]; GetCellInternal(e.ColumnIndex, e.RowIndex).OnContentClickInternal(e); } else { dataGridViewCell.OnContentClickInternal(e); } DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLCONTENTCLICK] as DataGridViewCellEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal void OnCellContentDoubleClickInternal(DataGridViewCellEventArgs e) { OnCellContentDoubleClick(e); } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellContentDoubleClick(DataGridViewCellEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex); Debug.Assert(dataGridViewCell != null); if (e.RowIndex >= 0 && dataGridViewCell.ContentDoubleClickUnsharesRowInternal(e)) { DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex]; GetCellInternal(e.ColumnIndex, e.RowIndex).OnContentDoubleClickInternal(e); } else { dataGridViewCell.OnContentDoubleClickInternal(e); } DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLCONTENTDOUBLECLICK] as DataGridViewCellEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal void OnCellContextMenuStripChanged(DataGridViewCell dataGridViewCell) { DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(dataGridViewCell); OnCellContextMenuStripChanged(dgvce); } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellContextMenuStripChanged(DataGridViewCellEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLCONTEXTMENUSTRIPCHANGED] as DataGridViewCellEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal ContextMenuStrip OnCellContextMenuStripNeeded(int columnIndex, int rowIndex, ContextMenuStrip contextMenuStrip) { DataGridViewCellContextMenuStripNeededEventArgs dgvccmsne = new DataGridViewCellContextMenuStripNeededEventArgs(columnIndex, rowIndex, contextMenuStrip); OnCellContextMenuStripNeeded(dgvccmsne); return dgvccmsne.ContextMenuStrip; } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellContextMenuStripNeeded(DataGridViewCellContextMenuStripNeededEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } DataGridViewCellContextMenuStripNeededEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLCONTEXTMENUSTRIPNEEDED] as DataGridViewCellContextMenuStripNeededEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellDoubleClick(DataGridViewCellEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex); Debug.Assert(dataGridViewCell != null); if (e.RowIndex >= 0 && dataGridViewCell.DoubleClickUnsharesRowInternal(e)) { DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex]; GetCellInternal(e.ColumnIndex, e.RowIndex).OnDoubleClickInternal(e); } else { dataGridViewCell.OnDoubleClickInternal(e); } DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLDOUBLECLICK] as DataGridViewCellEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellEndEdit(DataGridViewCellEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLENDEDIT] as DataGridViewCellEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal void OnCellEnter(ref DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex) { OnCellEnter(new DataGridViewCellEventArgs(columnIndex, rowIndex)); if (dataGridViewCell != null) { if (IsInnerCellOutOfBounds(columnIndex, rowIndex)) { dataGridViewCell = null; } else { Debug.Assert(rowIndex < this.Rows.Count && columnIndex < this.Columns.Count); dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex]; } } } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellEnter(DataGridViewCellEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } try { this.noDimensionChangeCount++; DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLENTER] as DataGridViewCellEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } finally { this.noDimensionChangeCount--; Debug.Assert(this.noDimensionChangeCount >= 0); } } internal void OnCellErrorTextChanged(DataGridViewCell dataGridViewCell) { Debug.Assert(dataGridViewCell.RowIndex >= -1); Debug.Assert(dataGridViewCell.ColumnIndex >= -1); DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(dataGridViewCell); OnCellErrorTextChanged(dgvce); } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellErrorTextChanged(DataGridViewCellEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } UpdateCellErrorText(e.ColumnIndex, e.RowIndex); DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLERRORTEXTCHANGED] as DataGridViewCellEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal string OnCellErrorTextNeeded(int columnIndex, int rowIndex, string errorText) { Debug.Assert(columnIndex >= 0); Debug.Assert(rowIndex >= 0); DataGridViewCellErrorTextNeededEventArgs dgvcetne = new DataGridViewCellErrorTextNeededEventArgs(columnIndex, rowIndex, errorText); OnCellErrorTextNeeded(dgvcetne); return dgvcetne.ErrorText; } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellErrorTextNeeded(DataGridViewCellErrorTextNeededEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } DataGridViewCellErrorTextNeededEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLERRORTEXTNEEDED] as DataGridViewCellErrorTextNeededEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal DataGridViewCellFormattingEventArgs OnCellFormatting(int columnIndex, int rowIndex, object val, Type formattedValueType, DataGridViewCellStyle cellStyle) { DataGridViewCellFormattingEventArgs dgvcfe = new DataGridViewCellFormattingEventArgs(columnIndex, rowIndex, val, formattedValueType, cellStyle); OnCellFormatting(dgvcfe); return dgvcfe; } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellFormatting(DataGridViewCellFormattingEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } DataGridViewCellFormattingEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLFORMATTING] as DataGridViewCellFormattingEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal void OnCellLeave(ref DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex) { OnCellLeave(new DataGridViewCellEventArgs(columnIndex, rowIndex)); if (dataGridViewCell != null) { if (IsInnerCellOutOfBounds(columnIndex, rowIndex)) { dataGridViewCell = null; } else { Debug.Assert(rowIndex < this.Rows.Count && columnIndex < this.Columns.Count); dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex]; } } } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellLeave(DataGridViewCellEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } try { this.noDimensionChangeCount++; DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLLEAVE] as DataGridViewCellEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } finally { this.noDimensionChangeCount--; Debug.Assert(this.noDimensionChangeCount >= 0); } } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellMouseClick(DataGridViewCellMouseEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex); Debug.Assert(dataGridViewCell != null); if (e.RowIndex >= 0 && dataGridViewCell.MouseClickUnsharesRowInternal(e)) { DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex]; GetCellInternal(e.ColumnIndex, e.RowIndex).OnMouseClickInternal(e); } else { dataGridViewCell.OnMouseClickInternal(e); } this.dataGridViewState2[DATAGRIDVIEWSTATE2_nextMouseUpIsDouble] = false; DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLMOUSECLICK] as DataGridViewCellMouseEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellMouseDoubleClick(DataGridViewCellMouseEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex); Debug.Assert(dataGridViewCell != null); if (e.RowIndex >= 0 && dataGridViewCell.MouseDoubleClickUnsharesRowInternal(e)) { DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex]; GetCellInternal(e.ColumnIndex, e.RowIndex).OnMouseDoubleClickInternal(e); } else { dataGridViewCell.OnMouseDoubleClickInternal(e); } this.dataGridViewState2[DATAGRIDVIEWSTATE2_nextMouseUpIsDouble] = true; DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLMOUSEDOUBLECLICK] as DataGridViewCellMouseEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellMouseDown(DataGridViewCellMouseEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex); Debug.Assert(dataGridViewCell != null); // Only left clicks for now Keys nModifier = ModifierKeys; bool isControlDown = (nModifier & Keys.Control) == Keys.Control && (nModifier & Keys.Alt) == 0; bool isShiftDown = (nModifier & Keys.Shift) == Keys.Shift; bool isAltDown = (nModifier & Keys.Alt) == Keys.Alt; Point ptGridCoord = ConvertCellToGridCoord(e.ColumnIndex, e.RowIndex, e.X, e.Y); HitTestInfo hti = HitTest(ptGridCoord.X, ptGridCoord.Y); if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls] && e.Button == MouseButtons.Left) { Debug.Assert(hti.Type != DataGridViewHitTestType.None && hti.Type != DataGridViewHitTestType.HorizontalScrollBar && hti.Type != DataGridViewHitTestType.VerticalScrollBar); Debug.Assert(this.ptMouseDownCell.X == hti.col); Debug.Assert(this.ptMouseDownCell.Y == hti.row); switch (hti.typeInternal) { // Check for column/row (headers) resize case DataGridViewHitTestTypeInternal.ColumnResizeLeft: case DataGridViewHitTestTypeInternal.ColumnResizeRight: case DataGridViewHitTestTypeInternal.RowResizeBottom: case DataGridViewHitTestTypeInternal.RowResizeTop: case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeLeft: case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeRight: case DataGridViewHitTestTypeInternal.RowHeadersResizeLeft: case DataGridViewHitTestTypeInternal.RowHeadersResizeRight: case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeTop: case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeBottom: case DataGridViewHitTestTypeInternal.ColumnHeadersResizeTop: case DataGridViewHitTestTypeInternal.ColumnHeadersResizeBottom: { this.dataGridViewOper[DATAGRIDVIEWOPER_resizingOperationAboutToStart] = (e.Clicks == 1); break; } } } try { if (e.RowIndex >= 0 && dataGridViewCell.MouseDownUnsharesRowInternal(e)) { DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex]; GetCellInternal(e.ColumnIndex, e.RowIndex).OnMouseDownInternal(e); } else { dataGridViewCell.OnMouseDownInternal(e); } DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLMOUSEDOWN] as DataGridViewCellMouseEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls] && e.Button == MouseButtons.Left) { switch (hti.typeInternal) { // Check column resize case DataGridViewHitTestTypeInternal.ColumnResizeLeft: case DataGridViewHitTestTypeInternal.ColumnResizeRight: { int columnIndex = (hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnResizeRight) ? hti.col : hti.adjacentCol; Debug.Assert(this.Columns[columnIndex].Resizable == DataGridViewTriState.True); if (e.Clicks == 1) { BeginColumnResize(ptGridCoord.X, hti.mouseBarOffset, columnIndex); } break; } // Check row resize case DataGridViewHitTestTypeInternal.RowResizeBottom: case DataGridViewHitTestTypeInternal.RowResizeTop: { int rowIndex = (hti.typeInternal == DataGridViewHitTestTypeInternal.RowResizeBottom) ? hti.row : hti.adjacentRow; if (e.Clicks == 1) { BeginRowResize(ptGridCoord.Y, hti.mouseBarOffset, rowIndex); } break; } // Check for column header mouse down case DataGridViewHitTestTypeInternal.ColumnHeader: case DataGridViewHitTestTypeInternal.ColumnHeaderLeft: case DataGridViewHitTestTypeInternal.ColumnHeaderRight: case DataGridViewHitTestTypeInternal.FirstColumnHeaderLeft: { if (isAltDown && this.AllowUserToOrderColumns && (this.SelectionMode == DataGridViewSelectionMode.FullColumnSelect || this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect)) { BeginColumnRelocation(ptGridCoord.X, hti.col); } else { OnColumnHeaderMouseDown(hti, isShiftDown, isControlDown); } break; } // Check for row header mouse down case DataGridViewHitTestTypeInternal.RowHeader: { OnRowHeaderMouseDown(hti, isShiftDown, isControlDown); break; } // Check for cell mouse down case DataGridViewHitTestTypeInternal.Cell: { OnCellMouseDown(hti, isShiftDown, isControlDown); break; } // Check for top/left header mouse down case DataGridViewHitTestTypeInternal.TopLeftHeader: { OnTopLeftHeaderMouseDown(); break; } // Check for row headers resize case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeLeft: case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeRight: case DataGridViewHitTestTypeInternal.RowHeadersResizeLeft: case DataGridViewHitTestTypeInternal.RowHeadersResizeRight: { if (e.Clicks == 1) { BeginRowHeadersResize(ptGridCoord.X, hti.mouseBarOffset); } break; } // Check for column headers resize case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeTop: case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeBottom: case DataGridViewHitTestTypeInternal.ColumnHeadersResizeTop: case DataGridViewHitTestTypeInternal.ColumnHeadersResizeBottom: { if (e.Clicks == 1) { BeginColumnHeadersResize(ptGridCoord.Y, hti.mouseBarOffset); } break; } } // Make sure that there is a current cell after this mouse down event. if (this.ptCurrentCell.X == -1) { MakeFirstDisplayedCellCurrentCell(true /*includeNewRow*/); } } } finally { this.dataGridViewOper[DATAGRIDVIEWOPER_resizingOperationAboutToStart] = false; } } private void OnCellMouseDown(HitTestInfo hti, bool isShiftDown, bool isControlDown) { Debug.Assert(hti.Type == DataGridViewHitTestType.Cell); // Only commit cell if the target cell is different from the current one. if (this.ptCurrentCell.X >= 0 && (this.ptCurrentCell.X != hti.col || this.ptCurrentCell.Y != hti.row)) { Point ptOriginalCurrentCell = this.ptCurrentCell; if (!CommitEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit, this.ptCurrentCell.X != hti.col || this.ptCurrentCell.Y != hti.row /*forCurrentCellChange*/, this.ptCurrentCell.Y != hti.row /*forCurrentRowChange*/)) { // Return silently if validating/commit/abort failed return; } if (this.ptCurrentCell != ptOriginalCurrentCell) { // VSWhidbey 492203. Somehow the fact that the current cell was committed altered the current cell value. // To avoid unintentional multi-selections, we act as if Shift and Control keys were up. isShiftDown = isControlDown = false; } } if (hti.col >= this.Columns.Count) { DataGridViewColumn dataGridViewLastVisibleColumn = this.Columns.GetLastColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.None); if (this.ptCurrentCell.X == -1 && dataGridViewLastVisibleColumn != null) { // CurrentCell was reset because CommitEdit deleted column(s). // Since the user clicked on a cell, we don't want to end up // with no CurrentCell. We pick the last visible column in the grid. hti.col = dataGridViewLastVisibleColumn.Index; } else { return; } } if (hti.row >= this.Rows.Count) { int lastVisibleRowIndex = this.Rows.GetLastRow(DataGridViewElementStates.Visible); if (this.ptCurrentCell.X == -1 && lastVisibleRowIndex != -1) { // CurrentCell was reset because CommitEdit deleted row(s). // Since the user clicked on a cell, we don't want to end up // with no CurrentCell. We pick the last visible row in the // grid which may be the 'new row'. hti.row = lastVisibleRowIndex; } else { return; } } bool select = true; this.noSelectionChangeCount++; try { switch (this.SelectionMode) { case DataGridViewSelectionMode.CellSelect: { if (isControlDown && IsSharedCellSelected(this.Rows.SharedRow(hti.row).Cells[hti.col], hti.row) && (!isShiftDown || !this.MultiSelect)) { select = false; } if (select) { if ((!this.MultiSelect || !isControlDown) && !(this.MultiSelect && isShiftDown)) { Debug.Assert(this.MultiSelect || this.individualSelectedCells.Count <= 1); RemoveIndividuallySelectedCells(hti.col, hti.row); } if (this.MultiSelect) { if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves]) { this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect] = true; } if (isShiftDown) { int oldEdgeColumnIndex = this.ptCurrentCell.X; int oldEdgeRowIndex = this.ptCurrentCell.Y; if (this.ptAnchorCell.X == -1) { return; } UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, hti.col, this.ptAnchorCell.Y, ref oldEdgeRowIndex, hti.row); } else { SetSelectedCellCore(hti.col, hti.row, true); } } else { SetSelectedCellCore(hti.col, hti.row, true); } } else { SetSelectedCellCore(hti.col, hti.row, false); } bool success = SetCurrentCellAddressCore(hti.col, hti.row, !isShiftDown, false, true); Debug.Assert(success); break; } case DataGridViewSelectionMode.FullColumnSelect: { if (isControlDown && this.Columns[hti.col].Selected) { select = false; } if (select) { bool selectColumnRange = false; this.trackColumn = hti.col; this.trackColumnEdge = -1; if (this.MultiSelect && isShiftDown && this.ptAnchorCell.X > -1 && this.Columns[this.ptAnchorCell.X].Selected) { selectColumnRange = true; } if (!this.MultiSelect || !isControlDown || isShiftDown) { Debug.Assert(this.MultiSelect || this.selectedBandIndexes.Count <= 1); int bandIndex = 0; bool switchedToBulkPaint = false; if (this.selectedBandIndexes.Count > DATAGRIDVIEW_bulkPaintThreshold) { this.inBulkPaintCount++; switchedToBulkPaint = true; } try { while (bandIndex < this.selectedBandIndexes.Count) { if (this.selectedBandIndexes[bandIndex] != hti.col) { // deselect currently selected column SetSelectedColumnCore(this.selectedBandIndexes[bandIndex], false); } else { bandIndex++; } } } finally { if (switchedToBulkPaint) { ExitBulkPaint(-1, -1); } } } if (this.MultiSelect && this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves]) { this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] = true; } if (selectColumnRange) { if (this.Columns.DisplayInOrder(this.ptAnchorCell.X, hti.col)) { SelectColumnRange(this.ptAnchorCell.X, hti.col, true); } else { SelectColumnRange(hti.col, this.ptAnchorCell.X, true); } } else if (!this.selectedBandIndexes.Contains(hti.col)) { SetSelectedColumnCore(hti.col, true); } } else { Debug.Assert(this.selectedBandIndexes.Contains(hti.col)); SetSelectedColumnCore(hti.col, false); } bool success = SetCurrentCellAddressCore(hti.col, hti.row, !isShiftDown, false, true); Debug.Assert(success); break; } case DataGridViewSelectionMode.ColumnHeaderSelect: { if (isControlDown && (this.Columns[hti.col].Selected || IsSharedCellSelected(this.Rows.SharedRow(hti.row).Cells[hti.col], hti.row)) && (!isShiftDown || !this.MultiSelect)) { select = false; } if (select) { if (!this.MultiSelect) { Debug.Assert(this.selectedBandIndexes.Count <= 1); if (this.selectedBandIndexes.Count > 0) { SetSelectedColumnCore(this.selectedBandIndexes.HeadInt, false); } else { RemoveIndividuallySelectedCells(); } SetSelectedCellCore(hti.col, hti.row, true); } else { // this.MultiSelect == true if (!isControlDown && !isShiftDown) { bool switchedToBulkPaint = false; if (this.selectedBandIndexes.Count > DATAGRIDVIEW_bulkPaintThreshold) { this.inBulkPaintCount++; switchedToBulkPaint = true; } try { while (this.selectedBandIndexes.Count > 0) { SetSelectedColumnCore(this.selectedBandIndexes.HeadInt, false); } RemoveIndividuallySelectedCells(hti.col, hti.row); } finally { if (switchedToBulkPaint) { ExitBulkPaint(-1, -1); } } } if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves]) { this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect] = true; } if (isShiftDown) { int oldEdgeColumnIndex = this.ptCurrentCell.X; int oldEdgeRowIndex = this.ptCurrentCell.Y; if (this.ptAnchorCell.X == -1) { return; } UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, hti.col, this.ptAnchorCell.Y, ref oldEdgeRowIndex, hti.row); } else { SetSelectedCellCore(hti.col, hti.row, true); } } } else { if (!this.MultiSelect) { Debug.Assert(this.selectedBandIndexes.Count <= 1); if (this.selectedBandIndexes.Count > 0) { SetSelectedColumnCore(this.selectedBandIndexes.HeadInt, false); } else { SetSelectedCellCore(hti.col, hti.row, false); } } else { SetSelectedCellCore(hti.col, hti.row, false); } } bool success = SetCurrentCellAddressCore(hti.col, hti.row, !isShiftDown, false, true); Debug.Assert(success); break; } case DataGridViewSelectionMode.FullRowSelect: { if (isControlDown && ((this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Selected) != 0)) { select = false; } if (select) { bool selectRowRange = false; this.trackRow = hti.row; this.trackRowEdge = -1; if (this.MultiSelect && isShiftDown && this.ptAnchorCell.Y > -1 && (this.Rows.GetRowState(this.ptAnchorCell.Y) & DataGridViewElementStates.Selected) != 0) { selectRowRange = true; } if (!this.MultiSelect || !isControlDown || isShiftDown) { Debug.Assert(this.MultiSelect || this.selectedBandIndexes.Count <= 1); int bandIndex = 0; bool switchedToBulkPaint = false; if (this.selectedBandIndexes.Count > DATAGRIDVIEW_bulkPaintThreshold) { this.inBulkPaintCount++; switchedToBulkPaint = true; } try { while (bandIndex < this.selectedBandIndexes.Count) { if (this.selectedBandIndexes[bandIndex] != hti.row) { // deselect currently selected row SetSelectedRowCore(this.selectedBandIndexes[bandIndex], false); } else { bandIndex++; } } } finally { if (switchedToBulkPaint) { ExitBulkPaint(-1, -1); } } } if (this.MultiSelect && this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves]) { this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect] = true; } if (selectRowRange) { if (hti.row >= this.ptAnchorCell.Y) { SelectRowRange(this.ptAnchorCell.Y, hti.row, true); } else { SelectRowRange(hti.row, this.ptAnchorCell.Y, true); } } else if ((this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Selected) == 0) { Debug.Assert(this.selectedBandIndexes.Contains(hti.row) == ((this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Selected) != 0)); SetSelectedRowCore(hti.row, true); } } else { Debug.Assert(this.selectedBandIndexes.Contains(hti.row)); SetSelectedRowCore(hti.row, false); } bool success = SetCurrentCellAddressCore(hti.col, hti.row, !isShiftDown, false, true); Debug.Assert(success); break; } case DataGridViewSelectionMode.RowHeaderSelect: { if (isControlDown && (((this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Selected) != 0) || IsSharedCellSelected(this.Rows.SharedRow(hti.row).Cells[hti.col], hti.row)) && (!isShiftDown || !this.MultiSelect)) { select = false; } if (select) { if (!this.MultiSelect) { Debug.Assert(this.selectedBandIndexes.Count <= 1); if (this.selectedBandIndexes.Count > 0) { SetSelectedRowCore(this.selectedBandIndexes.HeadInt, false); } else { RemoveIndividuallySelectedCells(); } SetSelectedCellCore(hti.col, hti.row, true); } else { // this.MultiSelect == true if (!isControlDown && !isShiftDown) { bool switchedToBulkPaint = false; if (this.selectedBandIndexes.Count > DATAGRIDVIEW_bulkPaintThreshold) { this.inBulkPaintCount++; switchedToBulkPaint = true; } try { while (this.selectedBandIndexes.Count > 0) { SetSelectedRowCore(this.selectedBandIndexes.HeadInt, false); } RemoveIndividuallySelectedCells(hti.col, hti.row); } finally { if (switchedToBulkPaint) { ExitBulkPaint(-1, -1); } } } if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves]) { this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect] = true; } if (isShiftDown) { int oldEdgeColumnIndex = this.ptCurrentCell.X; int oldEdgeRowIndex = this.ptCurrentCell.Y; if (this.ptAnchorCell.X == -1) { return; } UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, hti.col, this.ptAnchorCell.Y, ref oldEdgeRowIndex, hti.row); } else { SetSelectedCellCore(hti.col, hti.row, true); } } } else { if (!this.MultiSelect) { Debug.Assert(this.selectedBandIndexes.Count <= 1); if (this.selectedBandIndexes.Count > 0) { SetSelectedRowCore(this.selectedBandIndexes.HeadInt, false); } else { SetSelectedCellCore(hti.col, hti.row, false); } } else { SetSelectedCellCore(hti.col, hti.row, false); } } bool success = SetCurrentCellAddressCore(hti.col, hti.row, !isShiftDown, false, true); // [....]: SetCurrentCellAddressCore can fail if by navigating to a cell the list under the // DataGridView changes. // See vsWhidbey: 325296. // Debug.Assert(success); break; } } } finally { this.NoSelectionChangeCount--; } } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellMouseEnter(DataGridViewCellEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } this.ptMouseEnteredCell.X = e.ColumnIndex; this.ptMouseEnteredCell.Y = e.RowIndex; DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex); Debug.Assert(dataGridViewCell != null); if (e.RowIndex >= 0 && dataGridViewCell.MouseEnterUnsharesRowInternal(e.RowIndex)) { DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex]; GetCellInternal(e.ColumnIndex, e.RowIndex).OnMouseEnterInternal(e.RowIndex); } else { dataGridViewCell.OnMouseEnterInternal(e.RowIndex); } DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLMOUSEENTER] as DataGridViewCellEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellMouseLeave(DataGridViewCellEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } this.ptMouseEnteredCell.X = -2; this.ptMouseEnteredCell.Y = -2; DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex); Debug.Assert(dataGridViewCell != null); if (e.RowIndex >= 0 && dataGridViewCell.MouseLeaveUnsharesRowInternal(e.RowIndex)) { DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex]; GetCellInternal(e.ColumnIndex, e.RowIndex).OnMouseLeaveInternal(e.RowIndex); } else { dataGridViewCell.OnMouseLeaveInternal(e.RowIndex); } DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLMOUSELEAVE] as DataGridViewCellEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellMouseMove(DataGridViewCellMouseEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex); Debug.Assert(dataGridViewCell != null); if (e.RowIndex >= 0 && dataGridViewCell.MouseMoveUnsharesRowInternal(e)) { DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex]; GetCellInternal(e.ColumnIndex, e.RowIndex).OnMouseMoveInternal(e); } else { dataGridViewCell.OnMouseMoveInternal(e); } DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLMOUSEMOVE] as DataGridViewCellMouseEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } if (!this.dataGridViewState1[DATAGRIDVIEWSTATE1_scrolledSinceMouseDown] && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize] && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize] && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation] && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize] && this.AllowUserToOrderColumns && this.SelectionMode != DataGridViewSelectionMode.FullColumnSelect && this.SelectionMode != DataGridViewSelectionMode.ColumnHeaderSelect && e.Button == MouseButtons.Left && this.ptMouseDownCell.Y == -1 && this.ptMouseDownCell.X >= 0 && this.ptMouseDownCell.X < this.Columns.Count) { Point ptGridCoord = ConvertCellToGridCoord(e.ColumnIndex, e.RowIndex, e.X, e.Y); HitTestInfo hti = HitTest(ptGridCoord.X, ptGridCoord.Y); Debug.Assert(hti.Type != DataGridViewHitTestType.None && hti.Type != DataGridViewHitTestType.HorizontalScrollBar && hti.Type != DataGridViewHitTestType.VerticalScrollBar); switch (hti.typeInternal) { // Check for column header mouse down case DataGridViewHitTestTypeInternal.ColumnHeader: case DataGridViewHitTestTypeInternal.ColumnHeaderLeft: case DataGridViewHitTestTypeInternal.ColumnHeaderRight: case DataGridViewHitTestTypeInternal.FirstColumnHeaderLeft: { Debug.Assert(!this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls]); if (Math.Abs(this.ptMouseDownGridCoord.X - ptGridCoord.X) >= DataGridView.DragSize.Width || Math.Abs(this.ptMouseDownGridCoord.Y - ptGridCoord.Y) >= DataGridView.DragSize.Height) { BeginColumnRelocation(this.ptMouseDownGridCoord.X, this.ptMouseDownCell.X); } break; } } } } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellMouseUp(DataGridViewCellMouseEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } DataGridViewCell dataGridViewCell = GetCellInternal(e.ColumnIndex, e.RowIndex); Debug.Assert(dataGridViewCell != null); if (e.RowIndex >= 0 && dataGridViewCell.MouseUpUnsharesRowInternal(e)) { DataGridViewRow dataGridViewRow = this.Rows[e.RowIndex]; GetCellInternal(e.ColumnIndex, e.RowIndex).OnMouseUpInternal(e); } else { dataGridViewCell.OnMouseUpInternal(e); } DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLMOUSEUP] as DataGridViewCellMouseEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected internal virtual void OnCellPainting(DataGridViewCellPaintingEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } DataGridViewCellPaintingEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLPAINTING] as DataGridViewCellPaintingEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal DataGridViewCellParsingEventArgs OnCellParsing(int rowIndex, int columnIndex, object formattedValue, Type valueType, DataGridViewCellStyle cellStyle) { DataGridViewCellParsingEventArgs dgvcpe = new DataGridViewCellParsingEventArgs(rowIndex, columnIndex, formattedValue, valueType, cellStyle); OnCellParsing(dgvcpe); return dgvcpe; } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellParsing(DataGridViewCellParsingEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } DataGridViewCellParsingEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLPARSING] as DataGridViewCellParsingEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } private void OnCellSelectMouseMove(HitTestInfo hti) { Debug.Assert(this.MultiSelect); int oldEdgeColumnIndex = this.ptCurrentCell.X; int oldEdgeRowIndex = this.ptCurrentCell.Y; if ((hti.col != this.ptCurrentCell.X || hti.row != this.ptCurrentCell.Y) && !CommitEditForOperation(hti.col, hti.row, true)) { // Return silently if validating/commit/abort failed return; } this.noSelectionChangeCount++; try { if (this.ptAnchorCell.X == -1 || IsInnerCellOutOfBounds(hti.col, hti.row)) { return; } UpdateSelectedCellsBlock(this.ptAnchorCell.X, ref oldEdgeColumnIndex, hti.col, this.ptAnchorCell.Y, ref oldEdgeRowIndex, hti.row); if (hti.col != this.ptCurrentCell.X || hti.row != this.ptCurrentCell.Y) { bool success = SetCurrentCellAddressCore(hti.col, hti.row, false, false, false); Debug.Assert(success); } } finally { this.NoSelectionChangeCount--; } } /// protected virtual void OnCellStateChanged(DataGridViewCellStateChangedEventArgs e) { // At this point we assume that only the Selected state has an influence on the rendering of the cell. // If there is a scenario where another state has an effect, then the dev will have to invalidate the cell by hand. DataGridViewCell dataGridViewCell = e.Cell; if (e.StateChanged == DataGridViewElementStates.Selected) { Debug.Assert(dataGridViewCell.RowIndex >= 0); if (this.inBulkPaintCount == 0) { InvalidateCellPrivate(dataGridViewCell); } } DataGridViewCellStateChangedEventHandler eh = Events[EVENT_DATAGRIDVIEWCELLSTATECHANGED] as DataGridViewCellStateChangedEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } if (e.StateChanged == DataGridViewElementStates.ReadOnly && this.ptCurrentCell.X == dataGridViewCell.ColumnIndex && this.ptCurrentCell.Y == dataGridViewCell.RowIndex && dataGridViewCell.RowIndex > -1 && !this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange]) { VerifyImeRestrictedModeChanged(); if (!dataGridViewCell.ReadOnly && ColumnEditable(this.ptCurrentCell.X) && !this.IsCurrentCellInEditMode && (this.EditMode == DataGridViewEditMode.EditOnEnter || (this.EditMode != DataGridViewEditMode.EditProgrammatically && this.CurrentCellInternal.EditType == null))) { // Current cell becomes read/write. Enter editing mode. BeginEditInternal(true /*selectAll*/); } } } internal void OnCellStyleChanged(DataGridViewCell dataGridViewCell) { DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(dataGridViewCell); OnCellStyleChanged(dgvce); } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellStyleChanged(DataGridViewCellEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } OnCellCommonChange(e.ColumnIndex, e.RowIndex); DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLSTYLECHANGED] as DataGridViewCellEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal void OnCellStyleContentChanged(DataGridViewCellStyle dataGridViewCellStyle, DataGridViewCellStyle.DataGridViewCellStylePropertyInternal property) { Debug.Assert(dataGridViewCellStyle != null); switch (property) { case DataGridViewCellStyle.DataGridViewCellStylePropertyInternal.Font: if ((dataGridViewCellStyle.Scope & DataGridViewCellStyleScopes.DataGridView) != 0 && this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientFont]) { this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientFont] = false; } if ((dataGridViewCellStyle.Scope & DataGridViewCellStyleScopes.ColumnHeaders) != 0 && this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientColumnHeadersFont]) { this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientColumnHeadersFont] = false; } if ((dataGridViewCellStyle.Scope & DataGridViewCellStyleScopes.RowHeaders) != 0 && this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientRowHeadersFont]) { this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientRowHeadersFont] = false; } break; case DataGridViewCellStyle.DataGridViewCellStylePropertyInternal.ForeColor: if ((dataGridViewCellStyle.Scope & DataGridViewCellStyleScopes.DataGridView) != 0 && this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientForeColor]) { this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientForeColor] = false; } break; } DataGridViewCellStyleContentChangedEventArgs dgvcscce = new DataGridViewCellStyleContentChangedEventArgs(dataGridViewCellStyle, property != DataGridViewCellStyle.DataGridViewCellStylePropertyInternal.Color && property != DataGridViewCellStyle.DataGridViewCellStylePropertyInternal.ForeColor /*changeAffectsPreferredSize*/); OnCellStyleContentChanged(dgvcscce); } /// protected virtual void OnCellStyleContentChanged(DataGridViewCellStyleContentChangedEventArgs e) { // We assume that when a color changes, it has no effect on the autosize of elements bool repositionEditingControl = false; if ((e.CellStyleScope & DataGridViewCellStyleScopes.Cell) == DataGridViewCellStyleScopes.Cell && (e.CellStyleScope & DataGridViewCellStyleScopes.DataGridView) == 0) { // Same processing as in OnDefaultCellStyleChanged if (e.ChangeAffectsPreferredSize) { repositionEditingControl = true; OnGlobalAutoSize(); } else { Invalidate(); } } if ((e.CellStyleScope & DataGridViewCellStyleScopes.Column) == DataGridViewCellStyleScopes.Column) { if (e.ChangeAffectsPreferredSize) { repositionEditingControl = true; OnColumnsGlobalAutoSize(); } else { InvalidateData(); } } if ((e.CellStyleScope & DataGridViewCellStyleScopes.Row) == DataGridViewCellStyleScopes.Row && (e.CellStyleScope & DataGridViewCellStyleScopes.Rows) == 0 && (e.CellStyleScope & DataGridViewCellStyleScopes.AlternatingRows) == 0) { // Same processing as in OnRowsDefaultCellStyleChanged InvalidateData(); if (e.ChangeAffectsPreferredSize) { repositionEditingControl = true; // Autosize rows if needed if ((((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0) { AdjustShrinkingRows(this.autoSizeRowsMode, false /*fixedWidth*/, true /*internalAutosizing*/); } // Auto size columms also if needed // Impossible to figure out if DisplayedRows filter should be added or not. Adding it to be on the conservative side. AutoResizeAllVisibleColumnsInternal(DataGridViewAutoSizeColumnCriteriaInternal.AllRows | DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows, true /*fixedHeight*/); // Second round of rows autosizing if ((((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0) { AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); } } } if ((e.CellStyleScope & DataGridViewCellStyleScopes.DataGridView) == DataGridViewCellStyleScopes.DataGridView) { this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = e.ChangeAffectsPreferredSize; if (e.ChangeAffectsPreferredSize) { repositionEditingControl = false; // OnDefaultCellStyleChanged will reposition the editing control. } OnDefaultCellStyleChanged(this.CellStyleChangedEventArgs); } if ((e.CellStyleScope & DataGridViewCellStyleScopes.ColumnHeaders) == DataGridViewCellStyleScopes.ColumnHeaders) { this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = e.ChangeAffectsPreferredSize; if (e.ChangeAffectsPreferredSize) { repositionEditingControl = false; // OnColumnHeadersDefaultCellStyleChanged will reposition the editing control. } OnColumnHeadersDefaultCellStyleChanged(this.CellStyleChangedEventArgs); } if ((e.CellStyleScope & DataGridViewCellStyleScopes.RowHeaders) == DataGridViewCellStyleScopes.RowHeaders) { this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = e.ChangeAffectsPreferredSize; if (e.ChangeAffectsPreferredSize) { repositionEditingControl = false; // OnRowHeadersDefaultCellStyleChanged will reposition the editing control. } OnRowHeadersDefaultCellStyleChanged(this.CellStyleChangedEventArgs); } if ((e.CellStyleScope & DataGridViewCellStyleScopes.Rows) == DataGridViewCellStyleScopes.Rows) { this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = e.ChangeAffectsPreferredSize; if (e.ChangeAffectsPreferredSize) { repositionEditingControl = false; // OnRowsDefaultCellStyleChanged will reposition the editing control. } OnRowsDefaultCellStyleChanged(this.CellStyleChangedEventArgs); } if ((e.CellStyleScope & DataGridViewCellStyleScopes.AlternatingRows) == DataGridViewCellStyleScopes.AlternatingRows) { this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = e.ChangeAffectsPreferredSize; if (e.ChangeAffectsPreferredSize) { repositionEditingControl = false; // OnAlternatingRowsDefaultCellStyleChanged will reposition the editing control. } OnAlternatingRowsDefaultCellStyleChanged(this.CellStyleChangedEventArgs); } if (repositionEditingControl && this.editingControl != null) { PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/); } DataGridViewCellStyleContentChangedEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLSTYLECONTENTCHANGED] as DataGridViewCellStyleContentChangedEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal void OnCellToolTipTextChanged(DataGridViewCell dataGridViewCell) { DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(dataGridViewCell); OnCellToolTipTextChanged(dgvce); } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellToolTipTextChanged(DataGridViewCellEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLTOOLTIPTEXTCHANGED] as DataGridViewCellEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal string OnCellToolTipTextNeeded(int columnIndex, int rowIndex, string toolTipText) { DataGridViewCellToolTipTextNeededEventArgs dgvctttne = new DataGridViewCellToolTipTextNeededEventArgs(columnIndex, rowIndex, toolTipText); OnCellToolTipTextNeeded(dgvctttne); return dgvctttne.ToolTipText; } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellToolTipTextNeeded(DataGridViewCellToolTipTextNeededEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } DataGridViewCellToolTipTextNeededEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLTOOLTIPTEXTNEEDED] as DataGridViewCellToolTipTextNeededEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal void OnCellValidated(ref DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex) { OnCellValidated(new DataGridViewCellEventArgs(columnIndex, rowIndex)); if (dataGridViewCell != null) { if (IsInnerCellOutOfBounds(columnIndex, rowIndex)) { dataGridViewCell = null; } else { Debug.Assert(rowIndex < this.Rows.Count && columnIndex < this.Columns.Count); dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex]; } } } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellValidated(DataGridViewCellEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } try { this.noDimensionChangeCount++; DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLVALIDATED] as DataGridViewCellEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); CorrectFocus(true /*onlyIfGridHasFocus*/); } } finally { this.noDimensionChangeCount--; Debug.Assert(this.noDimensionChangeCount >= 0); } } internal bool OnCellValidating(ref DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex, DataGridViewDataErrorContexts context) { DataGridViewCell currentCell = (dataGridViewCell == null) ? this.CurrentCellInternal : dataGridViewCell; DataGridViewCellStyle dataGridViewCellStyle = currentCell.GetInheritedStyle(null, rowIndex, false); object val = currentCell.GetValueInternal(rowIndex); object editedFormattedValue = currentCell.GetEditedFormattedValue(val, rowIndex, ref dataGridViewCellStyle, context); DataGridViewCellValidatingEventArgs dgvcfvce = new DataGridViewCellValidatingEventArgs(columnIndex, rowIndex, editedFormattedValue); OnCellValidating(dgvcfvce); if (dataGridViewCell != null) { if (IsInnerCellOutOfBounds(columnIndex, rowIndex)) { dataGridViewCell = null; } else { Debug.Assert(rowIndex < this.Rows.Count && columnIndex < this.Columns.Count); dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex]; } } return dgvcfvce.Cancel; } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellValidating(DataGridViewCellValidatingEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } try { this.noDimensionChangeCount++; this.dataGridViewOper[DATAGRIDVIEWOPER_inCellValidating] = true; DataGridViewCellValidatingEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLVALIDATING] as DataGridViewCellValidatingEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); CorrectFocus(true /*onlyIfGridHasFocus*/); } } finally { this.noDimensionChangeCount--; Debug.Assert(this.noDimensionChangeCount >= 0); this.dataGridViewOper[DATAGRIDVIEWOPER_inCellValidating] = false; } } internal void OnCellValueChangedInternal(DataGridViewCellEventArgs e) { // For now, same effect as if the cell style had changed. OnCellValueChanged(e); } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellValueChanged(DataGridViewCellEventArgs e) { if (e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } OnCellCommonChange(e.ColumnIndex, e.RowIndex); DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLVALUECHANGED] as DataGridViewCellEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal object OnCellValueNeeded(int columnIndex, int rowIndex) { DataGridViewCellValueEventArgs dgvcve = this.CellValueEventArgs; dgvcve.SetProperties(columnIndex, rowIndex, null); OnCellValueNeeded(dgvcve); return dgvcve.Value; } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellValueNeeded(DataGridViewCellValueEventArgs e) { if (e.ColumnIndex < 0 || e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex < 0 || e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } //#if DEBUG // Some customer scenarios may result in accessing cell values while this.dataStoreAccessAllowed is false. This is bad practice, // but since we're late in Whidbey, throwing an exception would be destabilizing our internal customers. // Debug.Assert(this.dataStoreAccessAllowed); //#endif DataGridViewCellValueEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLVALUENEEDED] as DataGridViewCellValueEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal void OnCellValuePushed(int columnIndex, int rowIndex, object value) { DataGridViewCellValueEventArgs dgvcve = this.CellValueEventArgs; dgvcve.SetProperties(columnIndex, rowIndex, value); OnCellValuePushed(dgvcve); } /// [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] // e.ColumnIndex / e.RowIndex is more precise than just e protected virtual void OnCellValuePushed(DataGridViewCellValueEventArgs e) { if (e.ColumnIndex < 0 || e.ColumnIndex >= this.Columns.Count) { throw new ArgumentOutOfRangeException("e.ColumnIndex"); } if (e.RowIndex < 0 || e.RowIndex >= this.Rows.Count) { throw new ArgumentOutOfRangeException("e.RowIndex"); } DataGridViewCellValueEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCELLVALUEPUSHED] as DataGridViewCellValueEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal void OnClearedRows() { // Raise the RowStateChanged(Displayed->false) events foreach (DataGridViewRow dataGridViewRow in this.lstRows) { if (dataGridViewRow.Displayed) { dataGridViewRow.DisplayedInternal = false; DataGridViewRowStateChangedEventArgs dgvrsce = new DataGridViewRowStateChangedEventArgs(dataGridViewRow, DataGridViewElementStates.Displayed); OnRowStateChanged(-1 /*rowIndex*/, dgvrsce); } } this.lstRows.Clear(); } internal void OnClearingColumns() { this.CurrentCell = null; // Rows need to be cleared first. There cannot be rows without also having columns. this.Rows.ClearInternal(false /*recreateNewRow*/); // Reset sort related variables. this.sortedColumn = null; this.sortOrder = SortOrder.None; // selectedBandIndexes, individualSelectedCells & individualReadOnlyCells cleared in OnClearingRows. } [ SuppressMessage("Microsoft.Performance", "CA1817:DoNotCallPropertiesThatCloneValuesInLoops") // Illegitimate report. ] internal void OnClearingRows() { // Build a list of displayed rows in order to be able to raise their RowStateChanged(Displayed->false) events later on this.lstRows.Clear(); int numDisplayedRows = this.displayedBandsInfo.NumDisplayedFrozenRows + this.displayedBandsInfo.NumDisplayedScrollingRows; if (numDisplayedRows > 0) { this.lstRows.Capacity = numDisplayedRows; int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Displayed); while (numDisplayedRows > 0 && rowIndex != -1) { this.lstRows.Add(this.Rows[rowIndex]); numDisplayedRows--; if (numDisplayedRows > 0) { rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Displayed); } } } this.CurrentCell = null; this.newRowIndex = -1; this.dataGridViewState2[DATAGRIDVIEWSTATE2_raiseSelectionChanged] = this.selectedBandIndexes.Count > 0 || this.individualSelectedCells.Count > 0; this.selectedBandIndexes.Clear(); if (this.selectedBandSnapshotIndexes != null) { this.selectedBandSnapshotIndexes.Clear(); } this.individualSelectedCells.Clear(); this.individualReadOnlyCells.Clear(); } /// protected virtual void OnColumnAdded(DataGridViewColumnEventArgs e) { if (e.Column.DataGridView != this) { throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); } DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNADDED] as DataGridViewColumnEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal void OnColumnCollectionChanged_PreNotification(CollectionChangeEventArgs ccea) { // we need to map columns w/ DataPropertyName to bound columns if (this.DataSource != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inRefreshColumns]) { if (ccea.Action == CollectionChangeAction.Add) { DataGridViewColumn dataGridViewColumn = (DataGridViewColumn)ccea.Element; if (dataGridViewColumn.DataPropertyName.Length != 0) { MapDataGridViewColumnToDataBoundField(dataGridViewColumn); } } else if (ccea.Action == CollectionChangeAction.Refresh) { for (int i = 0; i < this.Columns.Count; i++) { if (this.Columns[i].DataPropertyName.Length != 0) { MapDataGridViewColumnToDataBoundField(this.Columns[i]); } } } } ResetUIState(false /*useRowShortcut*/, false /*computeVisibleRows*/); } internal void OnColumnCollectionChanged_PostNotification(DataGridViewColumn dataGridViewColumn) { if (this.Columns.Count != 0 && this.Rows.Count == 0) { if (this.DataSource != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inRefreshColumns]) { // this will create the 'add new row' when AllowUserToAddRowsInternal == true RefreshRows(true /*scrollIntoView*/); } else if (this.AllowUserToAddRowsInternal) { AddNewRow(false); } } if (this.AutoSize && (dataGridViewColumn == null || dataGridViewColumn.Visible)) { LayoutTransaction.DoLayout(this.ParentInternal, this, PropertyNames.Columns); } } internal void OnColumnCommonChange(int columnIndex) { OnColumnGlobalAutoSize(columnIndex); } /// protected virtual void OnColumnContextMenuStripChanged(DataGridViewColumnEventArgs e) { if (e.Column.DataGridView != this) { throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); } DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNCONTEXTMENUSTRIPCHANGED] as DataGridViewColumnEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal void OnColumnDataPropertyNameChanged(DataGridViewColumn dataGridViewColumn) { OnColumnDataPropertyNameChanged(new DataGridViewColumnEventArgs(dataGridViewColumn)); } /// protected virtual void OnColumnDataPropertyNameChanged(DataGridViewColumnEventArgs e) { if (e.Column.DataGridView != this) { throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); } // map the dataGridView column to some data field if (this.DataSource != null && e.Column.DataPropertyName.Length != 0 && !this.dataGridViewOper[DATAGRIDVIEWOPER_inRefreshColumns]) { MapDataGridViewColumnToDataBoundField(e.Column); } else if (this.DataSource != null && e.Column.DataPropertyName.Length == 0) { if (e.Column.IsDataBound) { e.Column.IsDataBoundInternal = false; e.Column.BoundColumnIndex = -1; e.Column.BoundColumnConverter = null; InvalidateColumnInternal(e.Column.Index); } } DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNDATAPROPERTYNAMECHANGED] as DataGridViewColumnEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnColumnDefaultCellStyleChanged(DataGridViewColumnEventArgs e) { if (e.Column.DataGridView != this) { throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); } OnColumnGlobalAutoSize(e.Column.Index); DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNDEFAULTCELLSTYLECHANGED] as DataGridViewColumnEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal void OnColumnDisplayIndexChanged(DataGridViewColumn dataGridViewColumn) { Debug.Assert(dataGridViewColumn != null); DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn); OnColumnDisplayIndexChanged(dgvce); } internal void OnColumnDisplayIndexChanging(DataGridViewColumn dataGridViewColumn, int newDisplayIndex) { Debug.Assert(dataGridViewColumn != null); Debug.Assert(newDisplayIndex != dataGridViewColumn.DisplayIndex); if (this.dataGridViewOper[DATAGRIDVIEWOPER_inDisplayIndexAdjustments]) { // We are within columns display indexes adjustments. We do not allow changing display indexes while adjusting them. throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAlterDisplayIndexWithinAdjustments)); } // Throws an exception if the requested move is illegal CorrectColumnFrozenStatesForMove(dataGridViewColumn, newDisplayIndex); try { this.dataGridViewOper[DATAGRIDVIEWOPER_inDisplayIndexAdjustments] = true; // Move is legal - let's adjust the affected display indexes. if (newDisplayIndex < dataGridViewColumn.DisplayIndex) { // DisplayIndex decreases. All columns with newDisplayIndex <= DisplayIndex < dataGridViewColumn.DisplayIndex // get their DisplayIndex incremented. foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns) { if (newDisplayIndex <= dataGridViewColumnTmp.DisplayIndex && dataGridViewColumnTmp.DisplayIndex < dataGridViewColumn.DisplayIndex) { dataGridViewColumnTmp.DisplayIndexInternal = dataGridViewColumnTmp.DisplayIndex + 1; dataGridViewColumnTmp.DisplayIndexHasChanged = true; // OnColumnDisplayIndexChanged needs to be raised later on } } } else { // DisplayIndex increases. All columns with dataGridViewColumn.DisplayIndex < DisplayIndex <= newDisplayIndex // get their DisplayIndex incremented. foreach (DataGridViewColumn dataGridViewColumnTmp in this.Columns) { if (dataGridViewColumn.DisplayIndex < dataGridViewColumnTmp.DisplayIndex && dataGridViewColumnTmp.DisplayIndex <= newDisplayIndex) { dataGridViewColumnTmp.DisplayIndexInternal = dataGridViewColumnTmp.DisplayIndex - 1; dataGridViewColumnTmp.DisplayIndexHasChanged = true; // OnColumnDisplayIndexChanged needs to be raised later on } } } } finally { this.dataGridViewOper[DATAGRIDVIEWOPER_inDisplayIndexAdjustments] = false; } // Note that displayIndex of moved column is updated by caller. } /// protected virtual void OnColumnDisplayIndexChanged(DataGridViewColumnEventArgs e) { if (e.Column.DataGridView != this) { throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); } Debug.Assert(this.dataGridViewOper[DATAGRIDVIEWOPER_inDisplayIndexAdjustments]); #if DEBUG Debug.Assert(this.Columns.VerifyColumnDisplayIndexes()); #endif DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNDISPLAYINDEXCHANGED] as DataGridViewColumnEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal void OnColumnDisplayIndexChanged_PreNotification() { Debug.Assert(this.dataGridViewOper[DATAGRIDVIEWOPER_inDisplayIndexAdjustments]); // column.DisplayIndex changed - this may require a complete re-layout of the control this.Columns.InvalidateCachedColumnsOrder(); PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); if (this.editingControl != null) { PositionEditingControl(true, true, false); } Invalidate(Rectangle.Union(this.layout.ColumnHeaders, this.layout.Data)); } internal void OnColumnDisplayIndexChanged_PostNotification() { // Notifications for adjusted display indexes. FlushDisplayIndexChanged(true /*raiseEvent*/); } /// protected virtual void OnColumnDividerDoubleClick(DataGridViewColumnDividerDoubleClickEventArgs e) { DataGridViewColumnDividerDoubleClickEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNDIVIDERDOUBLECLICK] as DataGridViewColumnDividerDoubleClickEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } if (!e.Handled && e.Button == MouseButtons.Left && e.ColumnIndex < this.Columns.Count) { if (e.ColumnIndex == -1) { AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders, true /*fixedColumnHeadersHeight*/, true /*fixedRowsHeight*/); } else { DataGridViewAutoSizeColumnMode inheritedAutoSizeMode = this.Columns[e.ColumnIndex].InheritedAutoSizeMode; if (inheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.None || inheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill) { AutoResizeColumnInternal(e.ColumnIndex, DataGridViewAutoSizeColumnCriteriaInternal.Header | DataGridViewAutoSizeColumnCriteriaInternal.AllRows, true /*fixedHeight*/); } else { AutoResizeColumnInternal(e.ColumnIndex, (DataGridViewAutoSizeColumnCriteriaInternal)inheritedAutoSizeMode, true /*fixedHeight*/); } } } } /// protected virtual void OnColumnDividerWidthChanged(DataGridViewColumnEventArgs e) { if (e.Column.DataGridView != this) { throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); } OnColumnGlobalAutoSize(e.Column.Index); DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNDIVIDERWIDTHCHANGED] as DataGridViewColumnEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal void OnColumnFillWeightChanged(DataGridViewColumn dataGridViewColumn) { if (dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill) { // UsedFillWeight properties need to be re-evaluated this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = true; // Adjust filling columns based on new weight of this column PerformLayoutPrivate(false /*useRowShortcut*/, true /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); } } internal void OnColumnFillWeightChanging(DataGridViewColumn dataGridViewColumn, float fillWeight) { if (this.InAdjustFillingColumns) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAlterAutoFillColumnParameter)); } // Make sure the sum of the column weights does not exceed ushort.MaxValue float weightSum = this.Columns.GetColumnsFillWeight(DataGridViewElementStates.None) - dataGridViewColumn.FillWeight + fillWeight; if (weightSum > (float)ushort.MaxValue) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_WeightSumCannotExceedLongMaxValue, (ushort.MaxValue).ToString(CultureInfo.CurrentCulture))); } } private void OnColumnGlobalAutoSize(int columnIndex) { Debug.Assert(columnIndex >= 0 && columnIndex < this.Columns.Count); if (!this.Columns[columnIndex].Visible) { return; } InvalidateColumnInternal(columnIndex); if (this.noAutoSizeCount > 0) { return; } bool fixedHeight = (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) == 0; DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaInternal = (DataGridViewAutoSizeColumnCriteriaInternal)this.Columns[columnIndex].InheritedAutoSizeMode; if (autoSizeColumnCriteriaInternal != DataGridViewAutoSizeColumnCriteriaInternal.None && autoSizeColumnCriteriaInternal != DataGridViewAutoSizeColumnCriteriaInternal.Fill) { AutoResizeColumnInternal(columnIndex, autoSizeColumnCriteriaInternal, fixedHeight); } // Autosize rows and column headers if needed if (!fixedHeight) { AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); } if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) { AutoResizeColumnHeadersHeight(columnIndex, true /*fixedRowHeadersWidth*/, true /*fixedColumnWidth*/); } if (!fixedHeight && autoSizeColumnCriteriaInternal != DataGridViewAutoSizeColumnCriteriaInternal.None && autoSizeColumnCriteriaInternal != DataGridViewAutoSizeColumnCriteriaInternal.Fill) { // Second round of column autosizing with 1 degree of freedom AutoResizeColumnInternal(columnIndex, autoSizeColumnCriteriaInternal, true /*fixedHeight*/); } } /// protected virtual void OnColumnHeaderCellChanged(DataGridViewColumnEventArgs e) { if (e.Column.DataGridView != this) { throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); } OnColumnHeaderGlobalAutoSize(e.Column.Index); DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNHEADERCELLCHANGED] as DataGridViewColumnEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } private void OnColumnHeaderGlobalAutoSize(int columnIndex) { if (!this.ColumnHeadersVisible) { return; } InvalidateCellPrivate(columnIndex, -1); if (this.noAutoSizeCount > 0) { return; } DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaInternal = (DataGridViewAutoSizeColumnCriteriaInternal)this.Columns[columnIndex].InheritedAutoSizeMode; DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFiltered = autoSizeColumnCriteriaInternal & DataGridViewAutoSizeColumnCriteriaInternal.Header; bool fixedColumnWidth = autoSizeColumnCriteriaFiltered == 0; if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) { AutoResizeColumnHeadersHeight(columnIndex, true /*fixedRowHeadersWidth*/, fixedColumnWidth); } if (!fixedColumnWidth) { Debug.Assert(autoSizeColumnCriteriaInternal != DataGridViewAutoSizeColumnCriteriaInternal.None); Debug.Assert(autoSizeColumnCriteriaInternal != DataGridViewAutoSizeColumnCriteriaInternal.Fill); bool fixedHeight = (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) == 0; AutoResizeColumnInternal(columnIndex, autoSizeColumnCriteriaInternal, fixedHeight); if (!fixedHeight) { AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); // Second round of column autosizing with 1 degree of freedom AutoResizeColumnInternal(columnIndex, autoSizeColumnCriteriaInternal, true /*fixedHeight*/); } if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) { // Second round of column headers autosizing with 1 degree of freedom AutoResizeColumnHeadersHeight(columnIndex, true /*fixedRowHeadersWidth*/, true /*fixedColumnWidth*/); } } } /// protected virtual void OnColumnHeaderMouseClick(DataGridViewCellMouseEventArgs e) { if (e.Button == MouseButtons.Left && this.SelectionMode != DataGridViewSelectionMode.FullColumnSelect && this.SelectionMode != DataGridViewSelectionMode.ColumnHeaderSelect) { DataGridViewColumn dataGridViewColumn = this.Columns[e.ColumnIndex]; if (dataGridViewColumn.SortMode == DataGridViewColumnSortMode.Automatic && (!this.VirtualMode || dataGridViewColumn.IsDataBound)) { ListSortDirection direction = ListSortDirection.Ascending; if (this.sortedColumn == dataGridViewColumn) { Debug.Assert(this.sortOrder != SortOrder.None); if (this.sortOrder == SortOrder.Ascending) { direction = ListSortDirection.Descending; } } if ((this.DataSource == null) || (this.DataSource != null && (this.dataConnection.List is IBindingList) && ((IBindingList) this.dataConnection.List).SupportsSorting && dataGridViewColumn.IsDataBound)) { Sort(dataGridViewColumn, direction); } } } DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNHEADERMOUSECLICK] as DataGridViewCellMouseEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnColumnHeaderMouseDoubleClick(DataGridViewCellMouseEventArgs e) { DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNHEADERMOUSEDOUBLECLICK] as DataGridViewCellMouseEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } private void OnColumnHeaderMouseDown(HitTestInfo hti, bool isShiftDown, bool isControlDown) { Debug.Assert(hti.Type == DataGridViewHitTestType.ColumnHeader); this.noSelectionChangeCount++; try { switch (this.SelectionMode) { case DataGridViewSelectionMode.CellSelect: case DataGridViewSelectionMode.FullRowSelect: case DataGridViewSelectionMode.RowHeaderSelect: break; case DataGridViewSelectionMode.FullColumnSelect: case DataGridViewSelectionMode.ColumnHeaderSelect: { bool select = true; if (isControlDown && this.Columns[hti.col].Selected) { select = false; } if (select) { int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible); if (rowIndex > -1 && hti.col != this.ptCurrentCell.X) { // Make sure we will be able to scroll into view int oldCurrentCellX = this.ptCurrentCell.X; int oldCurrentCellY = this.ptCurrentCell.Y; if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.CurrentCellChange, DataGridViewValidateCellInternal.Always /*validateCell*/, true /*fireCellLeave*/, true /*fireCellEnter*/, rowIndex != this.ptCurrentCell.Y /*fireRowLeave*/, rowIndex != this.ptCurrentCell.Y /*fireRowEnter*/, false /*fireLeave*/, this.EditMode != DataGridViewEditMode.EditOnEnter /*keepFocus*/, true /*resetCurrentCell*/, false /*resetAnchorCell*/)) { // Just cancel operation silently instead of throwing InvalidOperationException return; } if (rowIndex != oldCurrentCellY && oldCurrentCellY != -1) { DataGridViewCell dataGridViewCellTmp = null; if (IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) { return; } if (OnRowValidating(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY)) { // Row validation was cancelled if (IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) { return; } OnRowEnter(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY, true /*canCreateNewRow*/, true /*validationFailureOccurred*/); if (IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) { return; } OnCellEnter(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY); return; } if (IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) { return; } OnRowValidated(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY); } } if (IsColumnOutOfBounds(hti.col)) { return; } bool selectColumnRange = false; this.trackColumn = hti.col; this.trackColumnEdge = -1; if (this.MultiSelect && isShiftDown && this.ptAnchorCell.X > -1 && this.Columns[this.ptAnchorCell.X].Selected) { selectColumnRange = true; } if (!this.MultiSelect || !isControlDown || isShiftDown) { Debug.Assert(this.MultiSelect || this.selectedBandIndexes.Count <= 1); int bandIndex = 0; bool switchedToBulkPaint = false; if (this.selectedBandIndexes.Count > DATAGRIDVIEW_bulkPaintThreshold) { this.inBulkPaintCount++; switchedToBulkPaint = true; } try { while (bandIndex < this.selectedBandIndexes.Count) { if (this.selectedBandIndexes[bandIndex] != hti.col) { // deselect currently selected column SetSelectedColumnCore(this.selectedBandIndexes[bandIndex], false); } else { bandIndex++; } } if (this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect) { RemoveIndividuallySelectedCells(); } else { Debug.Assert(this.individualSelectedCells.Count == 0); } } finally { if (switchedToBulkPaint) { ExitBulkPaint(-1, -1); } } } if (this.MultiSelect && this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves]) { this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] = true; } if (selectColumnRange) { if (this.Columns.DisplayInOrder(this.ptAnchorCell.X, hti.col)) { SelectColumnRange(this.ptAnchorCell.X, hti.col, true); } else { SelectColumnRange(hti.col, this.ptAnchorCell.X, true); } } else if (!this.selectedBandIndexes.Contains(hti.col)) { SetSelectedColumnCore(hti.col, true); } // set current cell to the top most visible cell in the column if (rowIndex != -1) { if (hti.col != this.ptCurrentCell.X) { if (IsInnerCellOutOfBounds(hti.col, rowIndex)) { return; } bool success = ScrollIntoView(hti.col, rowIndex, false); Debug.Assert(success); if (IsInnerCellOutOfBounds(hti.col, rowIndex)) { return; } success = SetCurrentCellAddressCore(hti.col, rowIndex, !isShiftDown, false, true); Debug.Assert(success); } else if (-1 != this.ptCurrentCell.X) { // Potentially have to give focus back to the current edited cell. bool success = SetCurrentCellAddressCore(this.ptCurrentCell.X, this.ptCurrentCell.Y, false /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false /*throughMouseClick*/); Debug.Assert(success); } } else { Debug.Assert(this.CurrentCellAddress == new Point(-1, -1)); } } else { Debug.Assert(this.selectedBandIndexes.Contains(hti.col)); SetSelectedColumnCore(hti.col, false); } break; } } } finally { this.NoSelectionChangeCount--; } } /// protected virtual void OnColumnHeadersBorderStyleChanged(EventArgs e) { PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); Invalidate(); EventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNHEADERSBORDERSTYLECHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnColumnHeadersDefaultCellStyleChanged(EventArgs e) { if (this.ColumnHeadersVisible) { Invalidate(Rectangle.Union(this.layout.TopLeftHeader, this.layout.ColumnHeaders)); DataGridViewCellStyleChangedEventArgs dgvcsce = e as DataGridViewCellStyleChangedEventArgs; if (dgvcsce == null || dgvcsce.ChangeAffectsPreferredSize) { OnColumnHeadersGlobalAutoSize(); if (this.editingControl != null) { PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/); } } } EventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNHEADERSDEFAULTCELLSTYLECHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } private void OnColumnHeadersGlobalAutoSize() { if (this.noAutoSizeCount > 0) { return; } bool fixedRowHeadersWidth = this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing || this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.DisableResizing; bool fixedColumnHeadersHeight = this.ColumnHeadersHeightSizeMode != DataGridViewColumnHeadersHeightSizeMode.AutoSize; if (!fixedColumnHeadersHeight) { AutoResizeColumnHeadersHeight(fixedRowHeadersWidth, false /*fixedColumnsWidth*/); } if (!fixedRowHeadersWidth) { AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, false /*fixedRowsHeight*/); } // Autosize columns bool columnAutoSized = AutoResizeAllVisibleColumnsInternal(DataGridViewAutoSizeColumnCriteriaInternal.Header, false /*fixedHeight*/); if (!fixedRowHeadersWidth || columnAutoSized) { // Autosize rows AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); } if (!fixedColumnHeadersHeight) { // Second round of column headers autosizing AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/); } if (!fixedRowHeadersWidth) { // Second round of row headers autosizing AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, true /*fixedRowsHeight*/); } // Second round of columns autosizing AutoResizeAllVisibleColumnsInternal(DataGridViewAutoSizeColumnCriteriaInternal.Header, true /*fixedHeight*/); } /// protected virtual void OnColumnHeadersHeightChanged(EventArgs e) { if (this.editingControl != null) { PositionEditingControl(true, false, false); } UpdateMouseEnteredCell(null /*HitTestInfo*/, null /*MouseEventArgs*/); OnColumnHeadersGlobalAutoSize(); EventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNHEADERSHEIGHTCHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnColumnHeadersHeightSizeModeChanged(DataGridViewAutoSizeModeEventArgs e) { if (this.columnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) { if (!e.PreviousModeAutoSized) { // Save current column headers height for later reuse this.cachedColumnHeadersHeight = this.ColumnHeadersHeight; } AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/); } else if (e.PreviousModeAutoSized) { this.ColumnHeadersHeight = this.cachedColumnHeadersHeight; } DataGridViewAutoSizeModeEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNHEADERSHEIGHTSIZEMODECHANGED] as DataGridViewAutoSizeModeEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal void OnColumnHidden(DataGridViewColumn dataGridViewColumn) { Debug.Assert(dataGridViewColumn != null); if (dataGridViewColumn.Displayed) { dataGridViewColumn.DisplayedInternal = false; DataGridViewColumnStateChangedEventArgs dgvrsce = new DataGridViewColumnStateChangedEventArgs(dataGridViewColumn, DataGridViewElementStates.Displayed); OnColumnStateChanged(dgvrsce); } } internal void OnColumnMinimumWidthChanging(DataGridViewColumn dataGridViewColumn, int minimumWidth) { if (dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill && dataGridViewColumn.Width < minimumWidth) { // Force the filled column's width to be minimumWidth try { this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = true; dataGridViewColumn.DesiredMinimumWidth = minimumWidth; PerformLayoutPrivate(false /*useRowShortcut*/, true /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); } finally { dataGridViewColumn.DesiredMinimumWidth = 0; } Debug.Assert(dataGridViewColumn.Width == minimumWidth); } } /// protected virtual void OnColumnMinimumWidthChanged(DataGridViewColumnEventArgs e) { if (e.Column.DataGridView != this) { throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); } if (e.Column.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill) { // Column's width may adjust smaller PerformLayoutPrivate(false /*useRowShortcut*/, true /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); } DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNMINIMUMWIDTHCHANGED] as DataGridViewColumnEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal void OnColumnNameChanged(DataGridViewColumn dataGridViewColumn) { Debug.Assert(dataGridViewColumn != null); DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn); OnColumnNameChanged(dgvce); } /// protected virtual void OnColumnNameChanged(DataGridViewColumnEventArgs e) { if (e.Column.DataGridView != this) { throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); } // Check if the column name is used as is in the column header DataGridViewColumn dataGridViewColumn = e.Column; if (dataGridViewColumn.HasHeaderCell && dataGridViewColumn.HeaderCell.Value is string && String.Compare((string)dataGridViewColumn.HeaderCell.Value, dataGridViewColumn.Name, false, CultureInfo.InvariantCulture) == 0) { InvalidateCellPrivate(dataGridViewColumn.Index, -1); DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaInternal = (DataGridViewAutoSizeColumnCriteriaInternal) dataGridViewColumn.InheritedAutoSizeMode; DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFiltered = autoSizeColumnCriteriaInternal & DataGridViewAutoSizeColumnCriteriaInternal.Header; bool fixedColumnWidth = autoSizeColumnCriteriaFiltered == 0 || !this.ColumnHeadersVisible; if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) { AutoResizeColumnHeadersHeight(dataGridViewColumn.Index, true /*fixedRowHeadersWidth*/, fixedColumnWidth); } if (!fixedColumnWidth) { bool fixedHeight = (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) == 0; AutoResizeColumnInternal(dataGridViewColumn.Index, autoSizeColumnCriteriaInternal, fixedHeight); if (!fixedHeight) { AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); // Second round of column autosizing AutoResizeColumnInternal(dataGridViewColumn.Index, autoSizeColumnCriteriaInternal, true /*fixedHeight*/); } if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) { // Second round of column headers autosizing AutoResizeColumnHeadersHeight(dataGridViewColumn.Index, true /*fixedRowHeadersWidth*/, true /*fixedColumnWidth*/); } } } DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNNAMECHANGED] as DataGridViewColumnEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal void OnColumnRemoved(DataGridViewColumn dataGridViewColumn) { Debug.Assert(dataGridViewColumn != null); Debug.Assert(dataGridViewColumn.DataGridView == null); OnColumnRemoved(new DataGridViewColumnEventArgs(dataGridViewColumn)); } /// protected virtual void OnColumnRemoved(DataGridViewColumnEventArgs e) { DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNREMOVED] as DataGridViewColumnEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } private void OnColumnSelectMouseMove(HitTestInfo hti) { Debug.Assert(hti.col >= 0); Debug.Assert(this.MultiSelect); if (this.ptCurrentCell.X != -1 && hti.col != this.ptCurrentCell.X && !CommitEditForOperation(hti.col, this.ptCurrentCell.Y, true)) { // Return silently if validating/commit/abort failed return; } if (IsColumnOutOfBounds(hti.col)) { return; } this.noSelectionChangeCount++; try { if (this.trackColumnEdge >= 0 && (this.Columns.DisplayInOrder(this.trackColumn, this.trackColumnEdge) || this.trackColumnEdge == this.trackColumn) && this.Columns.DisplayInOrder(this.trackColumnEdge, hti.col)) { DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[this.trackColumnEdge], DataGridViewElementStates.Visible, DataGridViewElementStates.None); Debug.Assert(dataGridViewColumn != null); SelectColumnRange(dataGridViewColumn.Index, hti.col, true); this.trackColumnEdge = hti.col; } else if (this.trackColumnEdge >= 0 && this.Columns.DisplayInOrder(this.trackColumn, this.trackColumnEdge) && this.Columns.DisplayInOrder(hti.col, this.trackColumnEdge) && (this.Columns.DisplayInOrder(this.trackColumn, hti.col) || hti.col == this.trackColumn)) { DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[hti.col], DataGridViewElementStates.Visible, DataGridViewElementStates.None); Debug.Assert(dataGridViewColumn != null); SelectColumnRange(dataGridViewColumn.Index, this.trackColumnEdge, false); this.trackColumnEdge = hti.col; } else if (this.trackColumnEdge == -1 && this.Columns.DisplayInOrder(this.trackColumn, hti.col)) { DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[this.trackColumn], DataGridViewElementStates.Visible, DataGridViewElementStates.None); Debug.Assert(dataGridViewColumn != null); SelectColumnRange(dataGridViewColumn.Index, hti.col, true); this.trackColumnEdge = hti.col; } else if (this.trackColumnEdge >= 0 && (this.Columns.DisplayInOrder(this.trackColumnEdge, this.trackColumn) || this.trackColumnEdge == this.trackColumn) && this.Columns.DisplayInOrder(hti.col, this.trackColumnEdge)) { DataGridViewColumn dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[this.trackColumnEdge], DataGridViewElementStates.Visible, DataGridViewElementStates.None); Debug.Assert(dataGridViewColumn != null); SelectColumnRange(hti.col, dataGridViewColumn.Index, true); this.trackColumnEdge = hti.col; } else if (this.trackColumnEdge >= 0 && this.Columns.DisplayInOrder(this.trackColumnEdge, this.trackColumn) && this.Columns.DisplayInOrder(this.trackColumnEdge, hti.col) && (this.Columns.DisplayInOrder(hti.col, this.trackColumn) || hti.col == this.trackColumn)) { DataGridViewColumn dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[hti.col], DataGridViewElementStates.Visible, DataGridViewElementStates.None); Debug.Assert(dataGridViewColumn != null); SelectColumnRange(this.trackColumnEdge, dataGridViewColumn.Index, false); this.trackColumnEdge = hti.col; } else if (this.trackColumnEdge == -1 && this.Columns.DisplayInOrder(hti.col, this.trackColumn)) { DataGridViewColumn dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[this.trackColumn], DataGridViewElementStates.Visible, DataGridViewElementStates.None); Debug.Assert(dataGridViewColumn != null); SelectColumnRange(hti.col, dataGridViewColumn.Index, true); this.trackColumnEdge = hti.col; } else if (this.trackColumnEdge >= 0 && this.Columns.DisplayInOrder(this.trackColumn, this.trackColumnEdge) && this.Columns.DisplayInOrder(hti.col, this.trackColumn)) { DataGridViewColumn dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[this.trackColumn], DataGridViewElementStates.Visible, DataGridViewElementStates.None); Debug.Assert(dataGridViewColumn != null); SelectColumnRange(dataGridViewColumn.Index, this.trackColumnEdge, false); dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[this.trackColumn], DataGridViewElementStates.Visible, DataGridViewElementStates.None); Debug.Assert(dataGridViewColumn != null); SelectColumnRange(hti.col, dataGridViewColumn.Index, true); this.trackColumnEdge = hti.col; } else if (this.trackColumnEdge >= 0 && this.Columns.DisplayInOrder(this.trackColumn, hti.col) && this.Columns.DisplayInOrder(this.trackColumnEdge, this.trackColumn)) { DataGridViewColumn dataGridViewColumn = this.Columns.GetPreviousColumn(this.Columns[this.trackColumn], DataGridViewElementStates.Visible, DataGridViewElementStates.None); Debug.Assert(dataGridViewColumn != null); SelectColumnRange(this.trackColumnEdge, dataGridViewColumn.Index, false); dataGridViewColumn = this.Columns.GetNextColumn(this.Columns[this.trackColumn], DataGridViewElementStates.Visible, DataGridViewElementStates.None); Debug.Assert(dataGridViewColumn != null); SelectColumnRange(dataGridViewColumn.Index, hti.col, true); this.trackColumnEdge = hti.col; } } finally { this.NoSelectionChangeCount--; } if (this.ptCurrentCell.X != -1 && hti.col != this.ptCurrentCell.X) { if (this.ptCurrentCell.Y == -1 || IsColumnOutOfBounds(hti.col)) { return; } bool success = SetCurrentCellAddressCore(hti.col, this.ptCurrentCell.Y, false /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false /*throughMouseClick*/); Debug.Assert(success); } } private void OnColumnsGlobalAutoSize() { InvalidateData(); if (this.noAutoSizeCount > 0) { return; } // Auto-size columms if needed bool fixedHeight = (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) == 0; bool columnAutoSized = AutoResizeAllVisibleColumnsInternal(DataGridViewAutoSizeColumnCriteriaInternal.AllRows | DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows, fixedHeight); // Autosize rows if needed if (!fixedHeight) { if (columnAutoSized) { AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); } // Second round of columns autosizing AutoResizeAllVisibleColumnsInternal(DataGridViewAutoSizeColumnCriteriaInternal.AllRows | DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows, true /*fixedHeight*/); } } internal void OnColumnSortModeChanged(DataGridViewColumn dataGridViewColumn) { Debug.Assert(dataGridViewColumn != null); DataGridViewColumnEventArgs dgvce = new DataGridViewColumnEventArgs(dataGridViewColumn); OnColumnSortModeChanged(dgvce); } /// protected virtual void OnColumnSortModeChanged(DataGridViewColumnEventArgs e) { if (e.Column.DataGridView != this) { throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); } DataGridViewColumn dataGridViewColumn = e.Column; if (dataGridViewColumn.HasHeaderCell) { if (dataGridViewColumn.SortMode == DataGridViewColumnSortMode.NotSortable || (dataGridViewColumn.SortMode == DataGridViewColumnSortMode.Programmatic && this.SortedColumn == dataGridViewColumn)) { dataGridViewColumn.HeaderCell.SortGlyphDirection = SortOrder.None; // This call will trigger OnSortGlyphDirectionChanged which in turn does // this.sortedColumn = null; and InvalidateCellPrivate(e.Column.Index, -1); } // Potential resizing of the column headers and/or affected column. DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaInternal = (DataGridViewAutoSizeColumnCriteriaInternal) dataGridViewColumn.InheritedAutoSizeMode; DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFiltered = autoSizeColumnCriteriaInternal & DataGridViewAutoSizeColumnCriteriaInternal.Header; bool fixedColumnWidth = autoSizeColumnCriteriaFiltered == 0 || !this.ColumnHeadersVisible; if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) { AutoResizeColumnHeadersHeight(dataGridViewColumn.Index, true /*fixedRowHeadersWidth*/, fixedColumnWidth); } if (!fixedColumnWidth) { bool fixedHeight = (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) == 0; AutoResizeColumnInternal(dataGridViewColumn.Index, autoSizeColumnCriteriaInternal, fixedHeight); if (!fixedHeight) { AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); // Second round of column autosizing AutoResizeColumnInternal(dataGridViewColumn.Index, autoSizeColumnCriteriaInternal, true /*fixedHeight*/); } if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) { // Second round of column headers autosizing AutoResizeColumnHeadersHeight(dataGridViewColumn.Index, true /*fixedRowHeadersWidth*/, true /*fixedColumnWidth*/); } } } DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNSORTMODECHANGED] as DataGridViewColumnEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnColumnStateChanged(DataGridViewColumnStateChangedEventArgs e) { // column.Frozen | .Visible changed - this may require a complete re-layout of the control DataGridViewColumn dataGridViewColumn = e.Column; switch (e.StateChanged) { // At this point we assume that only the Selected state has an influence on the rendering of the column. // If there is a customer scenario where another state has an influence, the dev must invalidate the column by hand. // case DataGridViewElementStates.ReadOnly: // case DataGridViewElementStates.Resizable: case DataGridViewElementStates.Selected: if (dataGridViewColumn.Visible && this.inBulkPaintCount == 0) { InvalidateColumnInternal(dataGridViewColumn.Index); } break; case DataGridViewElementStates.Frozen: if (dataGridViewColumn.Visible) { if (dataGridViewColumn.Frozen) { // visible column became frozen if (this.horizontalOffset >= dataGridViewColumn.Thickness) { Debug.Assert(this.Columns.DisplayInOrder(dataGridViewColumn.Index, this.displayedBandsInfo.FirstDisplayedScrollingCol)); this.horizontalOffset -= dataGridViewColumn.Thickness; } else { this.horizontalOffset = this.negOffset = 0; } } else { // column was unfrozen - make it the first visible scrolling column if there is room this.horizontalOffset = this.negOffset = 0; } if (this.horizScrollBar.Enabled) { this.horizScrollBar.Value = this.horizontalOffset; } // UsedFillWeight values need to be updated this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = true; PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, true /*repositionEditingControl*/); Invalidate(); } break; case DataGridViewElementStates.Visible: if (!dataGridViewColumn.Visible && dataGridViewColumn.Displayed) { // Displayed column becomes invisible. Turns off the Displayed state. dataGridViewColumn.DisplayedInternal = false; } // UsedFillWeight values need to be updated this.dataGridViewState2[DATAGRIDVIEWSTATE2_usedFillWeightsDirty] = true; PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, true /*repositionEditingControl*/); bool autoSizeRows = (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0 || ((((DataGridViewAutoSizeRowsModeInternal) this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.Header) != 0 && this.RowHeadersVisible); bool autoSizeColumn = false; DataGridViewAutoSizeColumnMode autoSizeColumnMode = dataGridViewColumn.InheritedAutoSizeMode; Debug.Assert(autoSizeColumnMode != DataGridViewAutoSizeColumnMode.NotSet); if (autoSizeColumnMode != DataGridViewAutoSizeColumnMode.None && autoSizeColumnMode != DataGridViewAutoSizeColumnMode.Fill) { // Column autosizes int width = dataGridViewColumn.ThicknessInternal; if (dataGridViewColumn.Visible) { // Cache column's width before potential autosizing occurs dataGridViewColumn.CachedThickness = width; AutoResizeColumnInternal(dataGridViewColumn.Index, (DataGridViewAutoSizeColumnCriteriaInternal)autoSizeColumnMode, !autoSizeRows /*fixedHeight*/); autoSizeColumn = true; } else if (width != dataGridViewColumn.CachedThickness) { // Columns that are made invisible in the collection take their non-autosized width dataGridViewColumn.ThicknessInternal = Math.Max(dataGridViewColumn.MinimumWidth, dataGridViewColumn.CachedThickness); } } if (autoSizeRows) { if (dataGridViewColumn.Visible) { AdjustExpandingRows(dataGridViewColumn.Index, true /*fixedWidth*/); } else { AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); } if (autoSizeColumn) { // Second round of column autosizing AutoResizeColumnInternal(dataGridViewColumn.Index, (DataGridViewAutoSizeColumnCriteriaInternal)autoSizeColumnMode, true /*fixedHeight*/); } } else { Invalidate(); } break; } DataGridViewColumnStateChangedEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNSTATECHANGED] as DataGridViewColumnStateChangedEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } if (e.StateChanged == DataGridViewElementStates.ReadOnly && dataGridViewColumn.Index == this.ptCurrentCell.X && !this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange]) { VerifyImeRestrictedModeChanged(); if (!dataGridViewColumn.ReadOnly && ColumnEditable(this.ptCurrentCell.X) && (this.Rows.GetRowState(this.ptCurrentCell.Y) & DataGridViewElementStates.ReadOnly) == 0 && !this.IsCurrentCellInEditMode && (this.EditMode == DataGridViewEditMode.EditOnEnter || (this.EditMode != DataGridViewEditMode.EditProgrammatically && this.CurrentCellInternal.EditType == null))) { // Current column becomes read/write. Enter editing mode. BeginEditInternal(true /*selectAll*/); } } } internal void OnColumnToolTipTextChanged(DataGridViewColumn dataGridViewColumn) { OnColumnToolTipTextChanged(new DataGridViewColumnEventArgs(dataGridViewColumn)); } /// protected virtual void OnColumnToolTipTextChanged(DataGridViewColumnEventArgs e) { if (e.Column.DataGridView != this) { throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); } DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNTOOLTIPTEXTCHANGED] as DataGridViewColumnEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnColumnWidthChanged(DataGridViewColumnEventArgs e) { if (e.Column.DataGridView != this) { throw new ArgumentException(SR.GetString(SR.DataGridView_ColumnDoesNotBelongToDataGridView)); } this.Columns.InvalidateCachedColumnsWidths(); // don't do any layout logic if the handle was not created already if (e.Column.Visible && this.IsHandleCreated) { PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); Rectangle rightArea = this.layout.Data; if (this.layout.ColumnHeadersVisible) { rightArea = Rectangle.Union(rightArea, this.layout.ColumnHeaders); } else if (this.SingleHorizontalBorderAdded) { rightArea.Y--; rightArea.Height++; } if (rightArea.Width > 0 && rightArea.Height > 0) { int leftEdge = GetColumnXFromIndex(e.Column.Index); if (this.RightToLeftInternal) { rightArea.Width -= rightArea.Right - leftEdge; } else { rightArea.Width -= leftEdge - rightArea.X; rightArea.X = leftEdge; } if (rightArea.Width > 0 && rightArea.Height > 0) { Invalidate(rightArea); } } if (this.editingControl != null) { PositionEditingControl(this.ptCurrentCell.X != e.Column.Index, true, false); } UpdateMouseEnteredCell(null /*HitTestInfo*/, null /*MouseEventArgs*/); if (this.AutoSize) { LayoutTransaction.DoLayout(this.ParentInternal, this, PropertyNames.Columns); } } DataGridViewColumnEventHandler eh = this.Events[EVENT_DATAGRIDVIEWCOLUMNWIDTHCHANGED] as DataGridViewColumnEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } if (!this.InAdjustFillingColumns) { // Autosize rows and column headers if needed OnColumnGlobalAutoSize(e.Column.Index); } } internal void OnCommonCellContentClick(int columnIndex, int rowIndex, bool doubleClick) { if (this.ptMouseDownCell.X == -2 || (this.dataGridViewState2[DATAGRIDVIEWSTATE2_cellMouseDownInContentBounds] && this.ptMouseDownCell.X == columnIndex && this.ptMouseDownCell.Y == rowIndex && (this.ptMouseDownCell.X == -1 || this.ptMouseDownCell.Y == -1 || (columnIndex == this.ptCurrentCell.X && rowIndex == this.ptCurrentCell.Y)))) { DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(columnIndex, rowIndex); if (doubleClick) { OnCellContentDoubleClick(dgvce); } else { OnCellContentClick(dgvce); } } } /// protected virtual void OnCurrentCellChanged(EventArgs e) { VerifyImeRestrictedModeChanged(); EventHandler eh = this.Events[EVENT_DATAGRIDVIEWCURRENTCELLCHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnCurrentCellDirtyStateChanged(EventArgs e) { if (this.RowHeadersVisible && this.ShowEditingIcon) { // Force the pencil to appear in the row header Debug.Assert(this.ptCurrentCell.Y >= 0); InvalidateCellPrivate(-1, this.ptCurrentCell.Y); } if (this.IsCurrentCellDirty && this.newRowIndex == this.ptCurrentCell.Y) { Debug.Assert(this.newRowIndex != -1); Debug.Assert(this.AllowUserToAddRowsInternal); // First time the 'new' row gets edited. // It becomes a regular row and a new 'new' row is appened. this.newRowIndex = -1; AddNewRow(true /*createdByEditing*/); } EventHandler eh = this.Events[EVENT_DATAGRIDVIEWCURRENTCELLDIRTYSTATECHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected override void OnCursorChanged(EventArgs e) { base.OnCursorChanged(e); if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_ignoreCursorChange]) { this.oldCursor = this.Cursor; } } internal void OnDataBindingComplete(ListChangedType listChangedType) { OnDataBindingComplete(new DataGridViewBindingCompleteEventArgs(listChangedType)); } /// protected virtual void OnDataBindingComplete(DataGridViewBindingCompleteEventArgs e) { DataGridViewBindingCompleteEventHandler eh = this.Events[EVENT_DATAGRIDVIEWDATABINDINGCOMPLETE] as DataGridViewBindingCompleteEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// [ SuppressMessage("Microsoft.Globalization", "CA1300:SpecifyMessageBoxOptions") // Not using options when RightToLeft == false ] protected virtual void OnDataError(bool displayErrorDialogIfNoHandler, DataGridViewDataErrorEventArgs e) { DataGridViewDataErrorEventHandler eh = this.Events[EVENT_DATAGRIDVIEWDATAERROR] as DataGridViewDataErrorEventHandler; if (!this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { if (eh == null) { if (displayErrorDialogIfNoHandler) { string errorText; if (e.Exception == null) { errorText = SR.GetString(SR.DataGridView_ErrorMessageText_NoException); } else { errorText = SR.GetString(SR.DataGridView_ErrorMessageText_WithException, e.Exception); } if (this.RightToLeftInternal) { MessageBox.Show(errorText, SR.GetString(SR.DataGridView_ErrorMessageCaption), MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.RightAlign | MessageBoxOptions.RtlReading); } else { MessageBox.Show(errorText, SR.GetString(SR.DataGridView_ErrorMessageCaption), MessageBoxButtons.OK, MessageBoxIcon.Error); } CorrectFocus(true /*onlyIfGridHasFocus*/); } } else { eh(this, e); CorrectFocus(true /*onlyIfGridHasFocus*/); } } } internal void OnDataErrorInternal(DataGridViewDataErrorEventArgs e) { OnDataError(!this.DesignMode /*displayErrorDialogIfNoHandler*/, e); } internal void OnDataGridViewElementStateChanged(DataGridViewElement element, int index, DataGridViewElementStates elementState) { DataGridViewColumn dataGridViewColumn = element as DataGridViewColumn; if (dataGridViewColumn != null) { DataGridViewColumnStateChangedEventArgs dgvcsce = new DataGridViewColumnStateChangedEventArgs(dataGridViewColumn, elementState); OnColumnStateChanged(dgvcsce); } else { DataGridViewRow dataGridViewRow = element as DataGridViewRow; if (dataGridViewRow != null) { DataGridViewRowStateChangedEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWSTATECHANGED] as DataGridViewRowStateChangedEventHandler; if (eh != null && dataGridViewRow.DataGridView != null && dataGridViewRow.Index == -1) { dataGridViewRow = this.Rows[index]; } DataGridViewRowStateChangedEventArgs dgvrsce = new DataGridViewRowStateChangedEventArgs(dataGridViewRow, elementState); OnRowStateChanged(dataGridViewRow.Index == -1 ? index : dataGridViewRow.Index, dgvrsce); } else { DataGridViewCell dataGridViewCell = element as DataGridViewCell; if (dataGridViewCell != null) { DataGridViewCellStateChangedEventArgs dgvcsce = new DataGridViewCellStateChangedEventArgs(dataGridViewCell, elementState); OnCellStateChanged(dgvcsce); } } } if ((elementState & DataGridViewElementStates.Selected) == DataGridViewElementStates.Selected) { if (this.noSelectionChangeCount > 0) { this.dataGridViewState2[DATAGRIDVIEWSTATE2_raiseSelectionChanged] = true; } else { OnSelectionChanged(EventArgs.Empty); } } } internal void OnDataGridViewElementStateChanging(DataGridViewElement element, int index, DataGridViewElementStates elementState) { DataGridViewColumn dataGridViewColumn = element as DataGridViewColumn; if (dataGridViewColumn != null) { // column.Frozen | .Visible | .ReadOnly changing switch (elementState) { case DataGridViewElementStates.Frozen: case DataGridViewElementStates.Visible: if (elementState == DataGridViewElementStates.Visible) { if (!dataGridViewColumn.Visible && dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.ColumnHeader && !this.ColumnHeadersVisible) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotMakeAutoSizedColumnVisible)); } else if (!dataGridViewColumn.Visible && dataGridViewColumn.Frozen && dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill) { // alternative: throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotMakeAutoFillColumnVisible)); // DataGridView_CannotMakeAutoFillColumnVisible=The column cannot be made visible because its autosizing mode is Fill and it is frozen. // Removing the Fill auto size mode when frozen column becomes visible (instead of throwing an exception) dataGridViewColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.None; } else if (dataGridViewColumn.Visible && this.ptCurrentCell.X == dataGridViewColumn.Index) { // Column of the current cell is made invisible. Trying to reset the current cell. May throw an exception. ResetCurrentCell(); // [....]: Should the current cell be set to some cell after the operation? } } if (elementState == DataGridViewElementStates.Frozen && !dataGridViewColumn.Frozen && dataGridViewColumn.Visible && dataGridViewColumn.InheritedAutoSizeMode == DataGridViewAutoSizeColumnMode.Fill) { // Removing the Fill auto size mode when visible column becomes frozen (instead of throwing an exception) dataGridViewColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.None; } CorrectColumnFrozenStates(dataGridViewColumn, elementState == DataGridViewElementStates.Frozen); break; case DataGridViewElementStates.ReadOnly: if (this.ptCurrentCell.X == dataGridViewColumn.Index && this.IsCurrentCellInEditMode && !dataGridViewColumn.ReadOnly && !this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange]) { Debug.Assert(!this.ReadOnly); // Column becomes read-only. Exit editing mode. if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit, DataGridViewValidateCellInternal.Always /*validateCell*/, false /*fireCellLeave*/, false /*fireCellEnter*/, false /*fireRowLeave*/, false /*fireRowEnter*/, false /*fireLeave*/, true /*keepFocus*/, false /*resetCurrentCell*/, false /*resetAnchorCell*/)) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CommitFailedCannotCompleteOperation)); } } break; default: Debug.Fail("Unexpected DataGridViewElementStates param in DataGridView.OnDataGridViewElementStateChanging"); break; } } else { DataGridViewRow dataGridViewRow = element as DataGridViewRow; if (dataGridViewRow != null) { // row.Frozen | .Visible | .ReadOnly changing int rowIndex = ((dataGridViewRow.Index > -1) ? dataGridViewRow.Index : index); switch (elementState) { case DataGridViewElementStates.Frozen: case DataGridViewElementStates.Visible: if (elementState == DataGridViewElementStates.Visible && this.ptCurrentCell.Y == rowIndex) { Debug.Assert((this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Visible) != 0); // Row of the current cell is made invisible. if (this.DataSource != null) { Debug.Assert(this.dataConnection != null); Debug.Assert(this.dataConnection.CurrencyManager != null); Debug.Assert(this.dataConnection.CurrencyManager.Position == this.ptCurrentCell.Y); // the row associated with the currency manager's position cannot be made invisble. throw new InvalidOperationException(SR.GetString(SR.DataGridView_CurrencyManagerRowCannotBeInvisible)); } // Trying to reset the current cell. May throw an exception. ResetCurrentCell(); // [....]: Should the current cell be set to some cell after the operation? } CorrectRowFrozenStates(dataGridViewRow, rowIndex, elementState == DataGridViewElementStates.Frozen); break; case DataGridViewElementStates.ReadOnly: if (this.ptCurrentCell.Y == rowIndex && (this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.ReadOnly) == 0 && !this.ReadOnly && this.IsCurrentCellInEditMode && !this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange]) { // Row becomes read-only. Exit editing mode. if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit, DataGridViewValidateCellInternal.Always /*validateCell*/, false /*fireCellLeave*/, false /*fireCellEnter*/, false /*fireRowLeave*/, false /*fireRowEnter*/, false /*fireLeave*/, true /*keepFocus*/, false /*resetCurrentCell*/, false /*resetAnchorCell*/)) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CommitFailedCannotCompleteOperation)); } } break; default: Debug.Fail("Unexpected DataGridViewElementStates param in DataGridView.OnDataGridViewElementStateChanging"); break; } } else { DataGridViewCell dataGridViewCell = element as DataGridViewCell; if (dataGridViewCell != null) { // cell.ReadOnly changing switch (elementState) { case DataGridViewElementStates.ReadOnly: if (this.ptCurrentCell.X == dataGridViewCell.ColumnIndex && this.ptCurrentCell.Y == dataGridViewCell.RowIndex && this.IsCurrentCellInEditMode && !dataGridViewCell.ReadOnly && !this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange]) { Debug.Assert(!this.Columns[dataGridViewCell.ColumnIndex].ReadOnly); Debug.Assert(!this.Rows[dataGridViewCell.RowIndex].ReadOnly); Debug.Assert(!this.ReadOnly); // Current cell becomes read-only. Exit editing mode. if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit, DataGridViewValidateCellInternal.Always /*validateCell*/, false /*fireCellLeave*/, false /*fireCellEnter*/, false /*fireRowLeave*/, false /*fireRowEnter*/, false /*fireLeave*/, true /*keepFocus*/, false /*resetCurrentCell*/, false /*resetAnchorCell*/)) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CommitFailedCannotCompleteOperation)); } } break; default: Debug.Fail("Unexpected DataGridViewElementStates param in DataGridView.OnDataGridViewElementStateChanging"); break; } } else { Debug.Fail("Unexpected DataGridViewElement type in DataGridView.OnDataGridViewElementStateChanging"); } } } } /// protected virtual void OnDataMemberChanged(EventArgs e) { RefreshColumnsAndRows(); EventHandler eh = this.Events[EVENT_DATAGRIDVIEWDATAMEMBERCHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } if (this.dataConnection != null && this.dataConnection.CurrencyManager != null) { OnDataBindingComplete(ListChangedType.Reset); } } /// protected virtual void OnDataSourceChanged(EventArgs e) { RefreshColumnsAndRows(); InvalidateRowHeights(); EventHandler eh = this.Events[EVENT_DATAGRIDVIEWDATASOURCECHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } if (this.dataConnection != null && this.dataConnection.CurrencyManager != null) { OnDataBindingComplete(ListChangedType.Reset); } } /// protected virtual void OnDefaultCellStyleChanged(EventArgs e) { DataGridViewCellStyleChangedEventArgs dgvcsce = e as DataGridViewCellStyleChangedEventArgs; if (dgvcsce != null && !dgvcsce.ChangeAffectsPreferredSize) { Invalidate(); } else { OnGlobalAutoSize(); if (this.editingControl != null) { PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/); } } EventHandler eh = this.Events[EVENT_DATAGRIDVIEWDEFAULTCELLSTYLECHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnDefaultValuesNeeded(DataGridViewRowEventArgs e) { DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWDEFAULTVALUESNEEDED] as DataGridViewRowEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected override void OnDoubleClick(EventArgs e) { base.OnDoubleClick(e); if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls] && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { MouseEventArgs me = e as MouseEventArgs; if (me != null) { HitTestInfo hti = HitTest(me.X, me.Y); if (hti.Type != DataGridViewHitTestType.None && hti.Type != DataGridViewHitTestType.HorizontalScrollBar && hti.Type != DataGridViewHitTestType.VerticalScrollBar && me.Button == MouseButtons.Left) { OnCellDoubleClick(new DataGridViewCellEventArgs(hti.col, hti.row)); } } } } /// protected virtual void OnEditingControlShowing(DataGridViewEditingControlShowingEventArgs e) { DataGridViewEditingControlShowingEventHandler eh = this.Events[EVENT_DATAGRIDVIEWEDITINGCONTROLSHOWING] as DataGridViewEditingControlShowingEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnEditModeChanged(EventArgs e) { if (this.Focused && this.EditMode == DataGridViewEditMode.EditOnEnter && this.ptCurrentCell.X > -1 && !this.IsCurrentCellInEditMode) { // New edit mode is EditOnEnter and there is an editable current cell, try to go to edit mode. BeginEditInternal(true /*selectAll*/); } EventHandler eh = this.Events[EVENT_DATAGRIDVIEWEDITMODECHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected override void OnEnabledChanged(EventArgs e) { base.OnEnabledChanged(e); if (GetAnyDisposingInHierarchy()) { return; } if (this.IsHandleCreated && this.Enabled) { if (this.vertScrollBar != null && this.vertScrollBar.Visible) { this.vertScrollBar.Enabled = true; } if (this.horizScrollBar != null && this.horizScrollBar.Visible) { this.horizScrollBar.Enabled = true; } } } /// protected override void OnEnter(EventArgs e) { if (this.editingControl != null && this.editingControl.ContainsFocus) { return; } base.OnEnter(e); // vsw 453314: there are cases when a control is on the designer and it still receives the OnEnter event. // Guard against this. if (this.DesignMode) { return; } this.dataGridViewState1[DATAGRIDVIEWSTATE1_leavingWithTabKey] = false; if (this.ptCurrentCell.X > -1) { DataGridViewCell dataGridViewCell = null; // We're re-entering a row we already entered earlier. The first time we entered the row, // the DataGridView didn't have focus. This time it does. We don't want to recreate the new row a second time. OnRowEnter(ref dataGridViewCell, this.ptCurrentCell.X, this.ptCurrentCell.Y, false /*canCreateNewRow*/, false /*validationFailureOccurred*/); if (this.ptCurrentCell.X == -1) { return; } OnCellEnter(ref dataGridViewCell, this.ptCurrentCell.X, this.ptCurrentCell.Y); } else if (!this.dataGridViewOper[DATAGRIDVIEWOPER_inMouseDown]) { // Focus is given to the DataGridView control via a the TAB key. MakeFirstDisplayedCellCurrentCell(true /*includeNewRow*/); } if (this.ptCurrentCell.X > -1 && !this.IsCurrentCellInEditMode) { if (this.EditMode == DataGridViewEditMode.EditOnEnter || (this.EditMode != DataGridViewEditMode.EditProgrammatically && this.CurrentCellInternal.EditType == null)) { BeginEditInternal(true /*selectAll*/); if (this.ptCurrentCell.X > -1 && this.CurrentCellInternal.EditType == null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inMouseDown]) { // The current cell does not have an edit type so the data grid view did not put an edit control on top. // We should invalidate the current cell so that the dataGridView repaints the focus around the current cell. // But do that only if the dataGridView did not get the focus via mouse. InvalidateCellPrivate(this.ptCurrentCell.X /*columnIndex*/, this.ptCurrentCell.Y /*rowIndex*/); } } else if (!this.dataGridViewOper[DATAGRIDVIEWOPER_inMouseDown]) { // When the focus is given to the DataGridView control via mouse // the dataGridView changes selection so it invalidates the current cell anyway // // In any other case Invalidate the current cell so the dataGridView repaints the focus around the current cell InvalidateCellPrivate(this.ptCurrentCell.X /*columnIndex*/, this.ptCurrentCell.Y /*rowIndex*/); } } } /// protected override void OnFontChanged(EventArgs e) { base.OnFontChanged(e); if (GetAnyDisposingInHierarchy ()) { return; } // Change may be due to an ambient font change. if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientColumnHeadersFont] && this.ColumnHeadersDefaultCellStyle.Font != base.Font) { this.ColumnHeadersDefaultCellStyle.Font = base.Font; this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientColumnHeadersFont] = true; this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = true; OnColumnHeadersDefaultCellStyleChanged(this.CellStyleChangedEventArgs); } if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientRowHeadersFont] && this.RowHeadersDefaultCellStyle.Font != base.Font) { this.RowHeadersDefaultCellStyle.Font = base.Font; this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientRowHeadersFont] = true; this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = true; OnRowHeadersDefaultCellStyleChanged(this.CellStyleChangedEventArgs); } if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientFont] && this.DefaultCellStyle.Font != base.Font) { this.DefaultCellStyle.Font = base.Font; this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientFont] = true; this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = true; OnDefaultCellStyleChanged(this.CellStyleChangedEventArgs); } } /// protected override void OnForeColorChanged(EventArgs e) { base.OnForeColorChanged(e); if (GetAnyDisposingInHierarchy()) { return; } // Change may be due to an ambient forecolor change. if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientForeColor] && this.DefaultCellStyle.ForeColor != base.ForeColor) { this.DefaultCellStyle.ForeColor = base.ForeColor; this.dataGridViewState1[DATAGRIDVIEWSTATE1_ambientForeColor] = true; this.CellStyleChangedEventArgs.ChangeAffectsPreferredSize = false; OnDefaultCellStyleChanged(this.CellStyleChangedEventArgs); } } private void OnGlobalAutoSize() { Invalidate(); if (this.noAutoSizeCount > 0) { return; } bool autoSizeRowHeaders = this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.EnableResizing && this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.DisableResizing; if (autoSizeRowHeaders) { AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, this.ColumnHeadersHeightSizeMode != DataGridViewColumnHeadersHeightSizeMode.AutoSize /*fixedColumnHeadersHeight*/, this.autoSizeRowsMode == DataGridViewAutoSizeRowsMode.None /*fixedRowsHeight*/); } if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) { AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, false /*fixedColumnsWidth*/); } if (this.autoSizeRowsMode != DataGridViewAutoSizeRowsMode.None) { AdjustShrinkingRows(this.autoSizeRowsMode, false /*fixedWidth*/, true /*internalAutosizing*/); } AutoResizeAllVisibleColumnsInternal(DataGridViewAutoSizeColumnCriteriaInternal.Header | DataGridViewAutoSizeColumnCriteriaInternal.AllRows | DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows, true /*fixedHeight*/); if (autoSizeRowHeaders && (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize || this.autoSizeRowsMode != DataGridViewAutoSizeRowsMode.None)) { // Second round of row headers autosizing AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, true /*fixedRowsHeight*/); } if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) { // Second round of column headers autosizing AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/); } if (this.autoSizeRowsMode != DataGridViewAutoSizeRowsMode.None) { // Second round of rows autosizing AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); } } /// protected override void OnGotFocus(EventArgs e) { base.OnGotFocus(e); if (this.ptCurrentCell.X != -1) { InvalidateCell(this.ptCurrentCell.X, this.ptCurrentCell.Y); } // Inform Accessibility that our current cell contains the focus. if (!this.dataGridViewOper[DATAGRIDVIEWOPER_inCurrentCellChange] && (!this.dataGridViewOper[DATAGRIDVIEWOPER_inEndEdit] || this.EditMode != DataGridViewEditMode.EditOnEnter) && (!this.dataGridViewOper[DATAGRIDVIEWOPER_inMouseDown] || this.EditMode != DataGridViewEditMode.EditOnEnter) && this.ptCurrentCell.X > -1) { // The name is misleading ( the current cell did not change ). // However, AccessibilityNotifyCurrentCellChanged is now a public method so we can't change its name // to better reflect its purpose. AccessibilityNotifyCurrentCellChanged(this.ptCurrentCell); } } /// protected virtual void OnGridColorChanged(EventArgs e) { InvalidateInside(); EventHandler eh = this.Events[EVENT_DATAGRIDVIEWGRIDCOLORCHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected override void OnHandleCreated(EventArgs e) { base.OnHandleCreated(e); if (this.layout.dirty) { PerformLayoutPrivate(false /*useRowShortcut*/, true /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); } if (this.ptCurrentCell.X == -1) { MakeFirstDisplayedCellCurrentCell(false /*includeNewRow*/); } else { ScrollIntoView(this.ptCurrentCell.X, this.ptCurrentCell.Y, false /*forCurrentCellChange*/); } // do the AutoSize work that was skipped during initialization if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_autoSizedWithoutHandle]) { this.dataGridViewState2[DATAGRIDVIEWSTATE2_autoSizedWithoutHandle] = false; OnGlobalAutoSize(); } SystemEvents.UserPreferenceChanged += new UserPreferenceChangedEventHandler(this.OnUserPreferenceChanged); } /// protected override void OnHandleDestroyed(EventArgs e) { SystemEvents.UserPreferenceChanged -= new UserPreferenceChangedEventHandler(this.OnUserPreferenceChanged); base.OnHandleDestroyed(e); } internal void OnInsertedColumn_PreNotification(DataGridViewColumn dataGridViewColumn) { // Fix the OldFirstDisplayedScrollingCol this.displayedBandsInfo.CorrectColumnIndexAfterInsertion(dataGridViewColumn.Index, 1); // Fix the Index of all following columns CorrectColumnIndexesAfterInsertion(dataGridViewColumn, 1); // Same effect as appending a column OnAddedColumn(dataGridViewColumn); } internal void OnInsertedColumn_PostNotification(Point newCurrentCell) { // Update current cell if needed if (newCurrentCell.X != -1) { Debug.Assert(this.ptCurrentCell.X == -1); bool success = SetAndSelectCurrentCellAddress(newCurrentCell.X, newCurrentCell.Y, true, false, false, false /*clearSelection*/, this.Columns.GetColumnCount(DataGridViewElementStates.Visible) == 1 /*forceCurrentCellSelection*/); Debug.Assert(success); } } internal void OnInsertedRow_PreNotification(int rowIndex, int insertionCount) { Debug.Assert(rowIndex >= 0); Debug.Assert(insertionCount > 0); // Fix the OldFirstDisplayedScrollingRow this.displayedBandsInfo.CorrectRowIndexAfterInsertion(rowIndex, insertionCount); // Fix the Index of all following rows CorrectRowIndexesAfterInsertion(rowIndex, insertionCount); // Next, same effect as adding a row OnAddedRow_PreNotification(rowIndex); } internal void OnInsertedRow_PostNotification(int rowIndex, Point newCurrentCell, bool lastInsertion) { Debug.Assert(rowIndex >= 0); // Same effect as adding a row OnAddedRow_PostNotification(rowIndex); // Update current cell if needed if (lastInsertion && newCurrentCell.Y != -1) { Debug.Assert(this.ptCurrentCell.X == -1); bool success = SetAndSelectCurrentCellAddress(newCurrentCell.X, newCurrentCell.Y, true, false, false, false /*clearSelection*/, this.Rows.GetRowCount(DataGridViewElementStates.Visible) == 1 /*forceCurrentCellSelection*/); Debug.Assert(success); } } internal void OnInsertedRows_PreNotification(int rowIndex, DataGridViewRow[] dataGridViewRows) { Debug.Assert(rowIndex >= 0); Debug.Assert(dataGridViewRows != null); Debug.Assert(dataGridViewRows.Length > 0); // Fix the OldFirstDisplayedScrollingRow this.displayedBandsInfo.CorrectRowIndexAfterInsertion(rowIndex, dataGridViewRows.Length); // Fix the Index of all following rows CorrectRowIndexesAfterInsertion(rowIndex, dataGridViewRows.Length); // Next, same effect as adding the rows OnAddedRows_PreNotification(dataGridViewRows); } internal void OnInsertedRows_PostNotification(DataGridViewRow[] dataGridViewRows, Point newCurrentCell) { Debug.Assert(dataGridViewRows != null); Debug.Assert(dataGridViewRows.Length > 0); // Same effect as adding the rows OnAddedRows_PostNotification(dataGridViewRows); // Update current cell if needed if (newCurrentCell.Y != -1) { Debug.Assert(this.ptCurrentCell.X == -1); bool success = SetAndSelectCurrentCellAddress(newCurrentCell.X, newCurrentCell.Y, true, false, false, false /*clearSelection*/, false /*forceCurrentCellSelection*/); Debug.Assert(success); } } internal void OnInsertingColumn(int columnIndexInserted, DataGridViewColumn dataGridViewColumn, out Point newCurrentCell) { Debug.Assert(dataGridViewColumn != null); if (dataGridViewColumn.DataGridView != null) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_ColumnAlreadyBelongsToDataGridView)); } if (!this.InInitialization && dataGridViewColumn.SortMode == DataGridViewColumnSortMode.Automatic && (this.SelectionMode == DataGridViewSelectionMode.FullColumnSelect || this.SelectionMode == DataGridViewSelectionMode.ColumnHeaderSelect)) { throw new InvalidOperationException(SR.GetString(SR.DataGridViewColumn_SortModeAndSelectionModeClash, DataGridViewColumnSortMode.Automatic.ToString(), this.SelectionMode.ToString())); } if (dataGridViewColumn.Visible) { // Note that dataGridViewColumn.DataGridView is set later on, so dataGridViewColumn.InheritedAutoSizeMode should not be used // Make sure the column does not autosize based only on header while column headers are invisible if (!this.ColumnHeadersVisible && (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.ColumnHeader || (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.NotSet && this.AutoSizeColumnsMode == DataGridViewAutoSizeColumnsMode.ColumnHeader))) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddAutoSizedColumn)); } // Make sure the column is not frozen and auto fills if (dataGridViewColumn.Frozen && (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.Fill || (dataGridViewColumn.AutoSizeMode == DataGridViewAutoSizeColumnMode.NotSet && this.AutoSizeColumnsMode == DataGridViewAutoSizeColumnsMode.Fill))) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddAutoFillColumn)); } } // check for correctness of frozen state - throws exception if state is incorrect. CorrectColumnFrozenState(dataGridViewColumn, columnIndexInserted); // Reset current cell if there is one, no matter the relative position of the columns involved if (this.ptCurrentCell.X != -1) { newCurrentCell = new Point(columnIndexInserted <= this.ptCurrentCell.X ? this.ptCurrentCell.X + 1 : this.ptCurrentCell.X, this.ptCurrentCell.Y); ResetCurrentCell(); } else { newCurrentCell = new Point(-1, -1); } // prepare the existing rows by inserting cells of correct type if (this.Rows.Count > 0) { // Only require a default cell type when there are rows to fill if (dataGridViewColumn.CellType == null) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAddUntypedColumn)); } if (dataGridViewColumn.CellTemplate.DefaultNewRowValue != null && this.newRowIndex != -1) { // New row needs to be unshared before addition of new cell with a Value != null DataGridViewRow newRow = this.Rows[this.newRowIndex]; } int newColumnCount = this.Columns.Count + 1; try { for (int rowIndex = 0; rowIndex < this.Rows.Count; rowIndex++) { DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex); if (dataGridViewRow.Cells.Count < newColumnCount) { DataGridViewCell dataGridViewCellNew = (DataGridViewCell)dataGridViewColumn.CellTemplate.Clone(); dataGridViewRow.Cells.InsertInternal(columnIndexInserted, dataGridViewCellNew); if (rowIndex == this.newRowIndex) { dataGridViewCellNew.Value = dataGridViewCellNew.DefaultNewRowValue; } dataGridViewCellNew.DataGridViewInternal = this; dataGridViewCellNew.OwningRowInternal = dataGridViewRow; dataGridViewCellNew.OwningColumnInternal = dataGridViewColumn; } } } catch { // An error occurred while inserting the cells. Revert all the insertions. for (int rowIndex = 0; rowIndex < this.Rows.Count; rowIndex++) { DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex); if (dataGridViewRow.Cells.Count == newColumnCount) { dataGridViewRow.Cells.RemoveAtInternal(columnIndexInserted); } else { Debug.Assert(dataGridViewRow.Cells.Count < newColumnCount); break; } } throw; } } // Update the indexes of selected columns to compensate for the insertion of this column switch (this.SelectionMode) { case DataGridViewSelectionMode.FullColumnSelect: case DataGridViewSelectionMode.ColumnHeaderSelect: int columnEntries = this.selectedBandIndexes.Count; int columnEntry = 0; while (columnEntry < columnEntries) { int columnIndex = this.selectedBandIndexes[columnEntry]; if (columnIndexInserted <= columnIndex) { this.selectedBandIndexes[columnEntry] = columnIndex + 1; } columnEntry++; } if (this.selectedBandSnapshotIndexes != null) { columnEntries = this.selectedBandSnapshotIndexes.Count; columnEntry = 0; while (columnEntry < columnEntries) { int columnIndex = this.selectedBandSnapshotIndexes[columnEntry]; if (columnIndexInserted <= columnIndex) { this.selectedBandSnapshotIndexes[columnEntry] = columnIndex + 1; } columnEntry++; } } break; } } internal void OnInsertingRow(int rowIndexInserted, DataGridViewRow dataGridViewRow, DataGridViewElementStates rowState, ref Point newCurrentCell, bool firstInsertion, int insertionCount, bool force) { // Reset the current cell's address if it's after the inserted row. if (firstInsertion) { if (this.ptCurrentCell.Y != -1 && rowIndexInserted <= this.ptCurrentCell.Y) { newCurrentCell = new Point(this.ptCurrentCell.X, this.ptCurrentCell.Y + insertionCount); if (force) { // When force is true, the underlying data was already added, therefore we need to avoid accessing any back-end data // since we might be off by 1 row. this.dataGridViewState1[DATAGRIDVIEWSTATE1_temporarilyResetCurrentCell] = true; bool success = SetCurrentCellAddressCore(-1, -1, true /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false); Debug.Assert(success); } else { ResetCurrentCell(); } } else { newCurrentCell = new Point(-1, -1); } } else { if (newCurrentCell.Y != -1) { newCurrentCell.Y += insertionCount; } } // For now same checks as for OnAddingRow OnAddingRow(dataGridViewRow, rowState, false /*checkFrozenState*/); // check for correctness of frozen state - throws exception if state is incorrect. CorrectRowFrozenState(dataGridViewRow, rowState, rowIndexInserted); // Update the indexes of selected rows to compensate for the insertion of this row switch (this.SelectionMode) { case DataGridViewSelectionMode.FullRowSelect: case DataGridViewSelectionMode.RowHeaderSelect: int rowEntries = this.selectedBandIndexes.Count; int rowEntry = 0; while (rowEntry < rowEntries) { int rowIndex = this.selectedBandIndexes[rowEntry]; if (rowIndexInserted <= rowIndex) { this.selectedBandIndexes[rowEntry] = rowIndex + insertionCount; } rowEntry++; } if (this.selectedBandSnapshotIndexes != null) { rowEntries = this.selectedBandSnapshotIndexes.Count; rowEntry = 0; while (rowEntry < rowEntries) { int rowIndex = this.selectedBandSnapshotIndexes[rowEntry]; if (rowIndexInserted <= rowIndex) { this.selectedBandSnapshotIndexes[rowEntry] = rowIndex + insertionCount; } rowEntry++; } } break; } } internal void OnInsertingRows(int rowIndexInserted, DataGridViewRow[] dataGridViewRows, ref Point newCurrentCell) { Debug.Assert(dataGridViewRows != null); // Reset the current cell's address if it's after the inserted row. if (this.ptCurrentCell.Y != -1 && rowIndexInserted <= this.ptCurrentCell.Y) { newCurrentCell = new Point(this.ptCurrentCell.X, this.ptCurrentCell.Y + dataGridViewRows.Length); ResetCurrentCell(); } else { newCurrentCell = new Point(-1, -1); } // For now almost same checks as for OnAddingRows // OnAddingRows checks for Selected status of rows. OnAddingRows(dataGridViewRows, false /*checkFrozenStates*/); // Check for Frozen state correctness CorrectRowFrozenStates(dataGridViewRows, rowIndexInserted); // Update the indexes of selected rows to compensate for the insertion of this row switch (this.SelectionMode) { case DataGridViewSelectionMode.FullRowSelect: case DataGridViewSelectionMode.RowHeaderSelect: int rowEntries = this.selectedBandIndexes.Count; int rowEntry = 0; while (rowEntry < rowEntries) { int rowIndex = this.selectedBandIndexes[rowEntry]; if (rowIndexInserted <= rowIndex) { this.selectedBandIndexes[rowEntry] = rowIndex + dataGridViewRows.Length; } rowEntry++; } if (this.selectedBandSnapshotIndexes != null) { rowEntries = this.selectedBandSnapshotIndexes.Count; rowEntry = 0; while (rowEntry < rowEntries) { int rowIndex = this.selectedBandSnapshotIndexes[rowEntry]; if (rowIndexInserted <= rowIndex) { this.selectedBandSnapshotIndexes[rowEntry] = rowIndex + dataGridViewRows.Length; } rowEntry++; } } break; } } /// [EditorBrowsable(EditorBrowsableState.Advanced)] protected override void OnKeyDown(KeyEventArgs e) { base.OnKeyDown(e); if (e.Handled) { return; } // Forward key down to current cell if any if (this.ptCurrentCell.X != -1) { DataGridViewCell dataGridViewCell = this.CurrentCellInternal; Debug.Assert(dataGridViewCell != null); if (dataGridViewCell.KeyDownUnsharesRowInternal(e, this.ptCurrentCell.Y)) { DataGridViewRow dataGridViewRow = this.Rows[this.ptCurrentCell.Y]; this.CurrentCellInternal.OnKeyDownInternal(e, this.ptCurrentCell.Y); } else { dataGridViewCell.OnKeyDownInternal(e, this.ptCurrentCell.Y); } } if (!e.Handled) { switch (e.KeyData & Keys.KeyCode) { case Keys.A: case Keys.C: case Keys.D0: case Keys.NumPad0: case Keys.Delete: case Keys.Down: case Keys.F2: case Keys.End: case Keys.Enter: case Keys.Escape: case Keys.Home: case Keys.Insert: case Keys.Left: case Keys.Next: case Keys.Prior: case Keys.Right: case Keys.Space: case Keys.Tab: case Keys.Up: { e.Handled = ProcessDataGridViewKey(e); break; } } } } /// [EditorBrowsable(EditorBrowsableState.Advanced)] protected override void OnKeyPress(KeyPressEventArgs e) { base.OnKeyPress(e); if (e.Handled) { return; } // Forward key press to current cell if any if (this.ptCurrentCell.X != -1) { DataGridViewCell dataGridViewCell = this.CurrentCellInternal; Debug.Assert(dataGridViewCell != null); if (dataGridViewCell.KeyPressUnsharesRowInternal(e, this.ptCurrentCell.Y)) { DataGridViewRow dataGridViewRow = this.Rows[this.ptCurrentCell.Y]; this.CurrentCellInternal.OnKeyPressInternal(e, this.ptCurrentCell.Y); } else { dataGridViewCell.OnKeyPressInternal(e, this.ptCurrentCell.Y); } } } /// [EditorBrowsable(EditorBrowsableState.Advanced)] protected override void OnKeyUp(KeyEventArgs e) { base.OnKeyUp(e); if (e.Handled) { return; } // Forward key up to current cell if any if (this.ptCurrentCell.X != -1) { DataGridViewCell dataGridViewCell = this.CurrentCellInternal; Debug.Assert(dataGridViewCell != null); if (dataGridViewCell.KeyUpUnsharesRowInternal(e, this.ptCurrentCell.Y)) { DataGridViewRow dataGridViewRow = this.Rows[this.ptCurrentCell.Y]; this.CurrentCellInternal.OnKeyUpInternal(e, this.ptCurrentCell.Y); } else { dataGridViewCell.OnKeyUpInternal(e, this.ptCurrentCell.Y); } } } /// protected override void OnLayout(LayoutEventArgs e) { if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlChanging]) { return; } base.OnLayout(e); PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); if (this.RightToLeftInternal) { Invalidate(); } if (this.editingControl != null) { PositionEditingControl(true, true, false); } } /// protected override void OnLeave(EventArgs e) { if (this.ptCurrentCell.X > -1 && !this.dataGridViewState1[DATAGRIDVIEWSTATE1_leavingWithTabKey]) { DataGridViewCell dataGridViewCell = null; OnCellLeave(ref dataGridViewCell, this.ptCurrentCell.X, this.ptCurrentCell.Y); if (this.ptCurrentCell.X == -1) { return; } OnRowLeave(ref dataGridViewCell, this.ptCurrentCell.X, this.ptCurrentCell.Y); } if (!this.dataGridViewState1[DATAGRIDVIEWSTATE1_leavingWithTabKey]) { base.OnLeave(e); // invalidate the current cell so the data grid view does not paint the focus rectangle any longer if (this.ptCurrentCell.X > -1 && this.ptCurrentCell.Y > -1) { InvalidateCellPrivate(this.ptCurrentCell.X /*columnIndex*/, this.ptCurrentCell.Y /*rowIndex*/); } } } /// protected override void OnLostFocus(EventArgs e) { base.OnLostFocus(e); if (this.ptCurrentCell.X != -1) { InvalidateCell(this.ptCurrentCell.X, this.ptCurrentCell.Y); } } /// protected override void OnMouseClick(MouseEventArgs e) { bool mouseClickRaised = false; if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls] && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize] && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize] && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize]) { HitTestInfo hti = HitTest(e.X, e.Y); if (this.ptMouseDownCell.X == hti.col && this.ptMouseDownCell.Y == hti.row && (e.Button != MouseButtons.Left || this.ptMouseDownCell.X == -1 || this.ptMouseDownCell.Y == -1 || (this.ptMouseDownCell.X == this.ptCurrentCell.X && this.ptMouseDownCell.Y == this.ptCurrentCell.Y))) { DataGridViewCellMouseEventArgs dgvcme = null; if (hti.Type != DataGridViewHitTestType.None && hti.Type != DataGridViewHitTestType.HorizontalScrollBar && hti.Type != DataGridViewHitTestType.VerticalScrollBar) { int mouseX = e.X - hti.ColumnX; if (this.RightToLeftInternal) { mouseX += ((hti.col == -1) ? this.RowHeadersWidth : this.Columns[hti.col].Thickness); } dgvcme = new DataGridViewCellMouseEventArgs(hti.col, hti.row, mouseX, e.Y - hti.RowY, e); RecordCellMouseClick(dgvcme); if (e.Button == MouseButtons.Left) { OnCellClick(new DataGridViewCellEventArgs(hti.col, hti.row)); } base.OnMouseClick(e); mouseClickRaised = true; if (dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count) { OnCellMouseClick(dgvcme); } } else { base.OnMouseClick(e); mouseClickRaised = true; } if (!this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation]) { switch (hti.typeInternal) { case DataGridViewHitTestTypeInternal.ColumnHeader: case DataGridViewHitTestTypeInternal.ColumnHeaderLeft: case DataGridViewHitTestTypeInternal.ColumnHeaderRight: case DataGridViewHitTestTypeInternal.FirstColumnHeaderLeft: { Debug.Assert(dgvcme != null); if (dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count) { OnColumnHeaderMouseClick(dgvcme); } break; } case DataGridViewHitTestTypeInternal.RowHeader: { Debug.Assert(dgvcme != null); if (dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count) { OnRowHeaderMouseClick(dgvcme); } break; } } } } } if (!mouseClickRaised) { base.OnMouseClick(e); } } /// protected override void OnMouseDoubleClick(MouseEventArgs e) { base.OnMouseDoubleClick(e); if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls] && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize] && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize] && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize]) { HitTestInfo hti = HitTest(e.X, e.Y); if (this.ptMouseDownCell.X == hti.col && this.ptMouseDownCell.Y == hti.row) { DataGridViewCellMouseEventArgs dgvcme = null; if (hti.Type != DataGridViewHitTestType.None && hti.Type != DataGridViewHitTestType.HorizontalScrollBar && hti.Type != DataGridViewHitTestType.VerticalScrollBar) { int mouseX = e.X - hti.ColumnX; if (this.RightToLeftInternal) { mouseX += ((hti.col == -1) ? this.RowHeadersWidth : this.Columns[hti.col].Thickness); } dgvcme = new DataGridViewCellMouseEventArgs(hti.col, hti.row, mouseX, e.Y - hti.RowY, e); OnCellMouseDoubleClick(dgvcme); } if (!this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation]) { switch (hti.typeInternal) { case DataGridViewHitTestTypeInternal.ColumnHeader: case DataGridViewHitTestTypeInternal.ColumnHeaderLeft: case DataGridViewHitTestTypeInternal.ColumnHeaderRight: case DataGridViewHitTestTypeInternal.FirstColumnHeaderLeft: { Debug.Assert(dgvcme != null); if (dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count) { OnColumnHeaderMouseDoubleClick(dgvcme); } break; } case DataGridViewHitTestTypeInternal.ColumnResizeLeft: case DataGridViewHitTestTypeInternal.ColumnResizeRight: { int columnIndex = (hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnResizeRight) ? hti.col : hti.adjacentCol; if (columnIndex < this.Columns.Count) { HandledMouseEventArgs hme = new HandledMouseEventArgs(e.Button, e.Clicks, e.X, e.Y, e.Delta, false /*defaultHandledValue*/); DataGridViewColumnDividerDoubleClickEventArgs dgvcddce = new DataGridViewColumnDividerDoubleClickEventArgs(columnIndex, hme); Debug.Assert(this.Columns[columnIndex].Resizable == DataGridViewTriState.True); OnColumnDividerDoubleClick(dgvcddce); } break; } case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeTop: case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeBottom: case DataGridViewHitTestTypeInternal.ColumnHeadersResizeTop: case DataGridViewHitTestTypeInternal.ColumnHeadersResizeBottom: { HandledMouseEventArgs hme = new HandledMouseEventArgs(e.Button, e.Clicks, e.X, e.Y, e.Delta, false /*defaultHandledValue*/); DataGridViewRowDividerDoubleClickEventArgs dgvrddce = new DataGridViewRowDividerDoubleClickEventArgs(-1, hme); Debug.Assert(this.columnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.EnableResizing); OnRowDividerDoubleClick(dgvrddce); break; } case DataGridViewHitTestTypeInternal.RowHeader: { Debug.Assert(dgvcme != null); if (dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count) { OnRowHeaderMouseDoubleClick(dgvcme); } break; } case DataGridViewHitTestTypeInternal.RowResizeBottom: case DataGridViewHitTestTypeInternal.RowResizeTop: { int rowIndex = (hti.typeInternal == DataGridViewHitTestTypeInternal.RowResizeBottom) ? hti.row : hti.adjacentRow; if (rowIndex < this.Rows.Count) { HandledMouseEventArgs hme = new HandledMouseEventArgs(e.Button, e.Clicks, e.X, e.Y, e.Delta, false /*defaultHandledValue*/); DataGridViewRowDividerDoubleClickEventArgs dgvrddce = new DataGridViewRowDividerDoubleClickEventArgs(rowIndex, hme); Debug.Assert(this.Rows[rowIndex].Resizable == DataGridViewTriState.True); OnRowDividerDoubleClick(dgvrddce); } break; } case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeLeft: case DataGridViewHitTestTypeInternal.TopLeftHeaderResizeRight: case DataGridViewHitTestTypeInternal.RowHeadersResizeLeft: case DataGridViewHitTestTypeInternal.RowHeadersResizeRight: { HandledMouseEventArgs hme = new HandledMouseEventArgs(e.Button, e.Clicks, e.X, e.Y, e.Delta, false /*defaultHandledValue*/); DataGridViewColumnDividerDoubleClickEventArgs dgvcddce = new DataGridViewColumnDividerDoubleClickEventArgs(-1, hme); Debug.Assert(this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing); OnColumnDividerDoubleClick(dgvcddce); break; } } } } } } /// protected override void OnMouseDown(MouseEventArgs e) { if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls]) { this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves] = true; } base.OnMouseDown(e); if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls]) { return; } if (this.ptMouseDownCell.X != -2) { // Happens when user pushes the mouse wheel down while the left mouse button is already down Debug.Assert(this.ptMouseDownCell.Y != -2); return; } HitTestInfo hti = HitTest(e.X, e.Y); if (hti.Type != DataGridViewHitTestType.None && hti.Type != DataGridViewHitTestType.HorizontalScrollBar && hti.Type != DataGridViewHitTestType.VerticalScrollBar) { this.ptMouseDownCell.X = hti.col; this.ptMouseDownCell.Y = hti.row; this.ptMouseDownGridCoord = new Point(e.X, e.Y); int mouseX = e.X - hti.ColumnX; if (this.RightToLeftInternal) { mouseX += ((hti.col == -1) ? this.RowHeadersWidth : this.Columns[hti.col].Thickness); } DataGridViewCellMouseEventArgs dgvcme = new DataGridViewCellMouseEventArgs(hti.col, hti.row, mouseX, e.Y - hti.RowY, e); OnCellMouseDown(dgvcme); } } /// protected override void OnMouseEnter(EventArgs e) { if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseOverRemovedEditingCtrl] && !this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseOverRemovedEditingPanel] && this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseEnterExpected] && !this.toolTipControl.Activated) { base.OnMouseEnter(e); } this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseOverRemovedEditingCtrl] = false; this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseOverRemovedEditingPanel] = false; this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseEnterExpected] = false; } /// protected override void OnMouseLeave(EventArgs e) { // when the mouse leaves the dataGridView control, reset the cursor to the previously cached one if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet]) { this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet] = false; this.CursorInternal = this.oldCursor; } bool mouseOverEditingControl = this.MouseOverEditingControl; bool mouseOverEditingPanel = this.MouseOverEditingPanel; bool mouseOverToolTipControl = this.toolTipControl.Activated && this.ClientRectangle.Contains(PointToClient(Control.MousePosition)); if (!mouseOverEditingPanel && !mouseOverEditingControl && !mouseOverToolTipControl && this.ptMouseEnteredCell.X != -2) { if (this.ptMouseEnteredCell.X >= -1 && this.ptMouseEnteredCell.X < this.Columns.Count && this.ptMouseEnteredCell.Y >= -1 && this.ptMouseEnteredCell.Y < this.Rows.Count) { DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(this.ptMouseEnteredCell.X, this.ptMouseEnteredCell.Y); OnCellMouseLeave(dgvce); } else { this.ptMouseEnteredCell.X = this.ptMouseEnteredCell.Y = -2; } } ResetTrackingState(); this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves] = false; if (!mouseOverEditingPanel && !mouseOverEditingControl && !mouseOverToolTipControl && !this.MouseOverScrollBar) { this.toolTipControl.Activate(false /*activate*/); base.OnMouseLeave(e); this.dataGridViewState2[DATAGRIDVIEWSTATE2_mouseEnterExpected] = true; } } /// protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); HitTestInfo hti = HitTest(e.X, e.Y); UpdateMouseEnteredCell(hti, e); // We need to give UI feedback when the user is resizing a column if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize]) { MoveRowHeadersOrColumnResize(e); } else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize]) { MoveColumnHeadersOrRowResize(e); } else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation]) { MoveColumnRelocation(e, hti); } else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize]) { MoveColumnHeadersOrRowResize(e); } else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize]) { MoveRowHeadersOrColumnResize(e); } if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize] || this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize] || ((hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnResizeLeft || hti.typeInternal == DataGridViewHitTestTypeInternal.TopLeftHeaderResizeLeft || hti.typeInternal == DataGridViewHitTestTypeInternal.TopLeftHeaderResizeRight || hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnResizeRight || hti.typeInternal == DataGridViewHitTestTypeInternal.RowHeadersResizeLeft || hti.typeInternal == DataGridViewHitTestTypeInternal.RowHeadersResizeRight) && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation] && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect] && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect])) { if (!this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet]) { this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet] = true; this.oldCursor = this.Cursor; } this.CursorInternal = Cursors.SizeWE; return; } else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize] || this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] || ((hti.typeInternal == DataGridViewHitTestTypeInternal.RowResizeBottom || hti.typeInternal == DataGridViewHitTestTypeInternal.TopLeftHeaderResizeTop || hti.typeInternal == DataGridViewHitTestTypeInternal.TopLeftHeaderResizeBottom || hti.typeInternal == DataGridViewHitTestTypeInternal.RowResizeTop || hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeadersResizeTop || hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeadersResizeBottom) && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize] && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation] && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect] && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect])) { if (!this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet]) { this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet] = true; this.oldCursor = this.Cursor; } this.CursorInternal = Cursors.SizeNS; return; } /* Whidbey bug 156884 - no longer show hand cursor if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation] && (hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnResizeLeft || hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnResizeRight || hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeaderLeft || hti.typeInternal == DataGridViewHitTestTypeInternal.ColumnHeaderRight || hti.typeInternal == DataGridViewHitTestTypeInternal.FirstColumnHeaderLeft || hti.typeInternal == DataGridViewHitTestTypeInternal.TopLeftHeaderResizeRight)) { if (!this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet]) { this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet] = true; this.oldCursor = this.Cursor; } this.CursorInternal = Cursors.Hand; return; }*/ else if (this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet]) { this.dataGridViewState1[DATAGRIDVIEWSTATE1_customCursorSet] = false; this.CursorInternal = this.oldCursor; } if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] || this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect] || this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect]) { int xOffset, yOffset, mouseX = e.X, mouseY = e.Y; if (GetOutOfBoundCorrectedHitTestInfo(ref hti, ref mouseX, ref mouseY, out xOffset, out yOffset)) { if (xOffset == 0) { if (this.horizScrollTimer != null && this.horizScrollTimer.Enabled) { // Mouse's X came in-bound - need to stop the horizontal scroll timer this.horizScrollTimer.Enabled = false; } } else if (this.horizScrollTimer == null || !this.horizScrollTimer.Enabled) { // Need to start delayed horizontal scroll this.HorizScrollTimer.Interval = GetColumnScrollRate(Math.Abs(xOffset)); this.HorizScrollTimer.Enabled = true; } if (yOffset == 0) { if (this.vertScrollTimer != null && this.vertScrollTimer.Enabled) { // Mouse's Y came in-bound - need to stop the vertical scroll timer this.vertScrollTimer.Enabled = false; } } else if (this.vertScrollTimer == null || !this.vertScrollTimer.Enabled) { // Need to start delayed vertical scroll this.VertScrollTimer.Interval = GetRowScrollRate(Math.Abs(yOffset)); this.VertScrollTimer.Enabled = true; } if (this.HorizScrollTimer.Enabled || this.VertScrollTimer.Enabled) { return; } if (/*!this.dataGridViewState1[DATAGRIDVIEWSTATE1_scrolledSinceMouseDown] && */ hti.Type != DataGridViewHitTestType.None && hti.Type != DataGridViewHitTestType.HorizontalScrollBar && hti.Type != DataGridViewHitTestType.VerticalScrollBar) { if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColSelect] && hti.col >= 0) { OnColumnSelectMouseMove(hti); } else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect] && hti.row >= 0) { OnRowSelectMouseMove(hti); } else if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackCellSelect] && hti.col >= 0 && hti.row >= 0) { OnCellSelectMouseMove(hti); } } } } #if DEBUG else { Debug.Assert(this.vertScrollTimer == null || !this.vertScrollTimer.Enabled); Debug.Assert(this.horizScrollTimer == null || !this.horizScrollTimer.Enabled); } #endif if (!this.toolTipControl.Activated) { // // After processing the MouseMove event, the tool tip is still not activated. // Reset the tool tip cell. this.ptToolTipCell = new Point(-1, -1); } } /// protected override void OnMouseUp(MouseEventArgs e) { if (!this.dataGridViewState2[DATAGRIDVIEWSTATE2_messageFromEditingCtrls]) { this.dataGridViewState1[DATAGRIDVIEWSTATE1_scrolledSinceMouseDown] = false; HitTestInfo hti = HitTest(e.X, e.Y); if (!this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize] && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize] && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation] && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] && !this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize]) { if (hti.Type != DataGridViewHitTestType.None && hti.Type != DataGridViewHitTestType.HorizontalScrollBar && hti.Type != DataGridViewHitTestType.VerticalScrollBar) { int mouseX = e.X - hti.ColumnX; if (this.RightToLeftInternal) { mouseX += ((hti.col == -1) ? this.RowHeadersWidth : this.Columns[hti.col].Thickness); } DataGridViewCellMouseEventArgs dgvcme; if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_nextMouseUpIsDouble]) { MouseEventArgs meTmp = new MouseEventArgs(e.Button, 2, e.X, e.Y, e.Delta); dgvcme = new DataGridViewCellMouseEventArgs(hti.col, hti.row, mouseX, e.Y - hti.RowY, meTmp); } else { dgvcme = new DataGridViewCellMouseEventArgs(hti.col, hti.row, mouseX, e.Y - hti.RowY, e); } if (hti.col >= 0 && this.ptMouseDownCell.X == hti.col && hti.row >= 0 && this.ptMouseDownCell.Y == hti.row && this.EditMode == DataGridViewEditMode.EditOnEnter && this.editingControl != null) { OnClick(e); OnMouseClick(e); } CorrectFocus(true /*onlyIfGridHasFocus*/); if (dgvcme.ColumnIndex < this.Columns.Count && dgvcme.RowIndex < this.Rows.Count) { OnCellMouseUp(dgvcme); } } else if (hti.Type == DataGridViewHitTestType.None) { // VS Whidbey bug 469429 CorrectFocus(true /*onlyIfGridHasFocus*/); } } else { if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize]) { EndColumnResize(e); } if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize]) { EndRowResize(e); } if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColRelocation]) { EndColumnRelocation(e, hti); } if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize]) { EndColumnHeadersResize(e); } if (this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize]) { EndRowHeadersResize(e); } // VS Whidbey bug 256893 CorrectFocus(true /*onlyIfGridHasFocus*/); // Updating the hit test info since the EndXXX operation above may have invalidated the previously // determined hti. hti = HitTest(e.X, e.Y); if (hti.Type != DataGridViewHitTestType.None && hti.Type != DataGridViewHitTestType.HorizontalScrollBar && hti.Type != DataGridViewHitTestType.VerticalScrollBar) { int mouseX = e.X - hti.ColumnX; if (this.RightToLeftInternal) { mouseX += ((hti.col == -1) ? this.RowHeadersWidth : this.Columns[hti.col].Thickness); } OnCellMouseUp(new DataGridViewCellMouseEventArgs(hti.col, hti.row, mouseX, e.Y - hti.RowY, e)); } } ResetTrackingState(); } base.OnMouseUp(e); } /// protected override void OnMouseWheel(MouseEventArgs e) { base.OnMouseWheel(e); HandledMouseEventArgs hme = e as HandledMouseEventArgs; if (hme != null && hme.Handled) { // The application event handler handled the scrolling - don't do anything more. return; } if ((ModifierKeys & (Keys.Shift | Keys.Alt)) != 0 || MouseButtons != MouseButtons.None) { return; // Do not scroll when Shift or Alt key is down, or when a mouse button is down. } bool verticalScroll = ((ModifierKeys & Keys.Control) == 0); ScrollBar sb = (verticalScroll ? (ScrollBar) this.vertScrollBar : (ScrollBar) this.horizScrollBar); if (!sb.Visible || !sb.Enabled) { return; // Do not scroll when the corresponding scrollbar is invisible or disabled } if (hme != null) { hme.Handled = true; } int wheelScrollLines = SystemInformation.MouseWheelScrollLines; if (wheelScrollLines == 0) { return; // Do not scroll when the user system setting is 0 lines per notch } Debug.Assert(this.cumulativeVerticalWheelDelta > -NativeMethods.WHEEL_DELTA); Debug.Assert(this.cumulativeVerticalWheelDelta < NativeMethods.WHEEL_DELTA); Debug.Assert(this.cumulativeHorizontalWheelDelta > -NativeMethods.WHEEL_DELTA); Debug.Assert(this.cumulativeHorizontalWheelDelta < NativeMethods.WHEEL_DELTA); float partialNotches; if (verticalScroll) { this.cumulativeVerticalWheelDelta += e.Delta; partialNotches = (float) this.cumulativeVerticalWheelDelta / (float) NativeMethods.WHEEL_DELTA; } else { this.cumulativeHorizontalWheelDelta += e.Delta; partialNotches = (float) this.cumulativeHorizontalWheelDelta / (float) NativeMethods.WHEEL_DELTA; } int fullNotches = (int) partialNotches; if (wheelScrollLines == -1) { // Equivalent to large change scrolls if (fullNotches != 0) { if (this.ptCurrentCell.X >= 0 && !CommitEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.Scroll, false /*forCurrentCellChange*/, false /*forCurrentRowChange*/)) { // Could not commit edited cell value return; } if (verticalScroll) { int originalVerticalOffset = this.VerticalOffset; this.VerticalOffset -= fullNotches * this.vertScrollBar.LargeChange; if (Math.Abs(this.VerticalOffset - originalVerticalOffset) >= Math.Abs(fullNotches * this.vertScrollBar.LargeChange)) { this.cumulativeVerticalWheelDelta -= fullNotches * NativeMethods.WHEEL_DELTA; } else { this.cumulativeVerticalWheelDelta = 0; } } else { int originalHorizontalOffset = this.HorizontalOffset; this.HorizontalOffset -= fullNotches * this.horizScrollBar.LargeChange; if (Math.Abs(this.HorizontalOffset - originalHorizontalOffset) >= Math.Abs(fullNotches * this.horizScrollBar.LargeChange)) { this.cumulativeHorizontalWheelDelta -= fullNotches * NativeMethods.WHEEL_DELTA; } else { this.cumulativeHorizontalWheelDelta = 0; } } } } else { // Evaluate number of bands to scroll int scrollBands = (int) ((float) wheelScrollLines * partialNotches); if (scrollBands != 0) { if (this.ptCurrentCell.X >= 0 && !CommitEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.Scroll, false /*forCurrentCellChange*/, false /*forCurrentRowChange*/)) { // Could not commit edited cell value return; } int absScrollBands; if (verticalScroll) { if (scrollBands > 0) { absScrollBands = scrollBands; while (this.vertScrollBar.Value != this.vertScrollBar.Minimum && absScrollBands > 0) { ScrollRowsByCount(-1, ScrollEventType.SmallDecrement); absScrollBands--; } if (this.vertScrollBar.Value == this.vertScrollBar.Minimum) { this.cumulativeVerticalWheelDelta = 0; } else { this.cumulativeVerticalWheelDelta -= (int) ((float) scrollBands * ((float) NativeMethods.WHEEL_DELTA / (float) wheelScrollLines)); } } else { absScrollBands = -scrollBands; Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0); int totalVisibleFrozenHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); while (absScrollBands > 0 && this.vertScrollBar.Value + this.Rows.SharedRow(this.displayedBandsInfo.FirstDisplayedScrollingRow).GetHeight(this.displayedBandsInfo.FirstDisplayedScrollingRow) <= this.vertScrollBar.Maximum - ComputeHeightOfFittingTrailingScrollingRows(totalVisibleFrozenHeight)) { ScrollRowsByCount(1, ScrollEventType.SmallIncrement); // Assuming totalVisibleFrozenHeight is unchanged by scrolling operation Debug.Assert(totalVisibleFrozenHeight == this.Rows.GetRowsHeight(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen)); Debug.Assert(this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0); absScrollBands--; } if (this.vertScrollBar.Value + this.Rows.SharedRow(this.displayedBandsInfo.FirstDisplayedScrollingRow).GetHeight(this.displayedBandsInfo.FirstDisplayedScrollingRow) > this.vertScrollBar.Maximum - ComputeHeightOfFittingTrailingScrollingRows(totalVisibleFrozenHeight)) { this.cumulativeVerticalWheelDelta = 0; } else { this.cumulativeVerticalWheelDelta -= (int) ((float) scrollBands * ((float) NativeMethods.WHEEL_DELTA / (float) wheelScrollLines)); } } } else { int extremeScrollBarValue, scrollBand; if (scrollBands > 0) { extremeScrollBarValue = this.horizScrollBar.Minimum; scrollBand = -1; } else { extremeScrollBarValue = this.horizScrollBar.Maximum; scrollBand = 1; } absScrollBands = Math.Abs(scrollBands); while (this.horizScrollBar.Value != extremeScrollBarValue && absScrollBands > 0) { ScrollColumns(scrollBand); absScrollBands--; } if (this.horizScrollBar.Value == extremeScrollBarValue) { this.cumulativeHorizontalWheelDelta = 0; } else { this.cumulativeHorizontalWheelDelta -= (int) ((float) scrollBands * ((float) NativeMethods.WHEEL_DELTA / (float) wheelScrollLines)); } } } } } internal void OnMouseWheelInternal(MouseEventArgs e) { // Notification forwarded from editing control OnMouseWheel(e); } /// protected virtual void OnMultiSelectChanged(EventArgs e) { EventHandler eh = this.Events[EVENT_DATAGRIDVIEWMULTISELECTCHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnNewRowNeeded(DataGridViewRowEventArgs e) { if (e.Row.DataGridView != this) { throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row"); } DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWNEWROWNEEDED] as DataGridViewRowEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected override void OnPaint(PaintEventArgs e) { try { if (this.layout.dirty) { PerformLayoutPrivate(false /*useRowShortcut*/, true /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); } Graphics g = e.Graphics; bool singleVerticalBorderAdded = false, singleHorizontalBorderAdded = false; Rectangle clipRect = e.ClipRectangle; Rectangle gridRect = this.layout.Data; if (this.layout.RowHeadersVisible) { gridRect = Rectangle.Union(gridRect, this.layout.RowHeaders); } else if (this.SingleVerticalBorderAdded) { singleVerticalBorderAdded = true; if (!this.RightToLeftInternal) { gridRect.X--; } gridRect.Width++; } if (this.layout.ColumnHeadersVisible) { gridRect = Rectangle.Union(gridRect, this.layout.ColumnHeaders); } else if (this.SingleHorizontalBorderAdded) { singleHorizontalBorderAdded = true; if (gridRect.Y == this.layout.Data.Y) { gridRect.Y--; gridRect.Height++; } } if (this.currentRowSplitBar != -1) { clipRect = Rectangle.Union(clipRect, CalcRowResizeFeedbackRect(this.currentRowSplitBar)); } else if (this.currentColSplitBar != -1) { clipRect = Rectangle.Union(clipRect, CalcColResizeFeedbackRect(this.currentColSplitBar)); } if (clipRect.IntersectsWith(gridRect)) { using (Region clipRegion = g.Clip) { g.SetClip(gridRect); PaintBackground(g, clipRect, gridRect); PaintGrid(g, gridRect, clipRect, singleVerticalBorderAdded, singleHorizontalBorderAdded); g.Clip = clipRegion; } } PaintBorder(g, clipRect, this.layout.ClientRectangle); if (clipRect.IntersectsWith(this.layout.ResizeBoxRect)) { g.FillRectangle(SystemBrushes.Control, this.layout.ResizeBoxRect); } base.OnPaint(e); // raise paint event } catch (Exception ex) { #if DEBUG Debug.Fail("DataGridView.OnPaint exception: " + ex.Message + " stack trace " + ex.StackTrace); #endif if (ClientUtils.IsCriticalException(ex)) { throw; } } } // See VSWhidbey 527459 & 526373. internal override void OnParentBecameInvisible() { base.OnParentBecameInvisible(); if (GetState(STATE_VISIBLE)) { // This control became invisible too - Update the Displayed properties of the bands. OnVisibleChangedPrivate(); } } /// protected virtual void OnReadOnlyChanged(EventArgs e) { EventHandler eh = this.Events[EVENT_DATAGRIDVIEWREADONLYCHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } VerifyImeRestrictedModeChanged(); if (!this.ReadOnly && this.ptCurrentCell.X != -1 && ColumnEditable(this.ptCurrentCell.X) && !this.IsCurrentCellInEditMode && (this.EditMode == DataGridViewEditMode.EditOnEnter || (this.EditMode != DataGridViewEditMode.EditProgrammatically && this.CurrentCellInternal.EditType == null)) && !this.Rows[this.ptCurrentCell.Y].Cells[this.ptCurrentCell.X].ReadOnly) // Unshares the row { // Current cell becomes read/write. Enter editing mode. BeginEditInternal(true /*selectAll*/); } } internal void OnRemovedColumn_PreNotification(DataGridViewColumn dataGridViewColumn) { Debug.Assert(dataGridViewColumn.Index >= 0); Debug.Assert(dataGridViewColumn.DataGridView == null); // Clear the potential header sort glyph if (dataGridViewColumn.HasHeaderCell) { dataGridViewColumn.HeaderCell.SortGlyphDirectionInternal = SortOrder.None; } // Intentionally keep the DisplayIndex intact after detaching the column. CorrectColumnIndexesAfterDeletion(dataGridViewColumn); CorrectColumnDisplayIndexesAfterDeletion(dataGridViewColumn); // Fix the OldFirstDisplayedScrollingCol this.displayedBandsInfo.CorrectRowIndexAfterDeletion(dataGridViewColumn.Index); // Raise the ColumnRemoved event OnColumnRemoved(dataGridViewColumn); } internal void OnRemovedColumn_PostNotification(DataGridViewColumn dataGridViewColumn, Point newCurrentCell) { // Update current cell if needed if (newCurrentCell.X != -1) { Debug.Assert(this.ptCurrentCell.X == -1); bool success = SetAndSelectCurrentCellAddress(newCurrentCell.X, newCurrentCell.Y, true, false, false, false /*clearSelection*/, false /*forceCurrentCellSelection*/); Debug.Assert(success); } // Raise SelectionChanged event if needed FlushSelectionChanged(); // Raise ColumnStateChanged event for Displayed state of deleted column OnColumnHidden(dataGridViewColumn); // Columns that are removed from the collection take their non-autosized width // Note that in some edge cases, the dev could have changed: // - the grid's AutoSizeColumnsMode // - the column's Width or AutoSizeMode // in a ColumnRemoved event handler for example, in which case using the CachedThickness may be wrong. // At least we make sure the column is not sized smaller than its minimum width. DataGridViewAutoSizeColumnMode autoSizeColumnMode = dataGridViewColumn.GetInheritedAutoSizeMode(this); Debug.Assert(autoSizeColumnMode != DataGridViewAutoSizeColumnMode.NotSet); if (autoSizeColumnMode != DataGridViewAutoSizeColumnMode.None && autoSizeColumnMode != DataGridViewAutoSizeColumnMode.Fill && dataGridViewColumn.ThicknessInternal != dataGridViewColumn.CachedThickness) { dataGridViewColumn.ThicknessInternal = Math.Max(dataGridViewColumn.MinimumWidth, dataGridViewColumn.CachedThickness); } // Autosize rows if needed AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); } internal void OnRemovedRow_PreNotification(int rowIndexDeleted) { // Fix the OldFirstDisplayedScrollingRow this.displayedBandsInfo.CorrectRowIndexAfterDeletion(rowIndexDeleted); CorrectRowIndexesAfterDeletion(rowIndexDeleted); ComputeVisibleRows(); } internal void OnRemovedRow_PostNotification(DataGridViewRow dataGridViewRow, Point newCurrentCell) { // Update current cell if needed if (newCurrentCell.Y != -1) { Debug.Assert(this.ptCurrentCell.X == -1); bool success = SetAndSelectCurrentCellAddress(newCurrentCell.X, newCurrentCell.Y, true /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false /*throughMouseClick*/, false /*clearSelection*/, false /*forceCurrentCellSelection*/); Debug.Assert(success); } // Raise SelectionChange event if needed FlushSelectionChanged(); bool rowDisplayed = dataGridViewRow.DataGridView == null && dataGridViewRow.Displayed; // Raise RowStateChanged event for Displayed state of deleted row if (rowDisplayed) { dataGridViewRow.DisplayedInternal = false; DataGridViewRowStateChangedEventArgs dgvrsce = new DataGridViewRowStateChangedEventArgs(dataGridViewRow, DataGridViewElementStates.Displayed); OnRowStateChanged(-1 /*rowIndex*/, dgvrsce); } // Rows that are removed from the collection take their non-autosized height // Note that in some edge cases, the dev could have changed: // - the grid's AutoSizeRowsMode // - the row's Height // in a RowsRemoved event handler for example, in which case using the CachedThickness may be wrong. // At least we make sure the row is not sized smaller than its minimum height. if (this.autoSizeRowsMode != DataGridViewAutoSizeRowsMode.None && dataGridViewRow.ThicknessInternal != dataGridViewRow.CachedThickness) { dataGridViewRow.ThicknessInternal = Math.Max(dataGridViewRow.MinimumHeight, dataGridViewRow.CachedThickness); } // Auto size columms also if needed DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFilter = DataGridViewAutoSizeColumnCriteriaInternal.AllRows; if (rowDisplayed) { autoSizeColumnCriteriaFilter |= DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows; } bool columnAutoSized = AutoResizeAllVisibleColumnsInternal(autoSizeColumnCriteriaFilter, true /*fixedHeight*/); bool fixedColumnHeadersHeight = this.ColumnHeadersHeightSizeMode != DataGridViewColumnHeadersHeightSizeMode.AutoSize; bool fixedRowHeadersWidth = this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing || this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.DisableResizing; if (fixedRowHeadersWidth && !columnAutoSized) { // No need to autosize the column headers when the row headers and columns don't change. fixedColumnHeadersHeight = true; } // Auto size column headers if (!fixedColumnHeadersHeight) { AutoResizeColumnHeadersHeight(fixedRowHeadersWidth, true /*fixedColumnsWidth*/); } // Auto size row headers if (!fixedRowHeadersWidth) { AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, true /*fixedRowsHeight*/); } if (!fixedColumnHeadersHeight && !fixedRowHeadersWidth) { // Second round of column headers autosizing AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/); } } internal void OnRemovingColumn(DataGridViewColumn dataGridViewColumn, out Point newCurrentCell, bool force) { Debug.Assert(dataGridViewColumn != null); Debug.Assert(dataGridViewColumn.Index >= 0 && dataGridViewColumn.Index < this.Columns.Count); this.dataGridViewState1[DATAGRIDVIEWSTATE1_temporarilyResetCurrentCell] = false; int columnIndex = dataGridViewColumn.Index; // Reset the current cell's address if there is one. if (this.ptCurrentCell.X != -1) { int newX = this.ptCurrentCell.X; if (columnIndex == this.ptCurrentCell.X) { DataGridViewColumn dataGridViewColumnNext = this.Columns.GetNextColumn( this.Columns[columnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None); if (dataGridViewColumnNext != null) { if (dataGridViewColumnNext.Index > columnIndex) { newX = dataGridViewColumnNext.Index - 1; } else { newX = dataGridViewColumnNext.Index; } } else { DataGridViewColumn dataGridViewColumnPrevious = this.Columns.GetPreviousColumn( this.Columns[columnIndex], DataGridViewElementStates.Visible, DataGridViewElementStates.None); if (dataGridViewColumnPrevious != null) { if (dataGridViewColumnPrevious.Index > columnIndex) { newX = dataGridViewColumnPrevious.Index - 1; } else { newX = dataGridViewColumnPrevious.Index; } } else { newX = -1; } } } else if (columnIndex < this.ptCurrentCell.X) { newX = this.ptCurrentCell.X - 1; } newCurrentCell = new Point(newX, (newX == -1) ? -1 : this.ptCurrentCell.Y); if (columnIndex == this.ptCurrentCell.X) { // Left cell is not validated since cancelling validation wouldn't have any effect anyways. bool success = SetCurrentCellAddressCore(-1, -1, true /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false); Debug.Assert(success); } else if (force) { // Underlying data of deleted column is gone. It cannot be accessed anymore. // Do not end editing mode so that CellValidation doesn't get raised, since that event needs the current formatted value. this.dataGridViewState1[DATAGRIDVIEWSTATE1_temporarilyResetCurrentCell] = true; bool success = SetCurrentCellAddressCore(-1, -1, true /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false); Debug.Assert(success); } else { // Quit editing mode and set the current cell to its new location once everything is in [....] again. ResetCurrentCell(); } } else { newCurrentCell = new Point(-1, -1); } // If the last column is removed, delete all the rows first. if (this.Columns.Count == 1) { Debug.Assert(columnIndex == 0); this.Rows.ClearInternal(false /*recreateNewRow*/); } // Prepare the existing rows by removing cells at correct index int newColumnCount = this.Columns.Count - 1; for (int rowIndex = 0; rowIndex < this.Rows.Count; rowIndex++) { DataGridViewRow dataGridViewRow = this.Rows.SharedRow(rowIndex); if (dataGridViewRow.Cells.Count > newColumnCount) { dataGridViewRow.Cells.RemoveAtInternal(columnIndex); } } // Detach column header cell if (dataGridViewColumn.HasHeaderCell) { dataGridViewColumn.HeaderCell.DataGridViewInternal = null; } // Reset sort related variables. if (dataGridViewColumn == this.sortedColumn) { this.sortedColumn = null; this.sortOrder = SortOrder.None; if (dataGridViewColumn.IsDataBound) { // If the column being removed is the sorted column and it is also the dataBound column // then see if there is another dataBound column which has the same property name as the sorted column. // If so, then make that dataGridViewColumn the sorted column in the data grid view. for (int i = 0; i < this.Columns.Count; i ++) { if (dataGridViewColumn != this.Columns[i] && this.Columns[i].SortMode != DataGridViewColumnSortMode.NotSortable && String.Compare(dataGridViewColumn.DataPropertyName, this.Columns[i].DataPropertyName, true /*ignoreCase*/, CultureInfo.InvariantCulture) == 0) { Debug.Assert(this.Columns[i].IsDataBound, "two columns w/ the same DataPropertyName should be DataBound at the same time"); Debug.Assert(this.Columns[i].HeaderCell.SortGlyphDirection == dataGridViewColumn.HeaderCell.SortGlyphDirection, "DataBound columns should have the same SortGlyphDirection as the one on the DataGridView"); this.sortedColumn = this.Columns[i]; this.sortOrder = this.Columns[i].HeaderCell.SortGlyphDirection; break; } } } } // Is deleted column scrolled off screen? if (dataGridViewColumn.Visible && !dataGridViewColumn.Frozen && this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0) { // Deleted column is part of scrolling columns. if (this.displayedBandsInfo.FirstDisplayedScrollingCol == dataGridViewColumn.Index) { // Deleted column is first scrolling column this.horizontalOffset -= this.negOffset; this.negOffset = 0; } else if (this.Columns.DisplayInOrder(this.displayedBandsInfo.FirstDisplayedScrollingCol, dataGridViewColumn.Index)) { // Deleted column is displayed after first scrolling column if (this.horizScrollBar.Enabled) { int newHorizontalOffset = this.horizScrollBar.Maximum - this.horizScrollBar.LargeChange - dataGridViewColumn.Thickness; if (newHorizontalOffset >= 0 && newHorizontalOffset < this.horizScrollBar.Value) { this.horizontalOffset = newHorizontalOffset; this.negOffset = GetNegOffsetFromHorizontalOffset(this.horizontalOffset); } } else { this.horizontalOffset = this.negOffset = 0; } } else { // Deleted column is displayed before first scrolling column Debug.Assert(this.horizontalOffset >= dataGridViewColumn.Thickness); this.horizontalOffset -= dataGridViewColumn.Thickness; } if (this.horizScrollBar.Enabled) { this.horizScrollBar.Value = this.horizontalOffset; } } bool raiseSelectionChanged = false; // Update the indexes of selected columns or individual cells to compensate for the removal of this column switch (this.SelectionMode) { case DataGridViewSelectionMode.FullColumnSelect: case DataGridViewSelectionMode.ColumnHeaderSelect: int columnEntries = this.selectedBandIndexes.Count; int columnEntry = 0; while (columnEntry < columnEntries) { int columnIndexSelected = this.selectedBandIndexes[columnEntry]; if (columnIndex == columnIndexSelected) { this.selectedBandIndexes.RemoveAt(columnEntry); columnEntries--; raiseSelectionChanged = true; } else { if (columnIndex < columnIndexSelected) { this.selectedBandIndexes[columnEntry] = columnIndexSelected - 1; } columnEntry++; } } break; } this.dataGridViewState2[DATAGRIDVIEWSTATE2_raiseSelectionChanged] |= this.individualSelectedCells.RemoveAllCellsAtBand(true /*column*/, columnIndex) > 0 || raiseSelectionChanged; this.individualReadOnlyCells.RemoveAllCellsAtBand(true /*column*/, columnIndex); } internal void OnRemovingRow(int rowIndexDeleted, out Point newCurrentCell, bool force) { // if force is true, the row needs to be deleted no matter what. The underlying data row was already deleted. Debug.Assert(rowIndexDeleted >= 0 && rowIndexDeleted < this.Rows.Count); this.dataGridViewState1[DATAGRIDVIEWSTATE1_temporarilyResetCurrentCell] = false; newCurrentCell = new Point(-1, -1); // Reset the current cell's address if it's on the deleted row, or after it. if (this.ptCurrentCell.Y != -1 && rowIndexDeleted <= this.ptCurrentCell.Y) { int newY; if (rowIndexDeleted == this.ptCurrentCell.Y) { int rowIndexPrevious = this.Rows.GetPreviousRow(rowIndexDeleted, DataGridViewElementStates.Visible); int rowIndexNext = this.Rows.GetNextRow(rowIndexDeleted, DataGridViewElementStates.Visible); if (rowIndexPrevious > -1 && this.AllowUserToAddRowsInternal) { Debug.Assert(this.newRowIndex != -1); Debug.Assert(this.newRowIndex == this.Rows.Count-1); if (rowIndexNext > -1 && rowIndexNext < this.Rows.Count - 1) { newY = rowIndexNext - 1; } else { newY = rowIndexPrevious; } } else { if (rowIndexNext > -1) { newY = rowIndexNext - 1; } else { newY = rowIndexPrevious; } } // Since the current row is deleted, the dirty states need to be reset this.IsCurrentCellDirtyInternal = false; this.IsCurrentRowDirtyInternal = false; } else { Debug.Assert(rowIndexDeleted < this.ptCurrentCell.Y); newY = this.ptCurrentCell.Y - 1; } newCurrentCell = new Point(this.ptCurrentCell.X, newY); if (rowIndexDeleted == this.ptCurrentCell.Y) { // Left cell is not validated since cancelling validation wouldn't have any effect anyways. bool success = SetCurrentCellAddressCore(-1, -1, true /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false); Debug.Assert(success); } else if (force) { // Underlying data of deleted row is gone. It cannot be accessed anymore. // Do not end editing mode so that CellValidation doesn't get raised, since that event needs the current formatted value. this.dataGridViewState1[DATAGRIDVIEWSTATE1_temporarilyResetCurrentCell] = true; bool success = SetCurrentCellAddressCore(-1, -1, true /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false); Debug.Assert(success); } else { // Quit editing mode and set the current cell to its new location once everything is in [....] again. ResetCurrentCell(); } } bool raiseSelectionChanged = false; // Update the indexes of selected rows to compensate for the removal of this row switch (this.SelectionMode) { case DataGridViewSelectionMode.FullRowSelect: case DataGridViewSelectionMode.RowHeaderSelect: int rowEntries = this.selectedBandIndexes.Count; int rowEntry = 0; while (rowEntry < rowEntries) { int rowIndex = this.selectedBandIndexes[rowEntry]; if (rowIndexDeleted == rowIndex) { raiseSelectionChanged = true; this.selectedBandIndexes.RemoveAt(rowEntry); rowEntries--; } else { if (rowIndexDeleted < rowIndex) { this.selectedBandIndexes[rowEntry] = rowIndex - 1; } rowEntry++; } } if (this.selectedBandSnapshotIndexes != null) { rowEntries = this.selectedBandSnapshotIndexes.Count; rowEntry = 0; while (rowEntry < rowEntries) { int rowIndex = this.selectedBandSnapshotIndexes[rowEntry]; if (rowIndexDeleted == rowIndex) { this.selectedBandSnapshotIndexes.RemoveAt(rowEntry); rowEntries--; } else { if (rowIndexDeleted < rowIndex) { this.selectedBandSnapshotIndexes[rowEntry] = rowIndex - 1; } rowEntry++; } } } break; } this.dataGridViewState2[DATAGRIDVIEWSTATE2_raiseSelectionChanged] |= this.individualSelectedCells.RemoveAllCellsAtBand(false /*column*/, rowIndexDeleted) > 0 || raiseSelectionChanged; this.individualReadOnlyCells.RemoveAllCellsAtBand(false /*column*/, rowIndexDeleted); } internal void OnReplacedCell(DataGridViewRow dataGridViewRow, int columnIndex) { DataGridViewCell dataGridViewCell = dataGridViewRow.Cells[columnIndex]; if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_replacedCellSelected]) { this.individualSelectedCells.Add(dataGridViewCell); } if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_replacedCellReadOnly]) { this.individualReadOnlyCells.Add(dataGridViewCell); } // AutoSize column and row if needed OnCellCommonChange(columnIndex, dataGridViewRow.Index); if (this.ptCurrentCellCache.X != -1) { if (!IsInnerCellOutOfBounds(this.ptCurrentCellCache.X, this.ptCurrentCellCache.Y)) { SetCurrentCellAddressCore(this.ptCurrentCellCache.X, this.ptCurrentCellCache.Y, false, false, false); } this.ptCurrentCellCache.X = -1; this.ptCurrentCellCache.Y = -1; } } internal void OnReplacingCell(DataGridViewRow dataGridViewRow, int columnIndex) { if (this.ptCurrentCell.X == dataGridViewRow.Index && this.ptCurrentCell.Y == columnIndex) { // Trying to replace the current cell. Exiting editing mode first (if needed). // Remember to reset the current cell in OnReplacedCell notification this.ptCurrentCellCache.X = this.ptCurrentCell.X; this.ptCurrentCellCache.Y = this.ptCurrentCell.Y; // This may fail and throw an exception ResetCurrentCell(); } else { this.ptCurrentCellCache.X = -1; this.ptCurrentCellCache.Y = -1; } DataGridViewCell dataGridViewCell = dataGridViewRow.Cells[columnIndex]; this.dataGridViewState2[DATAGRIDVIEWSTATE2_replacedCellSelected] = this.individualSelectedCells.Contains(dataGridViewCell); if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_replacedCellSelected]) { this.individualSelectedCells.Remove(dataGridViewCell); } this.dataGridViewState2[DATAGRIDVIEWSTATE2_replacedCellReadOnly] = this.individualReadOnlyCells.Contains(dataGridViewCell); if (this.dataGridViewState2[DATAGRIDVIEWSTATE2_replacedCellReadOnly]) { this.individualReadOnlyCells.Remove(dataGridViewCell); } } /// protected override void OnResize(EventArgs e) { int borderWidth = this.BorderWidth; Rectangle right; Rectangle bottom; Rectangle oldClientRectangle = this.layout.ClientRectangle; right = new Rectangle(oldClientRectangle.X + oldClientRectangle.Width - borderWidth, oldClientRectangle.Y, borderWidth, oldClientRectangle.Height); bottom = new Rectangle(oldClientRectangle.X, oldClientRectangle.Y + oldClientRectangle.Height - borderWidth, oldClientRectangle.Width, borderWidth); if (!this.IsMinimized) { // When owning form is minimized, act as if it had a normal size this.normalClientRectangle = this.ClientRectangle; } Rectangle newClientRectangle = this.normalClientRectangle; if (newClientRectangle.Width != oldClientRectangle.Width) { Invalidate(right); right = new Rectangle(newClientRectangle.X + newClientRectangle.Width - borderWidth, newClientRectangle.Y, borderWidth, newClientRectangle.Height); Invalidate(right); } if (newClientRectangle.Height != oldClientRectangle.Height) { Invalidate(bottom); bottom = new Rectangle(newClientRectangle.X, newClientRectangle.Y + newClientRectangle.Height - borderWidth, newClientRectangle.Width, borderWidth); Invalidate(bottom); } //also, invalidate the ResizeBoxRect if (!this.layout.ResizeBoxRect.IsEmpty) { Invalidate(this.layout.ResizeBoxRect); } this.layout.ClientRectangle = newClientRectangle; int oldfirstDisplayedScrollingRow = this.displayedBandsInfo.FirstDisplayedScrollingRow; base.OnResize(e); if (oldfirstDisplayedScrollingRow != this.displayedBandsInfo.FirstDisplayedScrollingRow) { Invalidate(); } } /// protected override void OnRightToLeftChanged(EventArgs e) { this.dataGridViewState2[DATAGRIDVIEWSTATE2_rightToLeftValid] = false; base.OnRightToLeftChanged(e); CorrectFocus(true /*onlyIfGridHasFocus*/); PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); } internal void OnRowCollectionChanged_PostNotification(bool recreateNewRow, bool allowSettingCurrentCell, CollectionChangeAction cca, DataGridViewRow dataGridViewRow, int rowIndex) { if (recreateNewRow && cca == CollectionChangeAction.Refresh && this.Columns.Count != 0 && this.Rows.Count == 0 && this.AllowUserToAddRowsInternal) { AddNewRow(false); } if (cca == CollectionChangeAction.Refresh) { FlushSelectionChanged(); } if ((cca == CollectionChangeAction.Refresh || cca == CollectionChangeAction.Add) && this.ptCurrentCell.X == -1 && allowSettingCurrentCell && !this.InSortOperation) { MakeFirstDisplayedCellCurrentCell(false /*includeNewRow*/); } if (this.AutoSize) { bool invalidatePreferredSizeCache = true; switch (cca) { case CollectionChangeAction.Add: Debug.Assert(rowIndex >= 0); DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex); invalidatePreferredSizeCache = ((rowState & DataGridViewElementStates.Visible) != 0); break; case CollectionChangeAction.Remove: invalidatePreferredSizeCache = dataGridViewRow.DataGridView == null && dataGridViewRow.Visible; break; // case CollectionChangeAction.Refresh: invalidatePreferredSizeCache stays true } if (invalidatePreferredSizeCache) { LayoutTransaction.DoLayout(this.ParentInternal, this, PropertyNames.Rows); } } } /// protected virtual void OnRowContextMenuStripChanged(DataGridViewRowEventArgs e) { if (e.Row.DataGridView != this) { throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row"); } DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWCONTEXTMENUSTRIPCHANGED] as DataGridViewRowEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal ContextMenuStrip OnRowContextMenuStripNeeded(int rowIndex, ContextMenuStrip contextMenuStrip) { DataGridViewRowContextMenuStripNeededEventArgs dgvrcmsne = new DataGridViewRowContextMenuStripNeededEventArgs(rowIndex, contextMenuStrip); OnRowContextMenuStripNeeded(dgvrcmsne); return dgvrcmsne.ContextMenuStrip; } /// protected virtual void OnRowContextMenuStripNeeded(DataGridViewRowContextMenuStripNeededEventArgs e) { DataGridViewRowContextMenuStripNeededEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWCONTEXTMENUSTRIPNEEDED] as DataGridViewRowContextMenuStripNeededEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnRowDefaultCellStyleChanged(DataGridViewRowEventArgs e) { if (e.Row.DataGridView != this) { throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row"); } OnRowGlobalAutoSize(e.Row.Index); DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWDEFAULTCELLSTYLECHANGED] as DataGridViewRowEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnRowDirtyStateNeeded(QuestionEventArgs e) { QuestionEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWDIRTYSTATENEEDED] as QuestionEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnRowDividerDoubleClick(DataGridViewRowDividerDoubleClickEventArgs e) { DataGridViewRowDividerDoubleClickEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWDIVIDERDOUBLECLICK] as DataGridViewRowDividerDoubleClickEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } if (!e.Handled && e.Button == MouseButtons.Left && e.RowIndex < this.Rows.Count) { if (e.RowIndex == -1) { AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/); } else { if (this.autoSizeRowsMode == DataGridViewAutoSizeRowsMode.None) { AutoResizeRowInternal(e.RowIndex, DataGridViewAutoSizeRowMode.AllCells, true /*fixedWidth*/, true /*internalAutosizing*/); } else { AutoResizeRowInternal(e.RowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), true /*fixedWidth*/, true /*internalAutosizing*/); } } } } /// protected virtual void OnRowDividerHeightChanged(DataGridViewRowEventArgs e) { if (e.Row.DataGridView != this) { throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row"); } OnRowGlobalAutoSize(e.Row.Index); DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWDIVIDERHEIGHTCHANGED] as DataGridViewRowEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } private void OnRowEnter(ref DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex, bool canCreateNewRow, bool validationFailureOccurred) { Debug.Assert(columnIndex >= 0 && rowIndex >= 0); if (!validationFailureOccurred) { this.dataGridViewState1[DATAGRIDVIEWSTATE1_newRowEdited] = false; } if (rowIndex < this.Rows.Count && columnIndex < this.Columns.Count) { bool calledAddNewOnTheDataConnection = false; if (!validationFailureOccurred && this.AllowUserToAddRowsInternal && this.newRowIndex == rowIndex) { this.dataGridViewState1[DATAGRIDVIEWSTATE1_newRowEdited] = true; if (canCreateNewRow) { DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs(this.Rows[this.newRowIndex]); if (this.VirtualMode || this.DataSource != null) { if (this.dataConnection != null && this.dataConnection.InterestedInRowEvents) { this.dataConnection.OnNewRowNeeded(); calledAddNewOnTheDataConnection = true; } if (this.VirtualMode) { OnNewRowNeeded(dgvre); } } // vsWhidbey 329429: AllowUserToAddRowsInternal can become FALSE while adding a row. // NOTE: we don't need to invalidate if AllowUserToAddRowsInternal changed to FALSE. // if (this.AllowUserToAddRowsInternal) { OnDefaultValuesNeeded(dgvre); InvalidateRowPrivate(this.newRowIndex); } #if DEBUG else { Debug.Assert(this.newRowIndex == -1, "newRowIndex and AllowUserToAddRowsInternal became out of [....]"); } #endif // } } if (calledAddNewOnTheDataConnection && rowIndex > this.Rows.Count - 1) { // Calling AddNew on the DataConnection can result in the entire list being wiped out. // rowIndex = Math.Min(rowIndex, this.Rows.Count - 1); } DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(columnIndex, rowIndex); OnRowEnter(dgvce); if (this.dataConnection != null && this.dataConnection.InterestedInRowEvents && !this.dataConnection.PositionChangingOutsideDataGridView && !this.dataConnection.ListWasReset && (!calledAddNewOnTheDataConnection || this.dataConnection.List.Count > 0)) { this.dataConnection.OnRowEnter(dgvce); } if (dataGridViewCell != null) { if (IsInnerCellOutOfBounds(columnIndex, rowIndex)) { dataGridViewCell = null; } else { Debug.Assert(rowIndex < this.Rows.Count && columnIndex < this.Columns.Count); dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex]; } } } } /// protected virtual void OnRowEnter(DataGridViewCellEventArgs e) { try { this.noDimensionChangeCount++; DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWENTER] as DataGridViewCellEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); CorrectFocus(true /*onlyIfGridHasFocus*/); } } finally { this.noDimensionChangeCount--; Debug.Assert(this.noDimensionChangeCount >= 0); } } internal void OnRowErrorTextChanged(DataGridViewRow dataGridViewRow) { DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs(dataGridViewRow); OnRowErrorTextChanged(dgvre); } /// protected virtual void OnRowErrorTextChanged(DataGridViewRowEventArgs e) { if (e.Row.DataGridView != this) { throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row"); } UpdateRowErrorText(e.Row.Index); DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWERRORTEXTCHANGED] as DataGridViewRowEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal string OnRowErrorTextNeeded(int rowIndex, string errorText) { Debug.Assert(rowIndex >= 0); DataGridViewRowErrorTextNeededEventArgs dgvretne = new DataGridViewRowErrorTextNeededEventArgs(rowIndex, errorText); OnRowErrorTextNeeded(dgvretne); return dgvretne.ErrorText; } /// protected virtual void OnRowErrorTextNeeded(DataGridViewRowErrorTextNeededEventArgs e) { DataGridViewRowErrorTextNeededEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWERRORTEXTNEEDED] as DataGridViewRowErrorTextNeededEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } private void OnRowGlobalAutoSize(int rowIndex) { DataGridViewElementStates rowState = this.Rows.GetRowState(rowIndex); if ((rowState & DataGridViewElementStates.Visible) == 0) { return; } InvalidateRowPrivate(rowIndex); if (this.noAutoSizeCount > 0) { return; } DataGridViewAutoSizeRowsModeInternal autoSizeRowsModeInternal = (DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode; bool autoSizeRow = false; bool rowDisplayed = (rowState & DataGridViewElementStates.Displayed) != 0; if (autoSizeRowsModeInternal != DataGridViewAutoSizeRowsModeInternal.None && !((autoSizeRowsModeInternal & DataGridViewAutoSizeRowsModeInternal.DisplayedRows) != 0 && !rowDisplayed)) { AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), false /*fixedWidth*/, true /*internalAutosizing*/); autoSizeRow = true; } // Auto size columms also if needed DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFilter = DataGridViewAutoSizeColumnCriteriaInternal.AllRows; if (rowDisplayed) { autoSizeColumnCriteriaFilter |= DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows; } AutoResizeAllVisibleColumnsInternal(autoSizeColumnCriteriaFilter, true /*fixedHeight*/); bool fixedRowHeadersWidth = this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing || this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.DisableResizing; // Auto size column headers if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) { AutoResizeColumnHeadersHeight(fixedRowHeadersWidth, true /*fixedColumnsWidth*/); } // Auto size row headers if (!fixedRowHeadersWidth) { AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, true /*fixedRowsHeight*/); } if (autoSizeRow) { // Second round of row autosizing AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), true /*fixedWidth*/, true /*internalAutosizing*/); } if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize && !fixedRowHeadersWidth) { // Second round of column headers autosizing AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/); } } /// protected virtual void OnRowHeaderCellChanged(DataGridViewRowEventArgs e) { if (e.Row.DataGridView != this) { throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row"); } OnRowHeaderGlobalAutoSize(e.Row.Index); DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEADERCELLCHANGED] as DataGridViewRowEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } private void OnRowHeaderGlobalAutoSize(int rowIndex) { if (!this.RowHeadersVisible) { return; } InvalidateCellPrivate(-1, rowIndex); if (this.noAutoSizeCount > 0) { return; } bool rowDisplayed = false; if (rowIndex != -1) { rowDisplayed = (this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Displayed) != 0; } bool fixedColumnHeadersHeight = rowIndex != -1 || this.ColumnHeadersHeightSizeMode != DataGridViewColumnHeadersHeightSizeMode.AutoSize; bool fixedRowHeight = rowIndex == -1 || ((((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.Header) == 0) || ((((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.DisplayedRows) != 0 && rowIndex != -1 && !rowDisplayed); bool autoSizeRowHeaders = false; if (this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders || (this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders && rowIndex != -1 && rowDisplayed) || (this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.EnableResizing && this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.DisableResizing && rowIndex == -1) || (this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.AutoSizeToFirstHeader && rowIndex != -1 && rowIndex == this.Rows.GetFirstRow(DataGridViewElementStates.Visible))) { AutoResizeRowHeadersWidth(rowIndex, this.rowHeadersWidthSizeMode, fixedColumnHeadersHeight, fixedRowHeight); autoSizeRowHeaders = true; } if (!fixedColumnHeadersHeight) { AutoResizeColumnHeadersHeight(-1, true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/); } if (!fixedRowHeight) { AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), true /*fixedWidth*/, true /*internalAutosizing*/); } if (autoSizeRowHeaders && (!fixedColumnHeadersHeight || !fixedRowHeight)) { // Second round of row headers autosizing AutoResizeRowHeadersWidth(rowIndex, this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, true /*fixedRowHeight*/); } } /// protected virtual void OnRowHeaderMouseClick(DataGridViewCellMouseEventArgs e) { DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEADERMOUSECLICK] as DataGridViewCellMouseEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnRowHeaderMouseDoubleClick(DataGridViewCellMouseEventArgs e) { DataGridViewCellMouseEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEADERMOUSEDOUBLECLICK] as DataGridViewCellMouseEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } private void OnRowHeaderMouseDown(HitTestInfo hti, bool isShiftDown, bool isControlDown) { Debug.Assert(hti.Type == DataGridViewHitTestType.RowHeader); this.noSelectionChangeCount++; try { switch (this.SelectionMode) { case DataGridViewSelectionMode.CellSelect: case DataGridViewSelectionMode.FullColumnSelect: case DataGridViewSelectionMode.ColumnHeaderSelect: break; case DataGridViewSelectionMode.FullRowSelect: case DataGridViewSelectionMode.RowHeaderSelect: { bool select = true; if (isControlDown && ((this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Selected) != 0)) { select = false; } if (select) { DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible); if (dataGridViewColumn != null && hti.row != this.ptCurrentCell.Y) { int oldCurrentCellX = this.ptCurrentCell.X; int oldCurrentCellY = this.ptCurrentCell.Y; // Make sure we will be able to scroll into view if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.CurrentCellChange, DataGridViewValidateCellInternal.Always /*validateCell*/, true /*fireCellLeave*/, true /*fireCellEnter*/, hti.row != this.ptCurrentCell.Y /*fireRowLeave*/, hti.row != this.ptCurrentCell.Y /*fireRowEnter*/, false /*fireLeave*/, this.EditMode != DataGridViewEditMode.EditOnEnter /*keepFocus*/, true /*resetCurrentCell*/, false /*resetAnchorCell*/)) { // Just cancel operation silently instead of throwing InvalidOperationException return; } if (oldCurrentCellY != -1) { DataGridViewCell dataGridViewCellTmp = null; if (IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) { return; } if (OnRowValidating(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY)) { // Row validation was cancelled if (IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) { return; } OnRowEnter(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY, true /*canCreateNewRow*/, true /*validationFailureOccurred*/); if (IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) { return; } OnCellEnter(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY); return; } if (IsInnerCellOutOfBounds(oldCurrentCellX, oldCurrentCellY)) { return; } OnRowValidated(ref dataGridViewCellTmp, oldCurrentCellX, oldCurrentCellY); // Row validation was not cancelled, but operation needs to be re-evaluated. if (hti.row >= this.Rows.Count) { int lastVisibleRowIndex = this.Rows.GetLastRow(DataGridViewElementStates.Visible); if (this.ptCurrentCell.X == -1 && lastVisibleRowIndex != -1) { // CurrentCell was reset because commit deleted row(s). // Since the user wants to select a row, we don't want to // end up with no CurrentCell. We pick the last visible // row in the grid which may be the 'new row'. if (IsColumnOutOfBounds(oldCurrentCellX)) { return; } bool success = SetAndSelectCurrentCellAddress(oldCurrentCellX, lastVisibleRowIndex, true, false, false, false /*clearSelection*/, false /*forceCurrentCellSelection*/); Debug.Assert(success); } return; } else if ((this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Visible) == 0) { return; } } } bool selectRowRange = false; this.trackRow = hti.row; this.trackRowEdge = -1; if (this.MultiSelect && isShiftDown && this.ptAnchorCell.Y > -1 && (this.Rows.GetRowState(this.ptAnchorCell.Y) & DataGridViewElementStates.Selected) != 0) { selectRowRange = true; } if (!this.MultiSelect || !isControlDown || isShiftDown) { Debug.Assert(this.MultiSelect || this.selectedBandIndexes.Count <= 1); int bandIndex = 0; bool switchedToBulkPaint = false; if (this.selectedBandIndexes.Count > DATAGRIDVIEW_bulkPaintThreshold) { this.inBulkPaintCount++; switchedToBulkPaint = true; } try { while (bandIndex < this.selectedBandIndexes.Count) { if (this.selectedBandIndexes[bandIndex] != hti.row) { // deselect currently selected row SetSelectedRowCore(this.selectedBandIndexes[bandIndex], false); } else { bandIndex++; } } if (this.SelectionMode == DataGridViewSelectionMode.RowHeaderSelect) { RemoveIndividuallySelectedCells(); } else { Debug.Assert(this.individualSelectedCells.Count == 0); } } finally { if (switchedToBulkPaint) { ExitBulkPaint(-1, -1); } } } if (this.MultiSelect && this.dataGridViewOper[DATAGRIDVIEWOPER_trackMouseMoves]) { this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowSelect] = true; } if (selectRowRange) { if (hti.row >= this.ptAnchorCell.Y) { SelectRowRange(this.ptAnchorCell.Y, hti.row, true); } else { SelectRowRange(hti.row, this.ptAnchorCell.Y, true); } } else if ((this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Selected) == 0) { Debug.Assert(this.selectedBandIndexes.Contains(hti.row) == ((this.Rows.GetRowState(hti.row) & DataGridViewElementStates.Selected) != 0)); SetSelectedRowCore(hti.row, true); } if (dataGridViewColumn != null) { if (hti.row != this.ptCurrentCell.Y) { if (IsInnerCellOutOfBounds(dataGridViewColumn.Index, hti.row)) { return; } // set current cell to the left most visible cell in the row bool success = ScrollIntoView(dataGridViewColumn.Index, hti.row, false); Debug.Assert(success); if (IsInnerCellOutOfBounds(dataGridViewColumn.Index, hti.row)) { return; } success = SetCurrentCellAddressCore(dataGridViewColumn.Index, hti.row, !selectRowRange, false, true); Debug.Assert(success); } else if (-1 != this.ptCurrentCell.Y) { // Potentially have to give focus back to the current edited cell. bool success = SetCurrentCellAddressCore(this.ptCurrentCell.X, this.ptCurrentCell.Y, false /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false /*throughMouseClick*/); Debug.Assert(success); } } else { Debug.Assert(this.CurrentCellAddress == new Point(-1, -1)); } } else { Debug.Assert(this.selectedBandIndexes.Contains(hti.row)); SetSelectedRowCore(hti.row, false); } break; } } } finally { this.NoSelectionChangeCount--; } } /// protected virtual void OnRowHeadersBorderStyleChanged(EventArgs e) { PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, false /*repositionEditingControl*/); Invalidate(); EventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEADERSBORDERSTYLECHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnRowHeadersDefaultCellStyleChanged(EventArgs e) { if (this.RowHeadersVisible) { Invalidate(Rectangle.Union(this.layout.TopLeftHeader, this.layout.RowHeaders)); DataGridViewCellStyleChangedEventArgs dgvcsce = e as DataGridViewCellStyleChangedEventArgs; if (dgvcsce == null || dgvcsce.ChangeAffectsPreferredSize) { OnRowHeadersGlobalAutoSize(false /*expandingRows*/); if (this.editingControl != null) { PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/); } } } EventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEADERSDEFAULTCELLSTYLECHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } private void OnRowHeadersGlobalAutoSize(bool expandingRows) { if (this.noAutoSizeCount > 0) { return; } bool fixedRowsHeight = (((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.Header) == 0 || !this.RowHeadersVisible; bool autoSizeRowHeaders = this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.EnableResizing && this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.DisableResizing; if (autoSizeRowHeaders) { AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, fixedRowsHeight); } if (!fixedRowsHeight) { if (expandingRows) { AdjustExpandingRows(-1, true /*fixedWidth*/); } else { AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); } if (autoSizeRowHeaders) { // Second round of row headers autosizing AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, true /*fixedRowsHeight*/); } } } /// protected virtual void OnRowHeadersWidthChanged(EventArgs e) { if (this.RowHeadersVisible) { if (this.editingControl != null) { PositionEditingControl(true, false, false); } UpdateMouseEnteredCell(null /*HitTestInfo*/, null /*MouseEventArgs*/); OnRowHeadersGlobalAutoSize(false /*expandingRows*/); } EventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEADERSWIDTHCHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnRowHeadersWidthSizeModeChanged(DataGridViewAutoSizeModeEventArgs e) { if (this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.EnableResizing && this.rowHeadersWidthSizeMode != DataGridViewRowHeadersWidthSizeMode.DisableResizing) { if (!e.PreviousModeAutoSized) { // Save current row headers width for later reuse this.cachedRowHeadersWidth = this.RowHeadersWidth; } AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, true /*fixedRowsHeight*/); } else if (e.PreviousModeAutoSized) { this.RowHeadersWidth = this.cachedRowHeadersWidth; } EventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEADERSWIDTHSIZEMODECHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnRowHeightChanged(DataGridViewRowEventArgs e) { if (e.Row.DataGridView != this) { throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row"); } UpdateRowHeightInfoPrivate(e.Row.Index, false, false /*invalidInAdjustFillingColumns*/); DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEIGHTCHANGED] as DataGridViewRowEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } OnRowGlobalAutoSize(e.Row.Index); } internal DataGridViewRowHeightInfoNeededEventArgs OnRowHeightInfoNeeded(int rowIndex, int height, int minimumHeight) { DataGridViewRowHeightInfoNeededEventArgs dgvrhine = this.RowHeightInfoNeededEventArgs; dgvrhine.SetProperties(rowIndex, height, minimumHeight); OnRowHeightInfoNeeded(dgvrhine); return dgvrhine; } /// protected virtual void OnRowHeightInfoNeeded(DataGridViewRowHeightInfoNeededEventArgs e) { DataGridViewRowHeightInfoNeededEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEIGHTINFONEEDED] as DataGridViewRowHeightInfoNeededEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } private bool OnRowHeightInfoPushed(int rowIndex, int height, int minimumHeight) { Debug.Assert(rowIndex != -1); Debug.Assert(this.autoSizeRowsMode == DataGridViewAutoSizeRowsMode.None); if (this.VirtualMode || this.DataSource != null) { DataGridViewRowHeightInfoPushedEventArgs dgvrhipe = new DataGridViewRowHeightInfoPushedEventArgs(rowIndex, height, minimumHeight); OnRowHeightInfoPushed(dgvrhipe); if (dgvrhipe.Handled) { UpdateRowHeightInfoPrivate(rowIndex, false, true /*invalidInAdjustFillingColumns*/); return true; } } return false; } /// protected virtual void OnRowHeightInfoPushed(DataGridViewRowHeightInfoPushedEventArgs e) { DataGridViewRowHeightInfoPushedEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWHEIGHTINFOPUSHED] as DataGridViewRowHeightInfoPushedEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } private void OnRowLeave(ref DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex) { Debug.Assert(columnIndex >= 0 && rowIndex >= 0); if (rowIndex < this.Rows.Count && columnIndex < this.Columns.Count) { DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(columnIndex, rowIndex); OnRowLeave(dgvce); if (dataGridViewCell != null) { if (IsInnerCellOutOfBounds(columnIndex, rowIndex)) { dataGridViewCell = null; } else { Debug.Assert(rowIndex < this.Rows.Count && columnIndex < this.Columns.Count); dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex]; } } } } /// protected virtual void OnRowLeave(DataGridViewCellEventArgs e) { try { this.noDimensionChangeCount++; DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWLEAVE] as DataGridViewCellEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); CorrectFocus(true /*onlyIfGridHasFocus*/); } } finally { this.noDimensionChangeCount--; Debug.Assert(this.noDimensionChangeCount >= 0); } } /// protected virtual void OnRowMinimumHeightChanged(DataGridViewRowEventArgs e) { if (e.Row.DataGridView != this) { throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row"); } DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWMINIMUMHEIGHTCHANGED] as DataGridViewRowEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected internal virtual void OnRowPostPaint(DataGridViewRowPostPaintEventArgs e) { DataGridViewRowPostPaintEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWPOSTPAINT] as DataGridViewRowPostPaintEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected internal virtual void OnRowPrePaint(DataGridViewRowPrePaintEventArgs e) { DataGridViewRowPrePaintEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWPREPAINT] as DataGridViewRowPrePaintEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal void OnRowsAddedInternal(int rowIndex, int rowCount) { OnRowsAdded(new DataGridViewRowsAddedEventArgs(rowIndex, rowCount)); } /// protected virtual void OnRowsAdded(DataGridViewRowsAddedEventArgs e) { DataGridViewRowsAddedEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWSADDED] as DataGridViewRowsAddedEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnRowsDefaultCellStyleChanged(EventArgs e) { DataGridViewCellStyleChangedEventArgs dgvcsce = e as DataGridViewCellStyleChangedEventArgs; if (dgvcsce != null && !dgvcsce.ChangeAffectsPreferredSize) { InvalidateData(); } else { OnRowsGlobalAutoSize(); if (this.editingControl != null) { PositionEditingControl(true /*setLocation*/, true /*setSize*/, false /*setFocus*/); } } EventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWSDEFAULTCELLSTYLECHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } private void OnRowSelectMouseMove(HitTestInfo hti) { Debug.Assert(hti.row >= 0); Debug.Assert(this.MultiSelect); if (this.ptCurrentCell.Y != -1 && hti.row != this.ptCurrentCell.Y && !CommitEditForOperation(this.ptCurrentCell.X, hti.row, true)) { // Return silently if validating/commit/abort failed return; } if (IsRowOutOfBounds(hti.row)) { return; } this.noSelectionChangeCount++; try { if (this.trackRowEdge >= this.trackRow && hti.row > this.trackRowEdge && this.trackRowEdge >= 0) { SelectRowRange(this.Rows.GetNextRow(this.trackRowEdge, DataGridViewElementStates.Visible), hti.row, true); this.trackRowEdge = hti.row; } else if (this.trackRowEdge > this.trackRow && hti.row < this.trackRowEdge && hti.row >= this.trackRow && this.trackRowEdge >= 0) { SelectRowRange(this.Rows.GetNextRow(hti.row, DataGridViewElementStates.Visible), this.trackRowEdge, false); this.trackRowEdge = hti.row; } else if (hti.row > this.trackRow && this.trackRowEdge == -1) { SelectRowRange(this.Rows.GetNextRow(this.trackRow, DataGridViewElementStates.Visible), hti.row, true); this.trackRowEdge = hti.row; } else if (this.trackRowEdge <= this.trackRow && hti.row < this.trackRowEdge && this.trackRowEdge >= 0) { SelectRowRange(hti.row, this.Rows.GetPreviousRow(this.trackRowEdge, DataGridViewElementStates.Visible), true); this.trackRowEdge = hti.row; } else if (this.trackRowEdge < this.trackRow && hti.row > this.trackRowEdge && hti.row <= this.trackRow && this.trackRowEdge >= 0) { SelectRowRange(this.trackRowEdge, this.Rows.GetPreviousRow(hti.row, DataGridViewElementStates.Visible), false); this.trackRowEdge = hti.row; } else if (hti.row < this.trackRow && this.trackRowEdge == -1) { SelectRowRange(hti.row, this.Rows.GetPreviousRow(this.trackRow, DataGridViewElementStates.Visible), true); this.trackRowEdge = hti.row; } else if (this.trackRowEdge > this.trackRow && hti.row < this.trackRow) { SelectRowRange(this.Rows.GetNextRow(this.trackRow, DataGridViewElementStates.Visible), this.trackRowEdge, false); SelectRowRange(hti.row, this.Rows.GetPreviousRow(this.trackRow, DataGridViewElementStates.Visible), true); this.trackRowEdge = hti.row; } else if (hti.row > this.trackRow && this.trackRowEdge < this.trackRow && this.trackRowEdge >= 0) { SelectRowRange(this.trackRowEdge, this.Rows.GetPreviousRow(this.trackRow, DataGridViewElementStates.Visible), false); SelectRowRange(this.Rows.GetNextRow(this.trackRow, DataGridViewElementStates.Visible), hti.row, true); this.trackRowEdge = hti.row; } } finally { this.NoSelectionChangeCount--; } if (this.ptCurrentCell.Y != -1 && hti.row != this.ptCurrentCell.Y) { if (IsRowOutOfBounds(hti.row)) { return; } bool success = SetCurrentCellAddressCore(this.ptCurrentCell.X, hti.row, false /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false /*throughMouseClick*/); Debug.Assert(success); } } private void OnRowsGlobalAutoSize() { InvalidateData(); if (this.noAutoSizeCount > 0) { return; } // Autosize rows if needed if ((((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0) { AdjustShrinkingRows(this.autoSizeRowsMode, false /*fixedWidth*/, true /*internalAutosizing*/); } // Auto size columms also if needed AutoResizeAllVisibleColumnsInternal(DataGridViewAutoSizeColumnCriteriaInternal.AllRows | DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows, true /*fixedHeight*/); bool fixedRowHeadersWidth = this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.EnableResizing || this.rowHeadersWidthSizeMode == DataGridViewRowHeadersWidthSizeMode.DisableResizing; // Auto size column headers if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) { AutoResizeColumnHeadersHeight(fixedRowHeadersWidth, true /*fixedColumnsWidth*/); } // Auto size row headers if (!fixedRowHeadersWidth) { AutoResizeRowHeadersWidth(this.rowHeadersWidthSizeMode, true /*fixedColumnHeadersHeight*/, true /*fixedRowsHeight*/); } // Second round of rows autosizing if ((((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0) { AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); } // Second round of column headers autosizing if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize && !fixedRowHeadersWidth) { AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnsWidth*/); } } internal void OnRowsRemovedInternal(int rowIndex, int rowCount) { OnRowsRemoved(new DataGridViewRowsRemovedEventArgs(rowIndex, rowCount)); } /// protected virtual void OnRowsRemoved(DataGridViewRowsRemovedEventArgs e) { DataGridViewRowsRemovedEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWSREMOVED] as DataGridViewRowsRemovedEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnRowStateChanged(int rowIndex, DataGridViewRowStateChangedEventArgs e) { Debug.Assert(rowIndex >= -1); // If row.Frozen changed, we need to update the vertical scroll bar // A hidden row may become visible and vice-versa, we'd better repaint the whole control DataGridViewRow dataGridViewRow = e.Row; DataGridViewElementStates newState = DataGridViewElementStates.None; bool rowVisible = false; if (rowIndex >= 0) { newState = this.Rows.GetRowState(rowIndex); rowVisible = ((newState & DataGridViewElementStates.Visible) != 0); } switch (e.StateChanged) { // At this point we assume that only the Selected state has an influence on the rendering of the row. // If there is a customer scenario where another state has an influence, the dev will have to invalidate the row by hand. // case DataGridViewElementStates.ReadOnly: // case DataGridViewElementStates.Resizable: case DataGridViewElementStates.Selected: if (rowVisible && this.inBulkPaintCount == 0) { InvalidateRowPrivate(rowIndex); } break; case DataGridViewElementStates.Frozen: if (rowVisible) { if ((newState & DataGridViewElementStates.Frozen) == 0) { // row was unfrozen - make it the first visible scrolling row if there is room FirstVisibleScrollingRowTempted(rowIndex); } PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, true /*repositionEditingControl*/); Invalidate(); } break; case DataGridViewElementStates.Visible: { if (!rowVisible && (newState & DataGridViewElementStates.Displayed) != 0) { // Displayed row becomes invisible. Turns off the Displayed state. this.Rows.SetRowState(rowIndex, DataGridViewElementStates.Displayed, false); } PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, true /*invalidInAdjustFillingColumns*/, true /*repositionEditingControl*/); Invalidate(); bool rowDisplayed = (this.Rows.GetRowState(rowIndex) & DataGridViewElementStates.Displayed) != 0; DataGridViewAutoSizeRowsModeInternal autoSizeRowsModeInternal = (DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode; bool autoSizeRow = false; if (autoSizeRowsModeInternal != DataGridViewAutoSizeRowsModeInternal.None) { int height = dataGridViewRow.ThicknessInternal; if (rowVisible) { // Cache row's height before potential autosizing occurs // Valid operation even for shared rows dataGridViewRow.CachedThickness = height; if (!((autoSizeRowsModeInternal & DataGridViewAutoSizeRowsModeInternal.DisplayedRows) != 0 && !rowDisplayed)) { AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), false /*fixedWidth*/, true /*internalAutosizing*/); autoSizeRow = true; } } else if (height != dataGridViewRow.CachedThickness) { // Rows that are made invisible in the collection take their non-autosized height // Not calling OnRowHeightInfoPushed(...) because rows are autosized // Make sure the affected row is unshared if (dataGridViewRow.Index == -1) { dataGridViewRow = this.Rows[rowIndex]; } dataGridViewRow.ThicknessInternal = Math.Max(dataGridViewRow.MinimumHeight, dataGridViewRow.CachedThickness); } } // Auto size columms also if needed DataGridViewAutoSizeColumnCriteriaInternal autoSizeColumnCriteriaFilter = DataGridViewAutoSizeColumnCriteriaInternal.AllRows; if (rowDisplayed) { autoSizeColumnCriteriaFilter |= DataGridViewAutoSizeColumnCriteriaInternal.DisplayedRows; } if (rowVisible && this.Rows.GetRowCount(DataGridViewElementStates.Visible) > 1) { // Columns can only expand, and not collapse. AdjustExpandingColumns(autoSizeColumnCriteriaFilter, rowIndex); } else { AutoResizeAllVisibleColumnsInternal(autoSizeColumnCriteriaFilter, true /*fixedHeight*/); } if (autoSizeRow) { // Second round of row autosizing AutoResizeRowInternal(rowIndex, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), true /*fixedWidth*/, true /*internalAutosizing*/); } break; } } DataGridViewRowStateChangedEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWSTATECHANGED] as DataGridViewRowStateChangedEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } if (e.StateChanged == DataGridViewElementStates.ReadOnly && rowIndex == this.ptCurrentCell.Y && !this.dataGridViewOper[DATAGRIDVIEWOPER_inReadOnlyChange]) { VerifyImeRestrictedModeChanged(); if ((newState & DataGridViewElementStates.ReadOnly) == 0 && !this.ReadOnly && !this.Columns[this.ptCurrentCell.X].ReadOnly && ColumnEditable(this.ptCurrentCell.X) && !this.IsCurrentCellInEditMode && (this.EditMode == DataGridViewEditMode.EditOnEnter || (this.EditMode != DataGridViewEditMode.EditProgrammatically && this.CurrentCellInternal.EditType == null))) { // Current row becomes read/write. Enter editing mode. BeginEditInternal(true /*selectAll*/); } } } internal void OnRowUnshared(DataGridViewRow dataGridViewRow) { if (-1 != this.ptCurrentCell.X && dataGridViewRow.Index == this.ptCurrentCell.Y && this.editingControl != null) { this.CurrentCellInternal.CacheEditingControl(); } DataGridViewRowEventArgs dgvre = new DataGridViewRowEventArgs(dataGridViewRow); OnRowUnshared(dgvre); } /// protected virtual void OnRowUnshared(DataGridViewRowEventArgs e) { if (e.Row.DataGridView != this) { throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row"); } DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWUNSHARED] as DataGridViewRowEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } private bool OnRowValidating(ref DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex) { DataGridViewCellCancelEventArgs dgvcce = new DataGridViewCellCancelEventArgs(columnIndex, rowIndex); OnRowValidating(dgvcce); if (!dgvcce.Cancel) { if (this.dataConnection != null && this.dataConnection.InterestedInRowEvents && !this.dataConnection.PositionChangingOutsideDataGridView && !this.dataConnection.ListWasReset) { this.dataConnection.OnRowValidating(dgvcce); } } if (dataGridViewCell != null && rowIndex < this.Rows.Count && columnIndex < this.Columns.Count) { dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex]; } return dgvcce.Cancel; } /// protected virtual void OnRowValidating(DataGridViewCellCancelEventArgs e) { try { this.noDimensionChangeCount++; DataGridViewCellCancelEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWVALIDATING] as DataGridViewCellCancelEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); CorrectFocus(true /*onlyIfGridHasFocus*/); } } finally { this.noDimensionChangeCount--; Debug.Assert(this.noDimensionChangeCount >= 0); } } private void OnRowValidated(ref DataGridViewCell dataGridViewCell, int columnIndex, int rowIndex) { this.IsCurrentRowDirtyInternal = false; this.dataGridViewState1[DATAGRIDVIEWSTATE1_newRowCreatedByEditing] = false; if (rowIndex == this.newRowIndex) { // Stop displaying the default cell values on the 'new row'. InvalidateRowPrivate(rowIndex); } DataGridViewCellEventArgs dgvce = new DataGridViewCellEventArgs(columnIndex, rowIndex); OnRowValidated(dgvce); if (dataGridViewCell != null) { if (IsInnerCellOutOfBounds(columnIndex, rowIndex)) { dataGridViewCell = null; } else { Debug.Assert(rowIndex < this.Rows.Count && columnIndex < this.Columns.Count); dataGridViewCell = this.Rows.SharedRow(rowIndex).Cells[columnIndex]; } } } /// protected virtual void OnRowValidated(DataGridViewCellEventArgs e) { try { this.noDimensionChangeCount++; DataGridViewCellEventHandler eh = this.Events[EVENT_DATAGRIDVIEWROWVALIDATED] as DataGridViewCellEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); CorrectFocus(true /*onlyIfGridHasFocus*/); } } finally { this.noDimensionChangeCount--; Debug.Assert(this.noDimensionChangeCount >= 0); } } private void OnScroll(ScrollEventType scrollEventType, int oldValue, int newValue, ScrollOrientation orientation) { ScrollEventArgs se = new ScrollEventArgs(scrollEventType, oldValue, newValue, orientation); OnScroll(se); if (ScrollOrientation.VerticalScroll == orientation) { if (se.NewValue != newValue) { try { this.dataGridViewState2[DATAGRIDVIEWSTATE2_stopRaisingVerticalScroll] = true; int rowIndex = this.Rows.GetFirstRow(DataGridViewElementStates.Visible, DataGridViewElementStates.Frozen); int rowIndexPrevious = rowIndex; newValue = se.NewValue; while (rowIndex != -1 && newValue > 0) { rowIndexPrevious = rowIndex; rowIndex = this.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible); newValue--; } if (rowIndex != -1) { rowIndexPrevious = rowIndex; } if (rowIndexPrevious != -1) { this.FirstDisplayedScrollingRowIndex = rowIndexPrevious; } } finally { this.dataGridViewState2[DATAGRIDVIEWSTATE2_stopRaisingVerticalScroll] = false; } } } else { if (se.NewValue != newValue) { try { this.dataGridViewState2[DATAGRIDVIEWSTATE2_stopRaisingHorizontalScroll] = true; this.HorizontalOffset = se.NewValue; } finally { this.dataGridViewState2[DATAGRIDVIEWSTATE2_stopRaisingHorizontalScroll] = false; } } } } /// protected virtual void OnScroll(ScrollEventArgs e) { ScrollEventHandler eh = this.Events[EVENT_DATAGRIDVIEWSCROLL] as ScrollEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnSelectionChanged(EventArgs e) { this.dataGridViewState2[DATAGRIDVIEWSTATE2_raiseSelectionChanged] = false; EventHandler eh = this.Events[EVENT_DATAGRIDVIEWSELECTIONCHANGED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal bool OnSortCompare(DataGridViewColumn dataGridViewSortedColumn, object value1, object value2, int rowIndex1, int rowIndex2, out int sortResult) { DataGridViewSortCompareEventArgs dgvsce = new DataGridViewSortCompareEventArgs(dataGridViewSortedColumn, value1, value2, rowIndex1, rowIndex2); OnSortCompare(dgvsce); sortResult = dgvsce.SortResult; return dgvsce.Handled; } /// protected virtual void OnSortCompare(DataGridViewSortCompareEventArgs e) { DataGridViewSortCompareEventHandler eh = this.Events[EVENT_DATAGRIDVIEWSORTCOMPARE] as DataGridViewSortCompareEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnSorted(EventArgs e) { EventHandler eh = this.Events[EVENT_DATAGRIDVIEWSORTED] as EventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } internal void OnSortGlyphDirectionChanged(DataGridViewColumnHeaderCell dataGridViewColumnHeaderCell) { Debug.Assert(dataGridViewColumnHeaderCell != null); if (dataGridViewColumnHeaderCell.OwningColumn == this.SortedColumn) { if (dataGridViewColumnHeaderCell.SortGlyphDirection == SortOrder.None) { this.sortedColumn = null; DataGridViewColumn dataGridViewColumn = dataGridViewColumnHeaderCell.OwningColumn; if (dataGridViewColumn.IsDataBound) { // If the column whose SortGlyphChanges is the sorted column and it is also the dataBound column // then see if there is another dataBound column which has the same property name as the sorted column. // If so, then make that dataGridViewColumn the sorted column in the data grid view. for (int i = 0; i < this.Columns.Count; i ++) { if (dataGridViewColumn != this.Columns[i] && this.Columns[i].SortMode != DataGridViewColumnSortMode.NotSortable && String.Compare(dataGridViewColumn.DataPropertyName, this.Columns[i].DataPropertyName, true /*ignoreCase*/, CultureInfo.InvariantCulture) == 0) { Debug.Assert(this.Columns[i].IsDataBound, "two columns w/ the same DataPropertyName should be DataBound at the same time"); this.sortedColumn = this.Columns[i]; break; } } } } this.sortOrder = this.sortedColumn != null ? this.sortedColumn.HeaderCell.SortGlyphDirection : SortOrder.None; } InvalidateCellPrivate(dataGridViewColumnHeaderCell); } private void OnTopLeftHeaderMouseDown() { if (this.MultiSelect) { SelectAll(); if (-1 != this.ptCurrentCell.X) { // Potentially have to give focus back to the current edited cell. bool success = SetCurrentCellAddressCore(this.ptCurrentCell.X, this.ptCurrentCell.Y, false /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false /*throughMouseClick*/); Debug.Assert(success); } } } /// protected virtual void OnUserAddedRow(DataGridViewRowEventArgs e) { if (e.Row.DataGridView != this) { throw new ArgumentException(SR.GetString(SR.DataGridView_RowDoesNotBelongToDataGridView), "e.Row"); } DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWUSERADDEDROW] as DataGridViewRowEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnUserDeletedRow(DataGridViewRowEventArgs e) { DataGridViewRowEventHandler eh = this.Events[EVENT_DATAGRIDVIEWUSERDELETEDROW] as DataGridViewRowEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } /// protected virtual void OnUserDeletingRow(DataGridViewRowCancelEventArgs e) { DataGridViewRowCancelEventHandler eh = this.Events[EVENT_DATAGRIDVIEWUSERDELETINGROW] as DataGridViewRowCancelEventHandler; if (eh != null && !this.dataGridViewOper[DATAGRIDVIEWOPER_inDispose] && !this.IsDisposed) { eh(this, e); } } private void OnUserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e) { if (e.Category == UserPreferenceCategory.Color || e.Category == UserPreferenceCategory.Locale || e.Category == UserPreferenceCategory.General || e.Category == UserPreferenceCategory.Window || e.Category == UserPreferenceCategory.VisualStyle) { OnGlobalAutoSize(); if (e.Category == UserPreferenceCategory.Window) { this.cachedEditingControl = null; if (this.editingControl != null) { // The editing control may not adapt well to the new system rendering, // so instead of caching it into the this.cachedEditingControl variable // next time editing mode is exited, simply discard the control. this.dataGridViewState2[DATAGRIDVIEWSTATE2_discardEditingControl] = true; } PerformLayoutPrivate(false /*useRowShortcut*/, false /*computeVisibleRows*/, false /*invalidInAdjustFillingColumns*/, true /*repositionEditingControl*/); } } } /// protected override void OnValidating(CancelEventArgs e) { // VSWhidbey 481170. Avoid Cell/Row Validation events when the grid or its editing control gets the focus if (!this.BecomingActiveControl && (this.editingControl == null || !this.editingControl.BecomingActiveControl)) { if (!this.dataGridViewState1[DATAGRIDVIEWSTATE1_leavingWithTabKey]) { if (!EndEdit(DataGridViewDataErrorContexts.Parsing | DataGridViewDataErrorContexts.Commit | DataGridViewDataErrorContexts.LeaveControl, DataGridViewValidateCellInternal.Always, false /*fireCellLeave*/, false /*fireCellEnter*/, false /*fireRowLeave*/, false /*fireRowEnter*/, false /*fireLeave*/, false /*keepFocus*/, false /*resetCurrentCell*/, false /*resetAnchorCell unused here*/)) { e.Cancel = true; return; } } if (this.ptCurrentCell.X >= 0) { DataGridViewCell dataGridViewCellTmp = null; if (OnRowValidating(ref dataGridViewCellTmp, this.ptCurrentCell.X, this.ptCurrentCell.Y)) { // Row validation was cancelled e.Cancel = true; return; } if (this.ptCurrentCell.X == -1) { return; } OnRowValidated(ref dataGridViewCellTmp, this.ptCurrentCell.X, this.ptCurrentCell.Y); // Row validation was not cancelled, but does operation need to be re-evaluated. if (this.DataSource != null && this.ptCurrentCell.X >= 0 && this.AllowUserToAddRowsInternal && this.newRowIndex == this.ptCurrentCell.Y) { // Current cell needs to be moved to the row just above the 'new row' if possible. int rowIndex = this.Rows.GetPreviousRow(this.ptCurrentCell.Y, DataGridViewElementStates.Visible); if (rowIndex > -1) { bool success = SetAndSelectCurrentCellAddress(this.ptCurrentCell.X, rowIndex, true /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false /*throughMouseClick*/, false /*clearSelection*/, false /*forceCurrentCellSelection*/); Debug.Assert(success); } else { bool success = SetCurrentCellAddressCore(-1, -1, true /*setAnchorCellAddress*/, false /*validateCurrentCell*/, false /*throughMouseClick*/); Debug.Assert(success); } } } } base.OnValidating(e); } protected override void OnVisibleChanged(EventArgs e) { base.OnVisibleChanged(e); OnVisibleChangedPrivate(); } private void OnVisibleChangedPrivate() { // Debug.Assert(!this.displayedBandsInfo.Dirty); Not valid because EnsureDirtyState can potentially be called // for example when RowHeadersVisible is changed while the control is invisible. int rowIndexTmp; if (this.Visible) { // Make sure all displayed bands get the Displayed state: 1 & 2 for rows // 1. Make sure all displayed frozen rows have their Displayed state set to true int numDisplayedFrozenRows = this.displayedBandsInfo.NumDisplayedFrozenRows; if (numDisplayedFrozenRows > 0) { rowIndexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); while (numDisplayedFrozenRows > 0) { Debug.Assert(rowIndexTmp != -1); if ((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) != 0) { #if DEBUG int numDisplayedFrozenRowsDbg = numDisplayedFrozenRows; while (numDisplayedFrozenRowsDbg > 0) { Debug.Assert(rowIndexTmp != -1); Debug.Assert((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) != 0); rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); numDisplayedFrozenRowsDbg--; } #endif return; // rows' Displayed states are already up-to-date. OnHandleCreated already did the job. } else { this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, true); rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); numDisplayedFrozenRows--; } } } // 2. Make sure all displayed scrolling rows have their Displayed state set to true rowIndexTmp = this.displayedBandsInfo.FirstDisplayedScrollingRow; if (rowIndexTmp > -1) { Debug.Assert((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Visible) != 0); int numDisplayedScrollingRows = this.displayedBandsInfo.NumDisplayedScrollingRows; Debug.Assert(numDisplayedScrollingRows > 0); while (numDisplayedScrollingRows > 0) { Debug.Assert(rowIndexTmp != -1); if ((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) != 0) { #if DEBUG int numDisplayedScrollingRowsDbg = numDisplayedScrollingRows; while (numDisplayedScrollingRowsDbg > 0) { Debug.Assert(rowIndexTmp != -1); Debug.Assert((this.Rows.GetRowState(rowIndexTmp) & DataGridViewElementStates.Displayed) != 0); rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible); numDisplayedScrollingRowsDbg--; } #endif return; // rows' Displayed states are already up-to-date. OnHandleCreated already did the job. } else { this.Rows.SetRowState(rowIndexTmp, DataGridViewElementStates.Displayed, true); rowIndexTmp = this.Rows.GetNextRow(rowIndexTmp, DataGridViewElementStates.Visible); numDisplayedScrollingRows--; } } } } else { // Make sure all displayed bands lose the Displayed state UpdateRowsDisplayedState(false /*displayed*/); } UpdateColumnsDisplayedState(this.Visible /*displayed*/); } /// protected virtual void PaintBackground(Graphics graphics, Rectangle clipBounds, Rectangle gridBounds) { // Paint potential block below rows Rectangle rcBelowRows = gridBounds; // Fix Dev10 Bug473771 - Remaining cell images on DataGridView int visibleRowsHeight = this.Rows.GetRowsHeight(DataGridViewElementStates.Displayed); if (this.layout.ColumnHeadersVisible) { rcBelowRows.Y += this.layout.ColumnHeaders.Height; rcBelowRows.Height -= this.layout.ColumnHeaders.Height; } else if (this.SingleHorizontalBorderAdded && visibleRowsHeight > 0) { rcBelowRows.Y++; rcBelowRows.Height--; } rcBelowRows.Y += visibleRowsHeight; rcBelowRows.Height -= visibleRowsHeight; if (rcBelowRows.Width > 0 && rcBelowRows.Height > 0) { graphics.FillRectangle(this.backgroundBrush, rcBelowRows); } // Paint potential block next to column headers and rows // Fix Dev10 Bug473771 - Remaining cell images on DataGridView int visibleColumnsWidth = this.Columns.GetColumnsWidth(DataGridViewElementStates.Displayed); Rectangle rcNextRows = gridBounds; if (this.Columns.Count > 0) { if (this.layout.RowHeadersVisible) { if (!this.RightToLeftInternal) { rcNextRows.X += this.layout.RowHeaders.Width; } rcNextRows.Width -= this.layout.RowHeaders.Width; } else if (this.SingleVerticalBorderAdded && visibleColumnsWidth > 0) { if (!this.RightToLeftInternal) { rcNextRows.X++; } rcNextRows.Width--; } } int rowsWidth = visibleColumnsWidth - this.horizontalOffset; if (!this.RightToLeftInternal) { rcNextRows.X += rowsWidth; } rcNextRows.Width -= rowsWidth; if (rcBelowRows.Height > 0) { rcNextRows.Height = gridBounds.Height - rcBelowRows.Height; } if (rcNextRows.Width > 0 && rcNextRows.Height > 0) { graphics.FillRectangle(this.backgroundBrush, rcNextRows); } } private void PaintBorder(Graphics g, Rectangle clipRect, Rectangle bounds) { Debug.Assert(bounds.Left == 0); Debug.Assert(bounds.Top == 0); if (this.BorderStyle == BorderStyle.None) { return; } bool paintingNeeded = false; int borderWidth = this.BorderWidth; // Does the clipRect intersect with the top edge? Rectangle edge = new Rectangle(0, 0, bounds.Width, borderWidth); paintingNeeded = clipRect.IntersectsWith(edge); if (!paintingNeeded) { // Does the clipRect intersect with the bottom edge? edge.Y = bounds.Height - borderWidth; paintingNeeded = clipRect.IntersectsWith(edge); if (!paintingNeeded) { // Does the clipRect intersect with the left edge? edge.Y = 0; edge.Height = bounds.Height; edge.Width = borderWidth; paintingNeeded = clipRect.IntersectsWith(edge); if (!paintingNeeded) { // Does the clipRect intersect with the right edge? edge.X = bounds.Width - borderWidth; paintingNeeded = clipRect.IntersectsWith(edge); } } } if (paintingNeeded) { if (this.BorderStyle == BorderStyle.Fixed3D) { if (Application.RenderWithVisualStyles) { Pen pen = GetCachedPen(VisualStyleInformation.TextControlBorder); g.DrawRectangle(pen, new Rectangle(0, 0, bounds.Width - 1, bounds.Height - 1)); } else { ControlPaint.DrawBorder3D(g, bounds, Border3DStyle.Sunken); } } else if (this.BorderStyle == BorderStyle.FixedSingle) { Pen pen = GetCachedPen(SystemColors.ControlText); g.DrawRectangle(pen, new Rectangle(0, 0, bounds.Width - 1, bounds.Height - 1)); } else { Debug.Fail("DataGridView.PaintBorder - Unexpected BorderStyle value."); } } } private void PaintColumnHeaders(Graphics g, Rectangle clipBounds, bool singleBorderAdded) { if (g.IsVisible(this.layout.ColumnHeaders)) { Rectangle bandBounds, cellBounds; bandBounds = cellBounds = this.layout.ColumnHeaders; bandBounds.Height = cellBounds.Height = this.columnHeadersHeight; int cx = 0; bool isFirstDisplayedColumn = true, isLastVisibleColumn = false; DataGridViewCell cell; DataGridViewCellStyle inheritedCellStyle = new DataGridViewCellStyle(); DataGridViewAdvancedBorderStyle dataGridViewAdvancedBorderStylePlaceholder = new DataGridViewAdvancedBorderStyle(), dgvabsEffective; DataGridViewColumn dataGridViewColumnNext = null; // first paint the visible frozen columns DataGridViewColumn dataGridViewColumn = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); while (dataGridViewColumn != null) { cell = dataGridViewColumn.HeaderCell; cellBounds.Width = dataGridViewColumn.Thickness; if (singleBorderAdded && isFirstDisplayedColumn) { cellBounds.Width++; } Debug.Assert(cellBounds.Width > 0); if (this.RightToLeftInternal) { cellBounds.X = bandBounds.Right - cx - cellBounds.Width; } else { cellBounds.X = bandBounds.X + cx; } BuildInheritedColumnHeaderCellStyle(inheritedCellStyle, cell); dataGridViewColumnNext = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen, DataGridViewElementStates.None); if (dataGridViewColumnNext == null) { isLastVisibleColumn = (this.displayedBandsInfo.FirstDisplayedScrollingCol < 0); } dgvabsEffective = AdjustColumnHeaderBorderStyle(this.AdvancedColumnHeadersBorderStyle, dataGridViewAdvancedBorderStylePlaceholder, isFirstDisplayedColumn, isLastVisibleColumn); // [....]: should paintSelectionBackground be dev-settable? cell.PaintWork(g, clipBounds, cellBounds, -1, dataGridViewColumn.State, inheritedCellStyle, dgvabsEffective, DataGridViewPaintParts.Background | DataGridViewPaintParts.Border | DataGridViewPaintParts.ContentBackground | DataGridViewPaintParts.ContentForeground | DataGridViewPaintParts.ErrorIcon | DataGridViewPaintParts.SelectionBackground); cx += cellBounds.Width; if (cx >= bandBounds.Width) { break; } dataGridViewColumn = dataGridViewColumnNext; isFirstDisplayedColumn = false; } // then paint the visible scrolling ones Rectangle scrollingBounds = bandBounds; if (!this.RightToLeftInternal) { scrollingBounds.X -= this.negOffset; } scrollingBounds.Width += this.negOffset; if (this.displayedBandsInfo.FirstDisplayedScrollingCol >= 0 && cx < scrollingBounds.Width) { Region clipRegion = null; if (this.negOffset > 0) { clipRegion = g.Clip; Rectangle rowRect = bandBounds; if (!this.RightToLeftInternal) { rowRect.X += cx; } rowRect.Width -= cx; g.SetClip(rowRect); } dataGridViewColumn = this.Columns[this.displayedBandsInfo.FirstDisplayedScrollingCol]; while (dataGridViewColumn != null) { Debug.Assert(dataGridViewColumn.Visible && !dataGridViewColumn.Frozen); cell = dataGridViewColumn.HeaderCell; cellBounds.Width = dataGridViewColumn.Thickness; if (singleBorderAdded && isFirstDisplayedColumn) { cellBounds.Width++; } Debug.Assert(cellBounds.Width > 0); if (this.RightToLeftInternal) { cellBounds.X = scrollingBounds.Right - cx - cellBounds.Width; } else { cellBounds.X = scrollingBounds.X + cx; } BuildInheritedColumnHeaderCellStyle(inheritedCellStyle, cell); dataGridViewColumnNext = this.Columns.GetNextColumn(dataGridViewColumn, DataGridViewElementStates.Visible, DataGridViewElementStates.None); isLastVisibleColumn = (dataGridViewColumnNext == null); dgvabsEffective = AdjustColumnHeaderBorderStyle(this.AdvancedColumnHeadersBorderStyle, dataGridViewAdvancedBorderStylePlaceholder, isFirstDisplayedColumn, isLastVisibleColumn); cell.PaintWork(g, clipBounds, cellBounds, -1, dataGridViewColumn.State, inheritedCellStyle, dgvabsEffective, DataGridViewPaintParts.Background | DataGridViewPaintParts.Border | DataGridViewPaintParts.ContentBackground | DataGridViewPaintParts.ContentForeground | DataGridViewPaintParts.ErrorIcon | DataGridViewPaintParts.SelectionBackground); cx += cellBounds.Width; if (cx >= scrollingBounds.Width) { break; } dataGridViewColumn = dataGridViewColumnNext; isFirstDisplayedColumn = false; } if (this.negOffset > 0) { Debug.Assert(clipRegion != null); g.Clip = clipRegion; clipRegion.Dispose(); } } } } private void PaintGrid(Graphics g, Rectangle gridBounds, Rectangle clipRect, bool singleVerticalBorderAdded, bool singleHorizontalBorderAdded) { Rectangle rc = gridBounds; if (this.layout.TopLeftHeader.Width > 0 && (clipRect.IntersectsWith(this.layout.TopLeftHeader) || this.lastHeaderShadow != -1)) { if (this.Columns.Count > 0 || this.Rows.Count > 0) { using (Region clipRegion = g.Clip) { g.SetClip(this.layout.TopLeftHeader); PaintTopLeftHeaderCell(g); g.Clip = clipRegion; } } } if (this.layout.ColumnHeadersVisible) { Rectangle columnHeadersClip = new Rectangle(); columnHeadersClip = this.layout.ColumnHeaders; if (singleVerticalBorderAdded) { columnHeadersClip.Width++; } if (clipRect.IntersectsWith(columnHeadersClip) || this.lastHeaderShadow != -1) { using (Region clipRegion = g.Clip) { g.SetClip(columnHeadersClip); PaintColumnHeaders(g, columnHeadersClip, singleVerticalBorderAdded); g.Clip = clipRegion; } } int columnHeadersHeight = this.layout.ColumnHeaders.Height; rc.Y += columnHeadersHeight; rc.Height -= columnHeadersHeight; if (this.lastHeaderShadow != -1) { DrawColHeaderShadow(g, this.lastHeaderShadow); } } if (rc.Height > 0) { PaintRows(g, rc, clipRect, /*singleVerticalBorderAdded, */ singleHorizontalBorderAdded); } if (this.currentRowSplitBar != -1) { Debug.Assert(this.dataGridViewOper[DATAGRIDVIEWOPER_trackColHeadersResize] || this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowResize]); DrawRowSplitBar(this.currentRowSplitBar); } else if (this.currentColSplitBar != -1) { Debug.Assert(this.dataGridViewOper[DATAGRIDVIEWOPER_trackRowHeadersResize] || this.dataGridViewOper[DATAGRIDVIEWOPER_trackColResize]); DrawColSplitBar(this.currentColSplitBar); } } private void PaintRows(Graphics g, Rectangle boundingRect, Rectangle clipRect, /*bool singleVerticalBorderAdded,*/ bool singleHorizontalBorderAdded) { int cy = 0; Rectangle rowBounds; DataGridViewRow dataGridViewRow; bool isFirstDisplayedRow = true; int indexTmp, indexTmpNext; // paint visible none-scrolling rows indexTmp = this.Rows.GetFirstRow(DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); while (indexTmp != -1) { rowBounds = boundingRect; // Dev 10 Bug #434494 - DataGridView AutoSizeRowsMode does not work properly after column sort // Should unshared the row and set the thickness to a perfect value // every time user scroll to display the specific row. DataGridViewAutoSizeRowsModeInternal autoSizeRowsModeInternal = (DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode; // Auto size row if needed if (autoSizeRowsModeInternal != DataGridViewAutoSizeRowsModeInternal.None) { // this call may unshare the row. int rowHeight = this.Rows.SharedRow(indexTmp).GetHeight(indexTmp); this.Rows.SharedRow(indexTmp).CachedThickness = rowHeight; AutoResizeRowInternal(indexTmp, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), false /*fixedWidth*/, true /*internalAutosizing*/); } rowBounds.Height = this.Rows.SharedRow(indexTmp).GetHeight(indexTmp); if (isFirstDisplayedRow && singleHorizontalBorderAdded) { rowBounds.Height++; } rowBounds.Y = boundingRect.Y + cy; indexTmpNext = this.Rows.GetNextRow(indexTmp, DataGridViewElementStates.Visible | DataGridViewElementStates.Frozen); if (clipRect.IntersectsWith(rowBounds)) { dataGridViewRow = this.Rows.SharedRow(indexTmp); dataGridViewRow.Paint(g, clipRect, rowBounds, indexTmp, this.Rows.GetRowState(indexTmp), isFirstDisplayedRow, (indexTmpNext == -1) && (this.displayedBandsInfo.FirstDisplayedScrollingRow == -1)); } cy += rowBounds.Height; if (cy >= boundingRect.Height) { break; } indexTmp = indexTmpNext; isFirstDisplayedRow = false; } // paint scrolling rows if (this.displayedBandsInfo.FirstDisplayedScrollingRow >= 0 && cy < boundingRect.Height) { indexTmp = this.displayedBandsInfo.FirstDisplayedScrollingRow; Debug.Assert((this.Rows.GetRowState(indexTmp) & DataGridViewElementStates.Frozen) == 0); Debug.Assert((this.Rows.GetRowState(indexTmp) & DataGridViewElementStates.Visible) != 0); while (indexTmp != -1) { rowBounds = boundingRect; // Dev 10 Bug #434494 - DataGridView AutoSizeRowsMode does not work properly after column sort // Should unshared the row and set the thickness to a perfect value // every time user scroll to display the specific row. DataGridViewAutoSizeRowsModeInternal autoSizeRowsModeInternal = (DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode; // Auto size row if needed if (autoSizeRowsModeInternal != DataGridViewAutoSizeRowsModeInternal.None) { // this call may unshare the row. int rowHeight = this.Rows.SharedRow(indexTmp).GetHeight(indexTmp); this.Rows.SharedRow(indexTmp).CachedThickness = rowHeight; AutoResizeRowInternal(indexTmp, MapAutoSizeRowsModeToRowMode(this.autoSizeRowsMode), false /*fixedWidth*/, true /*internalAutosizing*/); } rowBounds.Height = this.Rows.SharedRow(indexTmp).GetHeight(indexTmp); if (isFirstDisplayedRow && singleHorizontalBorderAdded) { rowBounds.Height++; } rowBounds.Y = boundingRect.Y + cy; indexTmpNext = this.Rows.GetNextRow(indexTmp, DataGridViewElementStates.Visible); if (clipRect.IntersectsWith(rowBounds)) { dataGridViewRow = this.Rows.SharedRow(indexTmp); dataGridViewRow.Paint(g, clipRect, rowBounds, indexTmp, this.Rows.GetRowState(indexTmp), isFirstDisplayedRow, indexTmpNext == -1); } cy += rowBounds.Height; if (cy >= boundingRect.Height) { break; } indexTmp = indexTmpNext; isFirstDisplayedRow = false; } } } private void PaintTopLeftHeaderCell(Graphics g) { if (g.IsVisible(this.layout.TopLeftHeader)) { DataGridViewCell cell = this.TopLeftHeaderCell; DataGridViewCellStyle inheritedCellStyle = new DataGridViewCellStyle(); BuildInheritedColumnHeaderCellStyle(inheritedCellStyle, cell); Rectangle cellBounds = this.layout.TopLeftHeader; cellBounds.Width = this.rowHeadersWidth; cellBounds.Height = this.columnHeadersHeight; // [....]: Should paintSelectionBackground be dev-settable? cell.PaintWork(g, this.layout.TopLeftHeader, cellBounds, -1, cell.State, inheritedCellStyle, this.AdjustedTopLeftHeaderBorderStyle, DataGridViewPaintParts.Background | DataGridViewPaintParts.Border | DataGridViewPaintParts.ContentBackground | DataGridViewPaintParts.ContentForeground | DataGridViewPaintParts.ErrorIcon | DataGridViewPaintParts.SelectionBackground); } } private void PerformLayoutPrivate(bool useRowShortcut, bool computeVisibleRows, bool invalidInAdjustFillingColumns, bool repositionEditingControl) { this.inPerformLayoutCount++; try { if (invalidInAdjustFillingColumns && this.InAdjustFillingColumns) { throw new InvalidOperationException(SR.GetString(SR.DataGridView_CannotAlterAutoFillColumnParameter)); } if (this.IsHandleCreated) { bool columnsAdjusted = false; if (useRowShortcut) { ComputeLayoutShortcut(computeVisibleRows); } else { columnsAdjusted = ComputeLayout(); } FlushDisplayedChanged(); if (columnsAdjusted && this.inPerformLayoutCount < 3) { // Some columns were auto-filled, the rows and column headers may need to be autosized. if ((((DataGridViewAutoSizeRowsModeInternal)this.autoSizeRowsMode) & DataGridViewAutoSizeRowsModeInternal.AllColumns) != 0) { AdjustShrinkingRows(this.autoSizeRowsMode, true /*fixedWidth*/, true /*internalAutosizing*/); } if (this.ColumnHeadersHeightSizeMode == DataGridViewColumnHeadersHeightSizeMode.AutoSize) { AutoResizeColumnHeadersHeight(true /*fixedRowHeadersWidth*/, true /*fixedColumnWidth*/); } } if (repositionEditingControl && this.editingControl != null) { PositionEditingControl(true /*setLocation*/, false /*setSize*/, false /*setFocus*/); } } else { this.displayedBandsInfo.FirstDisplayedFrozenCol = -1; this.displayedBandsInfo.FirstDisplayedFrozenRow = -1; this.displayedBandsInfo.FirstDisplayedScrollingRow = -1; this.displayedBandsInfo.FirstDisplayedScrollingCol = -1; this.displayedBandsInfo.NumDisplayedFrozenRows = 0; this.displayedBandsInfo.NumDisplayedFrozenCols = 0; this.displayedBandsInfo.NumDisplayedScrollingRows = 0; this.displayedBandsInfo.NumDisplayedScrollingCols = 0; this.displayedBandsInfo.NumTotallyDisplayedFrozenRows = 0; this.displayedBandsInfo.NumTotallyDisplayedScrollingRows = 0; this.displayedBandsInfo.LastDisplayedScrollingRow = -1; this.displayedBandsInfo.LastTotallyDisplayedScrollingCol = -1; if (this.layout != null) { this.layout.dirty = true; } } } finally { this.inPerformLayoutCount--; Debug.Assert(this.inPerformLayoutCount >= 0); } } [ SuppressMessage("Microsoft.Performance", "CA1817:DoNotCallPropertiesThatCloneValuesInLoops") // Illegitimate report. ] private void PopulateNewRowWithDefaultValues() { if (this.newRowIndex != -1) { DataGridViewRow newRow = this.Rows.SharedRow(this.newRowIndex); DataGridViewCellCollection newRowCells = newRow.Cells; foreach (DataGridViewCell dataGridViewCell in newRowCells) { if (dataGridViewCell.DefaultNewRowValue != null) { newRow = this.Rows[this.newRowIndex]; // unshare the 'new row'. newRowCells = newRow.Cells; break; } } foreach (DataGridViewCell dataGridViewCell in newRowCells) { dataGridViewCell.SetValueInternal(this.newRowIndex, dataGridViewCell.DefaultNewRowValue); } } } private void PositionEditingControl(bool setLocation, bool setSize, bool setFocus) { Debug.Assert(this.editingControl != null); if (!this.IsHandleCreated) { return; } #if DEBUG DataGridViewCell dataGridViewCell = this.CurrentCellInternal; Debug.Assert(dataGridViewCell != null); Debug.Assert(dataGridViewCell.ColumnIndex == this.ptCurrentCell.X); Debug.Assert(dataGridViewCell.RowIndex == this.ptCurrentCell.Y || dataGridViewCell.RowIndex == -1); #endif Rectangle editingZone = this.layout.Data; if (editingZone.Width == 0 || editingZone.Height == 0) { return; } this.dataGridViewState1[DATAGRIDVIEWSTATE1_editingControlChanging] = true; try { int