Datagridview updation bug - c#

In my my project, I wrote a code such that if there is no data in the DGV it should not be updated, but even though data is not there when I click on the row which is empty and comes by default, and then on update button, it is getting updated. Please help me to fix the issue. The code I am using is:
private void btnUpdate_Click(object sender, EventArgs e)
{
if (dataGridView2.SelectedCells.Count == 0 )
{
MessageBox.Show("There are no any records to update");
}
else
{
SqlConnection con = Helper.getconnection();
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
con.Open();
cmd.CommandType = CommandType.Text;
string PrjName = txtPrjNmae.Text;
string Description = txtPrjdescription.Text;
DateTime Date = dateUpdate.Value;
dateUpdate.Format = DateTimePickerFormat.Custom;
dateUpdate.CustomFormat = "dd/MM/yy";
string Size = txtPrjSize.Text;
string Manager = txtPrjManager.Text;
cmd.CommandText = "Update Projects set Description='" + Description + "', DateStarted='" + Date + "',TeamSize='" + Size + "',Manager='" + Manager + "' where ProjectName= '" + PrjName + "' ";
MessageBox.Show("Project Details are updated");
dataGridView2.Update();
dataGridView2.Refresh();
cmd.ExecuteNonQuery();
con.Close();
}
BindData3();
}

You can prevent user from adding new row by click on the last row of datagridview via settig AllowUserToAddRows = false

Check this
dataGridView2.Rows.Count > 0
in a condition

Instead of checking if (dataGridView2.SelectedCells.Count == 0 )
Do this
if( dataGridView2.Rows.Count > 0)
{
}
This will only do conditions if there is more than 0 rows.

first set
dataGridView2.AllowUserToAddRows = false
or
check every time while updating.
dataGridView2.Rows.Count > 0
or
if(dataGridView2.Rows[e.RowIndex].Cells[e.ColumnIndex].EditedFormattedValue.ToString() != " ")
//do ur update here

Since you are letting the users to insert row through a different form (not through grdiview) first hide the empty row which is displayed by default as AllowUserToAddRow property is set to true, You have to set this property to false.
Still if you are allowing the users to add empty row to the grid in some other way then you have to validate it when user click update button. One approach i could think of is,
Check if the selected row has one of the mandatory cell value. Assume ProjectName is mandatory value then you can write a logic as follows,
selectedRow.Cells["ProjectName"] here ProjectName is column name.
private void btnUpdate_Click(object sender, EventArgs e)
{
//Get the selected row
DataGridViewRow selectedRow = dataGridView1.SelectedRows[0];
//Check if Project Name cell in the selected row null or empty
if (string.IsNullOrWhiteSpace(selectedRow.Cells["ProjectName"].Value.ToString()))
{
MessageBox.Show("There are no any records to update");
}
else
{
}
}

Related

Winform Datagridview cellclick error - Index was out of range

I've got a simple data grid that lists a bunch of records from a SQLSERVER table. The data grid populates without any issues. I want to click on a row and load the corresponding data into text boxes that I have created next to it. So far so simple.
Here is my code for the cellclick event
private void dataGridVieworderitems_CellClick(object sender, DataGridViewCellEventArgs e)
{
{
//try
//{
//if (dataGridVieworderitems.SelectedRows.Count > 0) // make sure user select at least 1 row
{
string jobId = dataGridVieworderitems.SelectedRows[0].Cells[0].Value + string.Empty;
string standpack = dataGridVieworderitems.SelectedRows[0].Cells[1].Value + string.Empty;
string description = dataGridVieworderitems.SelectedRows[0].Cells[2].Value + string.Empty;
string price = dataGridVieworderitems.SelectedRows[0].Cells[3].Value + string.Empty;
string itemType = dataGridVieworderitems.SelectedRows[0].Cells[4].Value + string.Empty;
string notes = dataGridVieworderitems.SelectedRows[0].Cells[5].Value + string.Empty;
labelidvalue.Text = jobId;
labelstandpackvalue.Text = standpack;
labeldescriptionvalue.Text = description;
textBoxprice.Text = price;
labeltypevalue.Text = itemType;
textBoxnotes.Text = notes;
}
//}
//catch (Exception)
//{
// MessageBox.Show("something went wrong!");
//}
}
}
I have deliberately commented out the If statement and try catch block to generate the error..
I get the following error..
System.ArgumentOutOfRangeException was unhandled HResult=-2146233086
Message=Index was out of range. Must be non-negative and less than the
size of the collection. Parameter name: index ParamName=index ....
...
It's WINFORM and c#.. The datagrid view has the data.. yet it says index is out of range. can some one point me in the right direction please?
This is how I Populate my grid
public DataTable GetStaffCurrentOrderItems()
{
try
{
DataTable dtstaffcurrentorderlist = new DataTable();
string connString = System.Configuration.ConfigurationManager.ConnectionStrings["nav"].ConnectionString;
using (SqlConnection con = new SqlConnection(connString))
{
using (SqlCommand cmd = new SqlCommand("select [ID],standpack as [Item], item_description as [Description], '$'+convert(varchar(5),price) as Price,item_type as [Item Type],notes as [Notes] from tbl_staff_orders_items", con))
{
if (con.State == ConnectionState.Open)
{
con.Close();
}
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
dtstaffcurrentorderlist.Load(reader);
}
con.Close();
}
return dtstaffcurrentorderlist;
}
catch (Exception)
{
return null;
}
}
Make a check within your cellClick event handler for handling the nulls like this
if (dataGridVieworderitems.CurrentCell == null ||
dataGridVieworderitems.CurrentCell.Value == null ||
e.RowIndex == -1) return;
This will sort out your problem as it checks for all the possible nulls while clicking the cell of GridView. An else part will get you the data if there is anything except null.
Hope it helps!
Index was out of range
This means index not found on your datagrid cell.
Kindly check the rows of you datagrid if index exists same with the column too.
Edited:
Ha, got the exact problem source:
The SelectionMode property must be set to FullRowSelect for the SelectedRows property to be populated with selected rows.
Otherwise you can use the following options:
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
string jobId = dataGridView1.Rows[e.RowIndex].Cells[0].Value.ToString();
}
or
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
DataGridViewRow selectedRow = dataGridView1.Rows[dataGridView1.SelectedCells[0].RowIndex];
string jobId = selectedRow.Cells[0].Value.ToString();
}

BindingSource not moves to next record with MoveNext() after TableAdapter.Fill

I have this event on a button click below:
private void button4_Click(object sender, EventArgs e)
{
string connectionString2 = "Data Source=LPMSW09000012JD\\SQLEXPRESS;Initial Catalog=Pharmacies;Integrated Security=True";
string query2 = "UPDATE Liguanea_Lane2 SET Progress= '1' where code = '" + comboBox2.Text + "'; ";
using (SqlConnection connection = new SqlConnection(connectionString2))
{
SqlCommand command = new SqlCommand(query2, connection);
command.Connection.Open();
command.ExecuteNonQuery();
}
comboBox2.ResetText();
textBox1.Clear();
comboBox2.SelectedIndex = comboBox2.SelectedIndex + 1;
this.liguanea_Lane2TableAdapter.Fill(this.pharmaciesDataSet3.Liguanea_Lane2);
liguaneaLane2BindingSource.MoveNext();
}
The problem is this particular block of code:
this.liguanea_Lane2TableAdapter.Fill(this.pharmaciesDataSet3.Liguanea_Lane2);
liguaneaLane2BindingSource.MoveNext();
Wha it is doing is basically refreshing the datasource within the data grid and move to the next item in the table. Eg.After the button is clicked it Updates the "progress" column value to "1" and then refresh the data set and then call the .MoveNext to move the cursor to the next item in the table. It works but only executes once and then stops moving. The dataset refreshes fine but the .MoveNext is the issue. I try moving it above the dataset but then it does not execute the problem. What am I doing wrong?
When you call TableAdapter.Fill(Table) it cause the BindingSource which is bind to Table moves to first record. So calling bindingSource.MoveNext() after filling the table always moves to second record.
If for any reason you want to move to next record after filling the table using table adapter, store the current position before fill and set the position to next record after fill:
int current = 0;
private void Button1_Click(object sender, EventArgs e)
{
current = bindingSource1.Position;
tableAdapter1.Fill(dataSet1.Table1);
bindingSource1.Position = Math.Min(current + 1, bindingSource1.Count - 1);
}

not updating all the multiple selected cells values in the datagridview by clicking set button

private void dataGridView1_CellContentClick
(object sender,DataGridViewCellEventArgs e)
{
int i,j;
i = dataGridView1.CurrentCell.RowIndex;
j = dataGridView1.CurrentCell.ColumnIndex;
txtcellvalue.Text = dataGridView1.Rows[i].Cells[j].Value.ToString();
}
private void Setvaluebutton_Click(object sender, EventArgs e)
{
int i = 0;
//foreach(DataGridViewRow datagridviewrow in dataGridView1.Rows)
//{
i = dataGridView1.SelectedCells[0].RowIndex;
string study = dataGridView1.Rows[i].Cells[2].Value.ToString();
txtcellvalue.Text = dataGridView1.Rows[i].Cells[3].Value.ToString();
txtcellvalue1.Text = dataGridView1.Rows[i].Cells[4].Value.ToString();
string unit = dataGridView1.Rows[i].Cells[5].Value.ToString();
i = i + 1;
DialogResult dr = MessageBox.Show
("Would like to update the click yes!!",
"values", MessageBoxButtons.YesNo);
if (dr == DialogResult.Yes)
{
db.OpenDB();
string query = "Update [table] set [status]=" + study + ",
[limit]='" + txtcellvalue.Text + "' ,[limit2]='" + txtcellvalue1.Text
+ "',[unit]='" + unit + "' where [tno]=" + i + ";";
db.Update(query);
DatagridviewMethod();
db.CloseDB();
}
else
{
DatagridviewMethod();
}
// }
}
here what i am trying to do displaying all the database table values in datagridview.after displaying all the values in datagridview,tried to replace the cell values in the datagridview, i can edit and replace another values but while updating it will update only one row value and not all other rows(all selected rows) values at a time in datagridview.
kindly give me any suggestion to do?
If I'm understanding your code correctly, whenever you run that method, it's only doing it on the one row because the variable [i] never gets updated. Even if you have multiple rows selected it stays as the same because [i] will always point at your current or "active" row (which never gets changed anywhere in your code). To get around this, try iterating through the SelectedRows collection like
foreach (DataGridViewRow dgvrow in dataGridView1.SelectedRows) {
string study = dgvrow.Cells[2].Value.ToString();
txtcellvalue.Text = dgvrow.Cells[3].Value.ToString();
txtcellvalue1.Text = dgvrow.Cells[4].Value.ToString();
string unit = dgvrow.Cells[5].Value.ToString();
if (MessageBox.Show("Would like to update the click yes!!",
"values", MessageBoxButtons.YesNo) ==
System.Windows.Forms.DialogResult.Yes) {
// ETC...
}
else { }
}

Displaying records in Same Gridview when Search Button in particular panel is clicked

I have 2 Panels on one page(SAPInfo, OSInfo). In SAPInfo panel there are 3 textboxes(SID, Client,User_id) and 1 SEARCH button. After clicking SEARCH button i want to display data of SAP table(user_id,Descriptio,sap_system_password) in Gridview on the next page. Similarly In OSInfo panel there are 2 text boxes(IP/HostName,User_id) and 1 SEARCH button. After clicking SEARCH button i want to display data of OS table(user_id,Descriptio,os_system_password) in the same Gridview. The Gridview has 4 columns(UserID,Description,Password,Change Password) SAP table contains fields as(sid,client_no,user_id,sap_system_password,description) OS table contains fields as(user_id,ip,host_name,os_system_password,description)
How to do this? Please help..
this is my Search button(SAP) code
protected void btnSAPSearch_Click(object sender, EventArgs e)
{
try
{
using (MySqlConnection conn = new MySqlConnection(clsUser.connStr))
{
conn.Open();
string strQuery = "select DISTINCT user_id,description,sap_system_password from sap_password_info where user_id is not null";
if (txtSid.Text !="")
{
strQuery += " AND sid = '" + txtSid.Text + "'";
}
if (txtClient.Text != "")
{
strQuery += " AND client_no = '" + txtClient.Text + "'";
}
if (txtUser.Text != "")
{
strQuery += " AND user_id = '" + txtUser.Text + "'";
}
MySqlCommand cmd = new MySqlCommand(strQuery, conn);
DataTable dt = new DataTable();
dt.Load(cmd.ExecuteReader(CommandBehavior.CloseConnection));
Session["userinfo"] = dt;
Response.Redirect("~\\PasswordInformation_Details.aspx");
}
}
catch (Exception ex)
{
//lblMessage.Text = DataObjects.Error_Message();
lblMsg.Text = ex.Message.ToString();
}
}
The solution is pretty simple. Pass the search criteria as query string to your other page.
So on click of search button(SAP Panel) build a query string like following
//if sap
string url = "Result.aspx?Mode=SAP&sid=some_sid&client=some_client&user_id=some_user_id;
Response.Redirect(url, false);
So on click of search button(OS Panel)
//if OS
string url = "Result.aspx?Mode=OS&ip=some_ip&user_id=some_userId;
Response.Redirect(url, false);
ON result page page_load
if(Request.QueryString["Mode"] =="SAP")
{
//bring sap result dataset
}
else
{
// bring os result dataset
}
//bind it to gridView
resultGridView.DataSource = dsResult
resultGridView.DataBind();
Keep in mind. make the autogeneratedcolumn = true on the grid view. Now your grid view would display whatever result would be given to it(3 column, 4 columns).The columns would be dynamically generated now.
EDIT 1
After search, you would have some dataset with the result. To change the grid header, simply change the column name in the dataTable. What ever column you would give, would be displayed by the grid
datatable.Columns["original_column_name"].ColumnName = "new column name";
//For adding a new column, just simply do this to your result set
datatable.Columns.Add("Change Password");
EDIT 2
string strQuery = "select DISTINCT user_id as User Id,description as Description,sap_system_password as Sap System Password from sap_password_info where user_id is not null";
Also see this : Column Alias

Why am getting concurrency violation error?

I've MS Access db, datagridview that displays items, two checkbox columns that represents Yes/No columns in the db, and refresh/del buttons.
When I try to delete a row that its checkboxes hasn't been modified, the row delets just fine, also when I modify the checkbox value, press refresh button, then delete, the row deletes fine too.
However when I try to delete a row right after modifying its checkbox value, I get concurrency violation exception error.
When checkbox value changed code:
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (dataGridView1.Columns[e.ColumnIndex].Name == "sales")
{
DataGridViewCheckBoxCell checkCell = (DataGridViewCheckBoxCell)dataGridView1.Rows[e.RowIndex].Cells["sales"];
bool _pSale = (Boolean)checkCell.Value;
string connstring = string.Format(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0}", Path.Combine(Directory.GetCurrentDirectory(), "MyDatabase01.accdb"));
OleDbConnection conn = new OleDbConnection(connstring);
conn.Open();
string sqlqry = "UPDATE Items SET pSale = " + _pSale + " WHERE p_Name = '" + this._pName + "'";
OleDbCommand upd = new OleDbCommand(sqlqry, conn);
upd.ExecuteNonQuery();
conn.Close();
//dataGridView1.Invalidate();
}
}
Refresh button code:
public void Refreshdgv()
{
this.categoriesItemsBindingSource.EndEdit();
this.itemsTableAdapter.Fill(myDatabase01DataSet.Items);
this.dataGridView1.Refresh();
}
Delete button code:
private void delBtn_Click(object sender, EventArgs e)
{
try
{
int cnt = dataGridView1.SelectedRows.Count;
for (int i = 0; i < cnt; i++)
{
if (this.dataGridView1.SelectedRows.Count > 0)
{
this.dataGridView1.Rows.RemoveAt(this.dataGridView1.SelectedRows[0].Index);
}
}
this.Validate();
this.categoriesItemsBindingSource.EndEdit();
this.itemsTableAdapter.Update(this.myDatabase01DataSet.Items);
this.myDatabase01DataSet.AcceptChanges();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
To resolve this issue I can call Refreshdgv() method in place of dataGridView1.Invalidate(). But I don't want the dgv refresh for each checkbox click!
The delete command of your DataSet is likely checking the original values. Since you are updating your database manually in the CellValueChanged event, the values in your database won't match the original values in your DataSet. If you modify the CellValueChanged event to use the update command in your DataSet, the values should match up when you call Delete.
Alternatively, you could change your delete command to use a less exclusive where clause (e.g., WHERE KeySegment0 = #keySegment0 AND KeySegment1 = #keySegment1 ...).
Try validiting the data then update it. After that, clear your dataset and fill it up so it would refresh the datagrid every changes you made.

Categories

Resources