C# DataGridView Checkbox checked event - c#

I want to handle Checked event of CheckBox columns in my DataGridView and perform an operation based on column checked value (true/false). I tried to use CellDirtyStateChanged without any success. In fact I want to detect checked change immediately after the user checks or unchecks the check box.
Here is a description about my application. I am new to c# and making a "book my room" app for a place which provides guest housing to travelers. This screen may explain well what I wish to achieve;
This is a .GIF of a software which calculates hourly pay of an employee and this photo is an illustration of what actually I want to build:
Code for displaying my table in DataGridView is:
OleDbConnection connection = new OleDbConnection();
connection.Open();
OleDbCommand command = new OleDbCommand();
command.Connection = connection;
string query = "select id,cusid,cusname,timein,
timeout,duration,amount,remark from entry";
command.CommandText = query;
OleDbDataAdapter da = new OleDbDataAdapter(command);
DataTable dt = new DataTable();
da.Fill(dt);
dataGridView1.DataSource = dt;
I added the checkbox column using this;
DataGridViewCheckBoxColumn checkColumn = new DataGridViewCheckBoxColumn();
checkColumn.Name = "logout";
checkColumn.HeaderText = "Logout";
checkColumn.Width = 50;
checkColumn.ReadOnly = false;
checkColumn.FillWeight = 10;
dataGridView1.Columns.Add(checkColumn);
Whenever a user logs in from the login screen a new row will be inserted in the table and hence the dgv will be updated, with corresponding users entry.
I don't understand how to link those checkboxes with datagridview I tried celldirtystatechanged but nothing works, what would be the right way to associate the row with checkbox.

You can handle CellContentClick event of your DataGridView and put the logic for changing those cells there.
The key point is using CommitEdit(DataGridViewDataErrorContexts.Commit) to commits changes in the current cell to the data cache without ending edit mode. This way when you check for value of cell in this event, it returns current checked or unchecked value which you see in the cell currently after click:
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
//We make DataGridCheckBoxColumn commit changes with single click
//use index of logout column
if(e.ColumnIndex == 4 && e.RowIndex>=0)
this.dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
//Check the value of cell
if((bool)this.dataGridView1.CurrentCell.Value == true)
{
//Use index of TimeOut column
this.dataGridView1.Rows[e.RowIndex].Cells[3].Value = DateTime.Now;
//Set other columns values
}
else
{
//Use index of TimeOut column
this.dataGridView1.Rows[e.RowIndex].Cells[3].Value = DBNull.Value;
//Set other columns values
}
}

Related

Getting cell value from GridView after Edit button is clicked Round 2

I posted this not long ago, but no I have to update the question to ensure I get the right answer.
I have a GridView. I need to update an SQL table based on values from the GridView.
When a user clicks the default EDIT button on the GridView, changes whatever they change, then hits UPDATE. Here is where I run into problems. I've tried multiple OnRowEditing, OnRowUpdating, OnRowUpdate as the button control.
Here is the code I use to that.
protected void gvReviewedPolicy_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
DateTime dateTime = DateTime.Now;
//GridViewRow editRow = gvReviewedPolicy.Rows[gvReviewedPolicy.EditIndex];
//string Emailed = editRow.Cells[7].Text;
//string UniqClient = editRow.Cells[1].Text;
//string UniqPolicy = editRow.Cells[3].Text;
string UniqClient = gvReviewedPolicy.SelectedRow.Cells[2].Text;
string UniqPolicy = gvReviewedPolicy.SelectedRow.Cells[3].Text;
//string Email = Emailed.ToString();
//string dt = dateTime.ToString();
//string Up = UniqClient.ToString();
MessageBox.Show(UniqClient);
MessageBox.Show(UniqPolicy);
//MessageBox.Show(dt);
string query = "UPDATE [Reviewed_Renewal_Policy] SET [DateUpdated] = #dateTime where ([UniqClient] = #UniqClient) AND ([UniqPolicy] = #UniqPolicy)";
using (SqlConnection conn = new SqlConnection("Data Source=GTU-BDE01;Initial Catalog=TestDB;Integrated Security=True"))
{
using (SqlCommand comm = new SqlCommand(query, conn))
{
comm.Parameters.AddWithValue("#UniqClient", UniqClient);
comm.Parameters.AddWithValue("#UniqPolicy", UniqPolicy);
//comm.Parameters.AddWithValue("#Emailed", Emailed);
comm.Parameters.AddWithValue("#dateTime", dateTime);
conn.Open();
comm.ExecuteNonQuery();
conn.Close();
}
}
}
I have some commented out because I was trying different things. However, the code that says
GridViewRow editRow = gvReviewedPolicy.Rows[gvReviewedPolicy.EditIndex];
string Emailed = editRow.Cells[7].Text;
string UniqClient = editRow.Cells[1].Text;
string UniqPolicy = editRow.Cells[3].Text;
It's supposed to access the values in those cells when UPDATE button is pushed. However, using MessageBox.Show , comes back blank.
Anyone have any idea how I can capture those values after hitting Edit, then the default UPDATE button?
I've tried to make that Winforms Datagrid usable for "write through" in the past, by implementing an DataGridView subclass (this allows you to access everything) but since immutable databases and queue transactions came into view, my Access-flavour DataGrid did not survive modern paradigm. Nowadays I tend to support ASP.NET MVC 5 to "edit" databases.
Anyway have you considered to connect a DataSource ? You don't have to access cells.. you can update using a connection like
private SqlDataAdapter daGrid = new SqlDataAdapter();
and this type of approach, you will have to fill in the details yourself, the complete code consists of several classes and is too large to post,
protected void dataGridView1_KeyUp(object sender, KeyEventArgs e)
{
DataGridView dgv = (DataGridView)sender;
/// .. perform actions according to keyboard events ..
/// .. for example below one ..
}
public override void UpdateAfterEditGrid(DataSet ds, DataGridView dataGridView1, bool DoRestoreCursor)
{
if (daGrid != null)
{
if (conn.State == ConnectionState.Closed) conn.Open();
dataGridView1.EndEdit();
try
{
if (ds == null)
{
//DataGridView dgv = dataGridView1;
//Console.WriteLine("Go datasource update .. " + dgv[cColumnIndex, cRowIndex].Value);
daGrid.Update((DataTable)dataGridView1.DataSource);
}
else daGrid.Update(ds);
LoadGridRestoreCursor(dataGridView1, DoRestoreCursor);
}
catch { ErrorReporting.ErrorMessage("== cannot update this content =="); }
}
}

How to detect if checkbox changed in DataGridView? [duplicate]

I want to handle Checked event of CheckBox columns in my DataGridView and perform an operation based on column checked value (true/false). I tried to use CellDirtyStateChanged without any success. In fact I want to detect checked change immediately after the user checks or unchecks the check box.
Here is a description about my application. I am new to c# and making a "book my room" app for a place which provides guest housing to travelers. This screen may explain well what I wish to achieve;
This is a .GIF of a software which calculates hourly pay of an employee and this photo is an illustration of what actually I want to build:
Code for displaying my table in DataGridView is:
OleDbConnection connection = new OleDbConnection();
connection.Open();
OleDbCommand command = new OleDbCommand();
command.Connection = connection;
string query = "select id,cusid,cusname,timein,
timeout,duration,amount,remark from entry";
command.CommandText = query;
OleDbDataAdapter da = new OleDbDataAdapter(command);
DataTable dt = new DataTable();
da.Fill(dt);
dataGridView1.DataSource = dt;
I added the checkbox column using this;
DataGridViewCheckBoxColumn checkColumn = new DataGridViewCheckBoxColumn();
checkColumn.Name = "logout";
checkColumn.HeaderText = "Logout";
checkColumn.Width = 50;
checkColumn.ReadOnly = false;
checkColumn.FillWeight = 10;
dataGridView1.Columns.Add(checkColumn);
Whenever a user logs in from the login screen a new row will be inserted in the table and hence the dgv will be updated, with corresponding users entry.
I don't understand how to link those checkboxes with datagridview I tried celldirtystatechanged but nothing works, what would be the right way to associate the row with checkbox.
You can handle CellContentClick event of your DataGridView and put the logic for changing those cells there.
The key point is using CommitEdit(DataGridViewDataErrorContexts.Commit) to commits changes in the current cell to the data cache without ending edit mode. This way when you check for value of cell in this event, it returns current checked or unchecked value which you see in the cell currently after click:
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
//We make DataGridCheckBoxColumn commit changes with single click
//use index of logout column
if(e.ColumnIndex == 4 && e.RowIndex>=0)
this.dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
//Check the value of cell
if((bool)this.dataGridView1.CurrentCell.Value == true)
{
//Use index of TimeOut column
this.dataGridView1.Rows[e.RowIndex].Cells[3].Value = DateTime.Now;
//Set other columns values
}
else
{
//Use index of TimeOut column
this.dataGridView1.Rows[e.RowIndex].Cells[3].Value = DBNull.Value;
//Set other columns values
}
}

How to delete row datagrid and update SQL database C#

I am really stuck and non of the books or tread here are user-friendly enough to explain how to delete data from data grid object using C#
from varies of books and fourm threads I have managed to get this coded but it fails to executes the sql command , I have One table call 'SpellingList' and two columns one is ID and the other is Words, all I want to do is delete a row from the datagrid.
Can someone point me to the correct direction , once I solved this , I shall upload some basic easy to follow tutorial so the rest of the newbie can follow this example.
I have used this thread How to delete a selected DataGridViewRow and update a connected database table?
and MCSD Certificaiton Toolkit Exam 70-483 book Page 392 , all attempts have failed.
there is a catch 22 here if I comment out if(dataGridView1.SelectedRows.Count > 0) line , I get the index out of range error .
private void btnDelete_Click(object sender, EventArgs e)
{
// My SQL connectionString
SqlConnection myConnection = new SqlConnection("Data Source=Epic-LaptopWR;Initial Catalog=words;Integrated Security=True");
myConnection.Open();
foreach (DataGridViewCell oneCell in dataGridView1.SelectedCells)
{
if(dataGridView1.SelectedRows.Count > 0)
{
int selectedIndex = dataGridView1.SelectedRows[0].Index;
// gets the RowID from the first column in the grid
int rowID = int.Parse(dataGridView1[0, selectedIndex].Value.ToString());
// your code for deleting it from the database
string sql = "DELETE FROM SpellingList WHERE Words =" + selectedIndex;
SqlCommand deleteRecord = new SqlCommand();
deleteRecord.Connection = myConnection;
deleteRecord.CommandType = CommandType.Text;
deleteRecord.CommandText = sql;
SqlParameter RowParameter = new SqlParameter();
RowParameter.ParameterName = "#Words";
RowParameter.SqlDbType = SqlDbType.Int;
RowParameter.IsNullable = false;
RowParameter.Value = rowID;
deleteRecord.Parameters.Add(RowParameter);
deleteRecord.Connection.Open();
deleteRecord.ExecuteNonQuery();
if (oneCell.Selected)
dataGridView1.Rows.RemoveAt(oneCell.RowIndex);
deleteRecord.Connection.Close();
wordsDataSet.GetChanges();
// booksDataset1.GetChanges();
spellingListTableAdapter.Fill(wordsDataSet.SpellingList);
}// end of if
// then your code for refreshing the DataGridView
}// end of for each statement
myConnection.Close();
}// end of delete Button
We could simplify a lot. And fix some evident bugs.
The ID field is the key field of your table and thus you should use it to find the row to delete, then, a parameter, to be useful, needs a parameter placeholder in the command text that you want to execute
private void btnDelete_Click(object sender, EventArgs e)
{
// No row selected no delete....
if(dataGridView1.SelectedRows.Count == 0)
return; // show a message here to inform
// Prepare the command text with the parameter placeholder
string sql = "DELETE FROM SpellingList WHERE ID = #rowID";
// Create the connection and the command inside a using block
using(SqlConnection myConnection = new SqlConnection("...."))
using(SqlCommand deleteRecord = new SqlCommand(sql, myConnection))
{
myConnection.Open();
int selectedIndex = dataGridView1.SelectedRows[0].Index;
// gets the RowID from the first column in the grid
int rowID = Convert.ToInt32(dataGridView1[0, selectedIndex].Value);
// Add the parameter to the command collection
deleteRecord.Parameters.Add("#rowID", SqlDbType.Int).Value = rowID;
deleteRecord.ExecuteNonQuery();
// Remove the row from the grid
dataGridView1.Rows.RemoveAt(selectedIndex);
}
}
As you can see, connections and commands are disposable objects and should be enclosed in a using statement to ensure proper closing and disposing also in case of exceptions.
Finally, removing the row from the grid should be done simply using the index of the row, removing the line in a single command. You don't need to loop over the cells to delete them one by one.
I would humbly like to thank Steve for his contribution , without guru's like him us newbies would have spent hours to end in trying to solve a simple yet complex problem.
Here is the working code with few modification that by passes the index out of bound error:
private void btnDelete_Click(object sender, EventArgs e)
{
// No row selected no delete....
if(dataGridView1.SelectedRows.Count == 0)
{
MessageBox.Show("No row selected !");// show a message here to inform
}
// Prepare the command text with the parameter placeholder
string sql = "DELETE FROM SpellingList WHERE ID = #rowID";
// Create the connection and the command inside a using block
using(SqlConnection myConnection = new SqlConnection("Data Source=Epic-LaptopWR;Initial Catalog=words;Integrated Security=True"))
using (SqlCommand deleteRecord = new SqlCommand(sql, myConnection))
{
myConnection.Open();
MessageBox.Show("The SQL Connection is Open");
// this overcomes the out of bound error message
// if the selectedRow is greater than 0 then exectute the code below.
if(dataGridView1.CurrentCell.RowIndex > 0)
{
int selectedIndex = dataGridView1.SelectedRows[0].Index;
// gets the RowID from the first column in the grid
int rowID = Convert.ToInt32(dataGridView1[0, selectedIndex].Value);
// Add the parameter to the command collection
deleteRecord.Parameters.Add("#rowID", SqlDbType.Int).Value = rowID;
deleteRecord.ExecuteNonQuery();
// Remove the row from the grid
dataGridView1.Rows.RemoveAt(selectedIndex);
}
}
}// end of delete Button
Please ensure that your datagrid property for SelectionMode is set to 'FullRowSelect' this as mention by Steve will populated with selected rows.
In additional to the above this is for the newbies , please ensure you have a Primary key set as ID with integer values ,in my first error I did not have any data in the primary key it was NULL with one field { Colum called Words} .
Within a week or so I shall post a step by step guide on how to create a simple database watch out for this space.

Refresh one row in Dataset from Database before show edit form

I have a DataSet + TableAdapter and bound dataGridView. I have an edit button which opens a new form with details to edit (WinForms). How do I refresh one row (selected one) in the Dataset and in dataGrid from database before opening the new form?
Example: Two users A and B. User A changed record ID(10) and user B still has the old value in record ID(10). User B presses edit button and should get fresh data from database (data after change made by user A).
string sql = "SELECT * FROM Orders";
SqlConnection connection = new SqlConnection(connectionString);
SqlDataAdapter da = new SqlDataAdapter(sql, connection);
DataSet ds = new DataSet();
connection.Open();
da.Fill(ds, "Orders");
connection.Close();
dataGridView1.DataSource = ds;
.....
private void button1_Click(object sender, EventArgs e)
{
//?
//refresh selected row in datagrid (from current database record)
//?
EditForm()
}
Create a new query in your TableAdapter that should only get one row and call it with just the primary key of the row you already have.
Plug the result into a new DataSet and grab the first row (after checking for Rows.Count() > 0)
I would enclose the populating the gridview bit in it's own method say something like fill_grid(). Then just call the method in the edit link click event. Then whatever has changed will update. Then add the method to all the other button link events too. Then every time the user is clicking a link the grid "refreshes" essentially.
For those who is looking for the answer in 2019,
assuming dataAdapter is a defined earlier class member
private void ButtonUpdate_Click(object sender, RoutedEventArgs e)
{
if (dataGrid.SelectedItem is DataRowView view)
{
DataRow currentRow = view.Row;
DataTable table = currentRow.Table;
dataAdapter.Fill(table.Rows.IndexOf(currentRow), 1, table);
}
}

GridView edit when bound to a Datatable

I am creating a website where our customers can order parts directly from us. I have a datatable setup and when users click a button it adds a quick detail of the order to a gridview. In the gridview, I have the edit and delete buttons enabled. the delete function works fine, however when you try to edit the information, it doesn't change the gridview with the new info. Here's what I have so far:
protected void griditems_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
DataTable dt = (DataTable)Session["table"];
foreach (DataRow dr in dt.Rows)
{
part = Convert.ToString(dr["Part"]);
dr["Part"] = part;
dr["Quantity"] = qty;
dr["Ship-To"] = shipto;
}
griditems.EditIndex = -1;
BindData();
}
when trying this, it displays the gridview back with the original input values. I have also tried this (not working and get an error that says "There is no row at position 0":
DataTable dt = (DataTable)Session["table"];
GridViewRow row = griditems.Rows[e.RowIndex];
dt.Rows[row.DataItemIndex]["Part"] = ((TextBox)(row.Cells[1].Controls[0])).Text;
dt.Rows[row.DataItemIndex]["Quantity"] = ((TextBox)(row.Cells[2].Controls[0])).Text;
dt.Rows[row.DataItemIndex]["Ship-To"] = ((CheckBox)(row.Cells[3].Controls[0])).Checked;
griditems.EditIndex = -1;
BindData();
Am I missing an EditItemTemplate in the aspx file, or am I just doing the RowUpdating all wrong?
You probably need to step back a bit and first check out how you could do create, update, delete and read with a grid view. Also, you may wanna check this post.

Categories