Note: If you like this article, please vote for it!
Figure 1. Demo screenshot.
Introduction
This article will discuss how to customize elements such as edit control, column and cell for DataGridView
in a numeric edit application, which has the functions listed below:
- Can set decimal length in the customized column (0 indicates integer, maximum decimal length can be 6).
- Can set whether negative sign is allowed or not when editing.
- Can set whether to show
null
when cell value is zero or not. - Supports mouse Cut, Copy, Paste, Clear in context menu when editing.
- Supports shortcut keys Ctrl+X, Ctrl+C or Ctrl+V when editing.
- Supports sort operations built in
DataGridView
.
Background
There are already many solutions for customizing column, cell or DataGridView
in numeric edit applications, and the classic one is Build a Custom NumericUpDown Cell and Column for the DataGridView Control, which describes in a deep, detailed and step by step manner, the implementation of edit control, column and cell for DataGridView
based on the standard NumericUpDown
control. However, it has some shortcomings as stated below:
- Can input decimal separator more than one
- Can input negative sign more than one
- Can paste nondigit char in context menu by mouse or shortcuts
- Sort may cause exception when assigned integer and decimal to cells directly
Most solutions behave like the article above, which handle keyboard input only, few support mouse Cut, Copy, Paste and Clear in context menu, few process conventional shortcut keys such as Ctrl+X, Ctrl+C or Ctrl+V too.
Main Steps
Here we customize edit control, column and cell according to Build a Custom NumericUpDown Cell and Column for the DataGridView Control, and we use the open source TNumEditBox control as the numeric edit control instead of NumericUpDown
, which is my open source control published on The Code Project. The core implementation is that we must build an edit control based on TNumEditBox
, and then customize the column and cell for DataGridView
.
The main steps include:
Derive TNumEditDataGridViewEditingControl
class from TNumEditBox
and standard IDataGridViewEditingControl
:
Implement all methods and properties defined in standard IDataGridViewEditingControl
interface.
Override OnKeyPress()
of TNumEditBox
to notify value change to DataGridView
when keys input.
Override OnTextChanged()
of TNumEditBox
to notify text changed to DataGridView
.
Derive TNumEditDataGridViewColumn
class from standard DataGridViewTextBoxColumn
to expose three properties of the customized cell: DecimalLength
, AllowNegative
, and ShowNullWhenZero.
Derive TNumEditDataGridViewCell
class from DataGridViewTextBoxCell
:
Override two properties: EditType
and ValueType
.
The EditType
property indicates the type of edit control, i.e. typeof(TNumEditDataGridViewEditingControl)
. The ValueType
property indicates the type of cell value, i.e. typeof(Decimal)
.
Override five methods: InitializeEditingControl
, DetachEditingControl
, SetValue
, Clone
, and GetFormattedValue
.
InitializeEditingControl
and DetachEditingControl
methods handle the initialization and clear work of edit control. SetValue
method can convert value to decimal when assigned directly to cells. GetFormattedValue
method provides formatted value text as need. Clone
method is used when not sharing cells.
Define three properties: DecimalLength
, AllowNegative
, and ShowNullWhenZero
In fact, the steps and implementation have been discussed in detail in the article above, but we need not follow them exactly as stated, since the edit control is TNumEditBox
instead of NumericUpDown
, which is derived from TextBox
like the standard DataGridViewTextBoxEditingControl
. Furthermore, we need not handle shortcut keys and context menu in customized edit control too, because this work has been done by the TNumEditBox
control.
Key Points
We explain some key points different from the article above.
1) Override SetValue Method in TNumEditDataGridViewCell Class
When we assign values to DataGridView
cells directly, for example, dataGridView1.Rows[0].Cells[0].Value = 1
, SetValue
method will be called. This method can deduce automatically the type of value assigned, that is to say, it takes value as integer
if 1
is assigned, and value is double
if 1.1
is assigned. So, one DataGridView
column will have integer
and double
value when we assign 1
and 1.1
to its cells, then it will throw an exception when we sort by clicking the column header, since we do not implement IComparer
for integer
and double
/decimal
.
We must override the SetValue
method, since the property Value
does not expose in the DataGridViewTextBoxCell
:
protected override bool SetValue(int rowIndex, object value)
{
decimal val = 0.0m;
try
{
val = Math.Round(System.Convert.ToDecimal(value), m_decimalLength);
}
catch { }
return base.SetValue(rowIndex, val);
}
We convert all type of values assigned to decimal. We need not care about the performance of the overriding method above, since it is called only when values are assigned directly to cells, and does not bring it up when we edit text or bind datasource
.
2) Define ShowNullWhenZero Property in TNumEditDataGridViewCell Class
DataGridView
shows usually 0
or 0.00
, etc. when cell values are zero, and we hope no number displayed as null
value does, especially in the case of great many zeros in DataGridView
. Here we define the ShowNullWhenZero property
in the TNumEditDataGridViewCell
class, which handles zero as null
, and then we need to override the GetFormattedValue
method:
protected override object GetFormattedValue(object value,
int rowIndex,
ref DataGridViewCellStyle cellStyle,
TypeConverter valueTypeConverter,
TypeConverter formattedValueTypeConverter,
DataGridViewDataErrorContexts context)
{
object baseFormattedValue = base.GetFormattedValue(value, rowIndex, ref cellStyle,
valueTypeConverter, formattedValueTypeConverter, context);
string formattedText = baseFormattedValue as string;
if (value == null || string.IsNullOrEmpty(formattedText))
{
return baseFormattedValue;
}
Decimal unformattedDecimal = System.Convert.ToDecimal(value);
Decimal formattedDecimal = System.Convert.ToDecimal(formattedText);
if (unformattedDecimal == 0.0m && m_showNullWhenZero)
{
return base.GetFormattedValue(null, rowIndex, ref cellStyle,
valueTypeConverter, formattedValueTypeConverter, context);
}
if (unformattedDecimal == formattedDecimal)
{
return formattedDecimal.ToString("F" + m_decimalLength.ToString());
}
return formattedText;
}
Using the Code
After unzipping TNumEditDataGridViewElements.zip, we can double click the solution file TNumEditDataGridViewElements.sln to view the demo project if we have Visual Studio 2005/2008, or we can run TNumEditDataGridViewElementsDemo.exe in subfolder \bin\ to take a view and test them. Below are some notes about the class files and steps for creating columns in DataGridView
control.
1) Two C# Class Files
There are two C# class files in the zip file:
- TNumEditBox.cs contains the customized
TextBox
control for numeric edit, whose introduction can be located here, and it works as the edit control in DataGridView
. - TNumEditDataGridViewElements.cs contains the three customized element classes for
DataGridView
, i.e. TNumEditDataGridViewEditingControl
, TNumEditDataGridViewColumn
and TNumEditDataGridViewCell
.
2) Usage Steps
We can use the customized DataGridView
elements in our application projects according to the steps below:
- Create a new application solution or project, and include TNumEditBox.cs and
TNumEditDataGridViewElements
into the project. - Add one standard
DataGridView
control onto one form control. - Add and select customized
TNumEditDataGridViewColumns
as shown in figure 2: 
Figure 2. Select the customized column in DataGridView.
- Define property values for customized
TNumEditDataGridViewColumn
, i.e. define the values of DecimalLength
, AllowNegative
and ShowNullWhenZero
as shown in figure 3: 
Figure 3. Define property values for customized column.
Ok, let us test, run and enjoy the customized elements for DataGridView
in our applications!
Conclusion
In Windows Forms, DataGridView
is a powerful control for displaying and editing data, and, we hope, a more convenient and standard kind to handle and show numeric data in it. We often customize one or more core elements in DataGridView
. Based on TNumEditBox control, here we provide a solution to customize elements such as edit control, column and cell for DataGridView
according to the methods and steps introduced by Build a Custom NumericUpDown Cell and Column for the DataGridView Control. The key features of our solution are that of supporting mouse context menu and shortcut input. The Chinese counterpart will be published at my csdn blog. Any comments will be appreciated.
History
- 25th November, 2008: First published