Title: Change a DataGridView entry when the user double-clicks a cell in C#
This post is in response to the following question:
Respected Sir,
I need help on how can i change the datagridview cell value by double click on that cell.
Let say cell contain value No when i double click it will change to Yes. |
(Actually the original question used valeus other than No and Yes, but I can't find that email now.)
First, note that by default the DataGridView control allows the user to edit its data. If you click on a DataGridView cell and then click on the cell again, the control allows you to edit that cell's value. For example, see my post Build a DataTable and bind it to a DataGridView in C#.
For the question to make sense, we must have disabled the control's natural editing capabilities. This example does that in its Form_Load event handler shown shortly. It then detects double-clicks and takes action depending on the cell that was clicked.
To make it easier for the user to know that particular cells are double-clickable, the program changes the cursor for those cells.
The following sections describe the pieces of the program that accomplish those tasks.
Setup
The following code shows the form's Load event handler.
private void Form1_Load(object sender, EventArgs e)
{
// Make the DataTable object.
DataTable dt = new DataTable("Books");
// Add columns to the DataTable.
dt.Columns.Add("Title",
System.Type.GetType("System.String"));
dt.Columns.Add("Has Download",
System.Type.GetType("System.Boolean"));
dt.Columns.Add("Year",
System.Type.GetType("System.Int32"));
dt.Columns.Add("URL",
System.Type.GetType("System.String"));
// Add items to the table.
dt.Rows.Add(new object[] { "Essential Algorithms", ... );
dt.Rows.Add(new object[] { "WPF 3d", true, "2018", ... );
dt.Rows.Add(new object[] { "The C# Helper Top 100", ... );
dt.Rows.Add(new object[] { "Interview Puzzles Dissected", ... );
// Make the DataGridView use the DataTable as its data source.
dgvBooks.DataSource = dt;
// Draw URLs in a blue, underlined font.
dgvBooks.Columns["URL"].DefaultCellStyle.Font=
new Font(dgvBooks.Font, FontStyle.Underline);
dgvBooks.Columns["URL"].DefaultCellStyle.ForeColor =
Color.Blue;
// Set column widths.
dgvBooks.AutoResizeColumns();
// Do not allow automatic editing.
dgvBooks.EditMode = DataGridViewEditMode.EditProgrammatically;
dgvBooks.AllowUserToAddRows = false;
dgvBooks.AllowUserToDeleteRows = false;
}
This code creates a DataTable to hold the data. It adds columns of different data types and then inserts data into the table.
Next, the program sets the DataGridView control's DataSource property to the DataTable. At this point, the control allows the user to view and edit the data.
Next, the program sets the font for the DefaultCellStyle property in the URL column. It sets that property to a new font that is based on the DataGridView control's font but with the underline style. That makes the values in that column appear underlined.
Similarly, the code sets the URL column's default cell style to draw blue text so the URL values are drawn with a blue, underlined font.
The code then calls the DataGridView control's AutoResizeColumns method to make the columns size themselves to fit their data.
Finally, the Load event handler sets the control's EditMode so the user cannot edit the data value. It also prevents the user from adding new records or deleting existing ones.
Changing Cursors
When the mouse enters a cell, the following event handler sets the appropriate cursor.
// Display an appropriate cursor in the Has Download and URL columns.
private void dgvBooks_CellMouseEnter(object sender,
DataGridViewCellEventArgs e)
{
int col = e.ColumnIndex;
if (col == -1) return;
if (dgvBooks.Columns[col].Name == "Has Download")
dgvBooks.Cursor = Cursors.Hand;
else if (dgvBooks.Columns[col].Name == "URL")
dgvBooks.Cursor = Cursors.UpArrow;
}
This event handler checks the column number below the mouse. If the mouse is to the left of the first column of data, then the column number is -1. In that case, the method exits. If the mouse is below the DataGridView control's last row or to the right of the rightmost column, then this event is not raised.
If the column number is at least 0, the code checks the name of the column. If this is the Has Download column, the code sets the control's cursor to Hand. If this is the URL column, the code sets the control's cursor to UpArrow.
When the mouse moves off of a column, the following event handler executes.
// Restore the default cursor..
private void dgvBooks_CellMouseLeave(object sender,
DataGridViewCellEventArgs e)
{
if (dgvBooks.Cursor != Cursors.Default)
dgvBooks.Cursor = Cursors.Default;
}
This code simply checks the DataGridView control's current cursor and resets it to the default if it is not already the default.
Modifying Values
When the user double-clicks on a cell, the following event handler executes.
// Toggle the Has Download field. Open the URL.
private void dgvBooks_CellDoubleClick(object sender,
DataGridViewCellEventArgs e)
{
int col = e.ColumnIndex;
if (col == -1) return;
int row = e.RowIndex;
// See which column this is.
if (dgvBooks.Columns[col].Name == "Has Download")
{
// Toggle the value.
bool value = (bool)dgvBooks.Rows[row].Cells[col].Value;
dgvBooks.Rows[row].Cells[col].Value = !value;
}
else if (dgvBooks.Columns[e.ColumnIndex].Name == "URL")
{
// Open the URL.
string url = (string)dgvBooks.Rows[row].Cells[col].Value;
System.Diagnostics.Process.Start(url);
}
}
This code verifies that the column number is at least 0 as before. If user double-clicked the Has Download column, the code gets the current value in the clicked cell and then updates the cell to hold the opposite of that value.
If the user double-clicked the URL column, the program gets the value in the cell and then uses System.Diagnostics.Process.Start to "start" the URL. That launches the URL in the system's default browser.
Conclusion
I generally don't recommend that you write your own code to edit DataGridView data because that control already does a pretty good job. Still, it may sometimes be useful to provide custom editing of some sort such as allowing the user to toggle a value as in this example.
An alternative might be to prevent editing in columns that the user should not modify. For example, the following statement prevents the user from editing the values in the first column.
dt.Columns[0].ReadOnly = true;
Download the example to experiment with it and to see additional details.
|