using System; using System.ComponentModel; using System.Globalization; using System.Text; using System.Windows.Forms; namespace CC_Functions.W32.Forms { /// /// Custom column type dedicated to the DataGridViewNumericUpDownCell cell type. /// public class DataGridViewNumericUpDownColumn : DataGridViewColumn { /// /// Constructor for the DataGridViewNumericUpDownColumn class. /// public DataGridViewNumericUpDownColumn() : base(new DataGridViewNumericUpDownCell()) { } /// /// Represents the implicit cell that gets cloned when adding rows to the grid. /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public override DataGridViewCell CellTemplate { get => base.CellTemplate; set { DataGridViewNumericUpDownCell dataGridViewNumericUpDownCell = value as DataGridViewNumericUpDownCell; if (value != null && dataGridViewNumericUpDownCell == null) throw new InvalidCastException( "Value provided for CellTemplate must be of type DataGridViewNumericUpDownElements.DataGridViewNumericUpDownCell or derive from it."); base.CellTemplate = value; } } /// /// Replicates the DecimalPlaces property of the DataGridViewNumericUpDownCell cell type. /// [Category("Appearance")] [DefaultValue(DataGridViewNumericUpDownCell.DATAGRIDVIEWNUMERICUPDOWNCELL_defaultDecimalPlaces)] [Description("Indicates the number of decimal places to display.")] public int DecimalPlaces { get { if (NumericUpDownCellTemplate == null) throw new InvalidOperationException( "Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate."); return NumericUpDownCellTemplate.DecimalPlaces; } set { if (NumericUpDownCellTemplate == null) throw new InvalidOperationException( "Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate."); // Update the template cell so that subsequent cloned cells use the new value. NumericUpDownCellTemplate.DecimalPlaces = value; if (DataGridView != null) { // Update all the existing DataGridViewNumericUpDownCell cells in the column accordingly. DataGridViewRowCollection dataGridViewRows = DataGridView.Rows; int rowCount = dataGridViewRows.Count; for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) { // Be careful not to unshare rows unnecessarily. // This could have severe performance repercussions. DataGridViewRow dataGridViewRow = dataGridViewRows.SharedRow(rowIndex); DataGridViewNumericUpDownCell dataGridViewCell = dataGridViewRow.Cells[Index] as DataGridViewNumericUpDownCell; if (dataGridViewCell != null) // Call the internal SetDecimalPlaces method instead of the property to avoid invalidation // of each cell. The whole column is invalidated later in a single operation for better performance. dataGridViewCell.SetDecimalPlaces(rowIndex, value); } DataGridView.InvalidateColumn(Index); // TODO: Call the grid's autosizing methods to autosize the column, rows, column headers / row headers as needed. } } } /// /// Replicates the Increment property of the DataGridViewNumericUpDownCell cell type. /// [Category("Data")] [Description("Indicates the amount to increment or decrement on each button click.")] public decimal Increment { get { if (NumericUpDownCellTemplate == null) throw new InvalidOperationException( "Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate."); return NumericUpDownCellTemplate.Increment; } set { if (NumericUpDownCellTemplate == null) throw new InvalidOperationException( "Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate."); NumericUpDownCellTemplate.Increment = value; if (DataGridView != null) { DataGridViewRowCollection dataGridViewRows = DataGridView.Rows; int rowCount = dataGridViewRows.Count; for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) { DataGridViewRow dataGridViewRow = dataGridViewRows.SharedRow(rowIndex); DataGridViewNumericUpDownCell dataGridViewCell = dataGridViewRow.Cells[Index] as DataGridViewNumericUpDownCell; if (dataGridViewCell != null) dataGridViewCell.SetIncrement(rowIndex, value); } } } } /// /// Replicates the Maximum property of the DataGridViewNumericUpDownCell cell type. /// [Category("Data")] [Description("Indicates the maximum value for the numeric up-down cells.")] [RefreshProperties(RefreshProperties.All)] public decimal Maximum { get { if (NumericUpDownCellTemplate == null) throw new InvalidOperationException( "Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate."); return NumericUpDownCellTemplate.Maximum; } set { if (NumericUpDownCellTemplate == null) throw new InvalidOperationException( "Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate."); NumericUpDownCellTemplate.Maximum = value; if (DataGridView != null) { DataGridViewRowCollection dataGridViewRows = DataGridView.Rows; int rowCount = dataGridViewRows.Count; for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) { DataGridViewRow dataGridViewRow = dataGridViewRows.SharedRow(rowIndex); DataGridViewNumericUpDownCell dataGridViewCell = dataGridViewRow.Cells[Index] as DataGridViewNumericUpDownCell; if (dataGridViewCell != null) dataGridViewCell.SetMaximum(rowIndex, value); } DataGridView.InvalidateColumn(Index); // TODO: This column and/or grid rows may need to be autosized depending on their // autosize settings. Call the autosizing methods to autosize the column, rows, // column headers / row headers as needed. } } } /// /// Replicates the Minimum property of the DataGridViewNumericUpDownCell cell type. /// [Category("Data")] [Description("Indicates the minimum value for the numeric up-down cells.")] [RefreshProperties(RefreshProperties.All)] public decimal Minimum { get { if (NumericUpDownCellTemplate == null) throw new InvalidOperationException( "Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate."); return NumericUpDownCellTemplate.Minimum; } set { if (NumericUpDownCellTemplate == null) throw new InvalidOperationException( "Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate."); NumericUpDownCellTemplate.Minimum = value; if (DataGridView != null) { DataGridViewRowCollection dataGridViewRows = DataGridView.Rows; int rowCount = dataGridViewRows.Count; for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) { DataGridViewRow dataGridViewRow = dataGridViewRows.SharedRow(rowIndex); DataGridViewNumericUpDownCell dataGridViewCell = dataGridViewRow.Cells[Index] as DataGridViewNumericUpDownCell; if (dataGridViewCell != null) dataGridViewCell.SetMinimum(rowIndex, value); } DataGridView.InvalidateColumn(Index); // TODO: This column and/or grid rows may need to be autosized depending on their // autosize settings. Call the autosizing methods to autosize the column, rows, // column headers / row headers as needed. } } } /// /// Replicates the ThousandsSeparator property of the DataGridViewNumericUpDownCell cell type. /// [Category("Data")] [DefaultValue(DataGridViewNumericUpDownCell.DATAGRIDVIEWNUMERICUPDOWNCELL_defaultThousandsSeparator)] [Description("Indicates whether the thousands separator will be inserted between every three decimal digits.")] public bool ThousandsSeparator { get { if (NumericUpDownCellTemplate == null) throw new InvalidOperationException( "Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate."); return NumericUpDownCellTemplate.ThousandsSeparator; } set { if (NumericUpDownCellTemplate == null) throw new InvalidOperationException( "Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate."); NumericUpDownCellTemplate.ThousandsSeparator = value; if (DataGridView != null) { DataGridViewRowCollection dataGridViewRows = DataGridView.Rows; int rowCount = dataGridViewRows.Count; for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) { DataGridViewRow dataGridViewRow = dataGridViewRows.SharedRow(rowIndex); DataGridViewNumericUpDownCell dataGridViewCell = dataGridViewRow.Cells[Index] as DataGridViewNumericUpDownCell; if (dataGridViewCell != null) dataGridViewCell.SetThousandsSeparator(rowIndex, value); } DataGridView.InvalidateColumn(Index); // TODO: This column and/or grid rows may need to be autosized depending on their // autosize settings. Call the autosizing methods to autosize the column, rows, // column headers / row headers as needed. } } } /// /// Small utility function that returns the template cell as a DataGridViewNumericUpDownCell /// private DataGridViewNumericUpDownCell NumericUpDownCellTemplate => (DataGridViewNumericUpDownCell) CellTemplate; /// Indicates whether the Increment property should be persisted. private bool ShouldSerializeIncrement() => !Increment.Equals(DataGridViewNumericUpDownCell.DATAGRIDVIEWNUMERICUPDOWNCELL_defaultIncrement); /// Indicates whether the Maximum property should be persisted. private bool ShouldSerializeMaximum() => !Maximum.Equals(DataGridViewNumericUpDownCell.DATAGRIDVIEWNUMERICUPDOWNCELL_defaultMaximum); /// Indicates whether the Maximum property should be persisted. private bool ShouldSerializeMinimum() => !Minimum.Equals(DataGridViewNumericUpDownCell.DATAGRIDVIEWNUMERICUPDOWNCELL_defaultMinimum); /// /// Returns a standard compact string representation of the column. /// public override string ToString() { StringBuilder sb = new StringBuilder(100); sb.Append("DataGridViewNumericUpDownColumn { Name="); sb.Append(Name); sb.Append(", Index="); sb.Append(Index.ToString(CultureInfo.CurrentCulture)); sb.Append(" }"); return sb.ToString(); } } }