I am developing a program for a Computer Store using c# with VS2010 and Database Provider = OleDB.
I need a form for updating the existing Products information in the stock. So I have a DataGridView to show the products Table (Edit property = on)
My code for updating a row :
private void button1_Click(object sender, EventArgs e)
{
con.Open();
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
DataGridViewRow UpdateRow = dataGridView1.Rows[i];
if (UpdateRow.Selected == true)
{
try
{
com.CommandText = "UPDATE Products SET ProductName=#pname,Model=#model WHERE ProductID= " + UpdateRow.Cells[0].Value + "";
com.Connection = con;
com.Parameters.AddWithValue("#pname", UpdateRow.Cells[1].Value);
com.Parameters.AddWithValue("#model", UpdateRow.Cells[2].Value);
int count = com.ExecuteNonQuery();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
con.Close();
}
That code works and it updates the access database file but it's only for one row (the selected row)
Now i want to update every edit the user have done in the DataGridView
So all i have to do is to delete the line if (UpdateRow.Selected == true) and that way , the loop will go for every row and update the info .
I debugged the program and it didn't crash but the Access database didn't update anything! I wonder why...
There are 2 methods to accomplish this:
Follow the dataset and datatable route, assign the datatable to the grid and then use the getchanges() method to retrieve the rows which have changed and then update the selected rows into the database
Use the following following function to capture the rowindex property of the changed row
private void dataGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
// use e.rowindex to get the row being modified and keep that in some list and
//after update button is pressed get the rows and update accordingly
//
}
Related
I need to Hide the row from Gridcontrol instead of deleting the data from data source.
e.g when user deletes the row a query runs which inserts the 0 value in my table and Shows the table with rows whose value is not null.
I have tried using the code below. But i cant seem to run it.
del = 1;
ColumnView view = gridControl1.FocusedView as ColumnView;
view.FocusedRowHandle = user_typeTableAdapter1.Insert_del(del);
view.SelectRow(view.FocusedRowHandle);
The error occurs that I cannot put del only in table adapter although i inserted self defined query.
This is the main problem that is occurring and i don't have so much help in this matter.
Hi, The answer to this question is as given below.
Actually I was inserting the value instead of updating it.
All i had to do was to run a query and execute it when delete is called.
Note this is to demonstrate the data deleted from gridView in Devexpress
private void Delete(){
try
{
conn.Open();
ColumnView view = gridControl1.FocusedView as ColumnView;
int id = Convert.ToInt32(gridView1.GetDataRow(view.FocusedRowHandle)["product_id"]);
string query = "UPDATE product SET del =#product_del where product_id= #id";
int del = 1;
SqlCommand sc = new SqlCommand(query, conn);
sc.Parameters.AddWithValue("#product_del", del);
sc.Parameters.AddWithValue("#id", id);
sc.ExecuteScalar();
sc.Dispose();
conn.Close();
}
}
Now for gridView part
private void gridControl1_ProcessGridKey(object sender, KeyEventArgs e)
{
if (e.KeyData == Keys.Delete)
{
DialogResult dialogResult = MessageBox.Show("Are you sure you want to delete this row, it will permanently delete the data", "Delete?", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
ColumnView view = gridControl1.FocusedView as ColumnView;
view.CloseEditor();
{
Delete();
view.UpdateCurrentRow();
product_viewTableAdapter1.Fill(allDataSets1.Product_view);
}
}
}
}
Now every time user delete a row it will get hidden instead of being deleted.
Actually it was requirement by a user. So i had to implement it.
Edit 2: Turns out it only gives a NullReferenceException the first time. After that, it says that I am not allowed to change the ConnectionString property, even though I think I have closed it in the right places.
Thanks for taking the time to read this.
I am working on a WinForms application that uses an MS Access database, and I am currently having problems with an entry deletion feature I made.
So, I have a DataGridView that switches between 3 tables on a button click, and I have a function that deletes a row on a table that is currently open by clicking a button that is at the end of the row.
When I open my first table, and try to delete a row, it works just fine. However, if I open a different table afterwards and try to delete an entry, or even go back to the first table I opened, I get a NullReferenceException in the deletion function.
Here is the code to display one of the tables in DataGridView.
public DataTable Read()
{
connection.ConnectionString = connectionString;
OpenConnection(); //connection.Open() inside an if statement
dataTable.Clear();
OleDbCommand readStudentCommand = new OleDbCommand("select * from Students", connection); //display the whole list of students
OleDbDataReader reader = readStudentCommand.ExecuteReader();
dataTable.Load(reader);
connection.Close();
return dataTable;
}
Here is the code that deletes an entry
private void MainDataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
connection.ConnectionString = connectionString;
if (ConnectionState.Closed == connection.State)
{
connection.Open();
}
var senderGrid = (DataGridView)sender;
if (e.RowIndex >= 0 && senderGrid.Columns[e.ColumnIndex] == MainDataGridView.Columns["Delete"])
{
//this function retrieves the first column value of the deleted row, which has the ID of the entry (works with any table).
DeleteEntry(MainDataGridView.Rows[e.RowIndex].Cells[0].Value.ToString()); //exception thrown here (System.Windows.Forms.DataGridViewCell.Value.get returned null)
MainDataGridView.Rows.RemoveAt(e.RowIndex);
}
and here is DeleteEntry()
private void DeleteEntry(string deletedID)
{
string tableName = null;
string idType = null;
if (studentsDisplayed)
{
tableName = "Students";
idType = "Student ID";
}
else if(booksDisplayed)
{
tableName = "Books";
idType = "BookID";
}
else if(loansDisplayed)
{
tableName = "Loans";
idType = "Loan ID";
}
string deleteCommand = String.Format("DELETE * FROM {0} WHERE [{1}] = {2}", tableName, idType, deletedID);
OleDbCommand deleteEntryCommand = new OleDbCommand(deleteCommand, connection);
deleteEntryCommand.ExecuteNonQuery();
SaveData(); //this method just calls Update() in a dataAdapter of a relevant table
connection.Close();
}
Thank you!
Edit:
As per request, here is the code that switches the table. It simply references the first function and sets the returned dataTable as DataSource.
private void StudentButton_Click(object sender, EventArgs e) //display students
{
try
{
if (!studentsDisplayed)
{
MainDataGridView.DataSource = studentDAL.Read(); //studentDAL is the class that works with the Students table of my DB.
studentsDisplayed = true; //these 3 are to avoid duplicated creation of the same table
booksDisplayed = false;
loansDisplayed = false;
ComboBoxChanger(); //don't mind this, it's for an irrelevant feature
CreateButtons(5);
}
}
catch
{
throw;
}
}
Okay, so turns out the problem was the fact that DeleteEntry(MainDataGridView.Rows[e.RowIndex].Cells[0].Value.ToString()) had a problem with the Cells[0] part. After the first time loading a table, the 0th cell just vanished. So, I rewrote the code so that instead of declaring tableName and idType in DeleteEntry(), they're declared in MainDataGridView_CellContentClick(), and then made the DeleteEntry() accept 3 idType and tableName as parameters, and changed the MainDataGridView.Rows[e.RowIndex].Cells[0].Value.ToString() argument to MainDataGridView.Rows[e.RowIndex].Cells[idType].Value.ToString(). Now it works just fine!
I have 2 datagrid views with one datatable. I am trying to have a button that when clicked it adds the rows from csv_datagridview to optimal_datagridview. The below works however whenever I deselect an entry in csv_datagridview and hit the button again it clears that selection. I would like to have the selection stick each time.
if (selectedRowCount <= 9)
{
List<object> destList = new List<object>();
foreach (DataGridViewRow row in csv_datagridview.SelectedRows)
destList.Add(row.DataBoundItem);
optimaldataGridView.DataSource = destList;
Thank you so much in advance :)
It is unclear what your exact problem is with the little code you show, but from your statement whenever I deselect an entry in csv_datagridview and hit the button again it clears that selection. I am guessing that if nothing is selected, the data in optimaldataGridView clears when you press the add selected button.
I will assume the csv_datagridview is bound to a table. Your posted code shows the creation of new List destList which you fill with the selected rows from the csv_datagridview. Then you set optimaldataGridView data source to the destList. One issue I see in this picture is that as soon as you leave the if (selectedRowCount <= 9) clause… destList will no longer exist. As a data source for a DataGridView on your form, I would think you would want to keep this List global as long as the form is open. Either way... you are not adding the selected rows, you are simply removing the existing rows and then adding what was selected in csv_datagridview.
I hope the code below will help. I created two DataTables, one for each DataGridView. The csv_datagridview data table is filled with some data, the second data table is left empty. Then simply add the selected rows from the csv_datagridview to the optimaldataGridView’s DataTable… Then refresh optimaldataGridView.
DataTable table1;
DataTable table2;
public Form1() {
InitializeComponent();
csv_datagridview.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
optimaldataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
table1 = GetTable("table1");
table2 = GetTable("table2");
FillTable(table1);
csv_datagridview.DataSource = table1;
optimaldataGridView.DataSource = table2;
}
private void button1_Click(object sender, EventArgs e) {
if (csv_datagridview.SelectedRows.Count > 0) {
foreach (DataGridViewRow row in csv_datagridview.SelectedRows) {
DataRowView dr = (DataRowView)row.DataBoundItem;
table2.Rows.Add(dr.Row.ItemArray[0], dr.Row.ItemArray[1], dr.Row.ItemArray[2]);
}
optimaldataGridView.Refresh();
}
}
private DataTable GetTable(string name) {
DataTable table = new DataTable(name);
table.Columns.Add("col1");
table.Columns.Add("col2");
table.Columns.Add("col3");
return table;
}
private void FillTable(DataTable table) {
for (int i = 0; i < 10; i++) {
table.Rows.Add("R" + i + "C0", "R" + i + "C1", "R" + i + "C2");
}
}
Hope this helps.
Your code is working on my side.
Created a DataTable for Datasource of csv_datagridview.
Selected some rows in this grid.
Clicked the button to copy the selected rows to the
optimaldataGridView
The selected rows are still selected.
public Form1()
{
InitializeComponent();
DataTable dt = new DataTable();
dt.ReadXml(Application.StartupPath + #"\test.xml");
csv_datagridview.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
csv_datagridview.DataSource = dt;
}
private void button1_Click(object sender, EventArgs e)
{
List<object> destList = new List<object>();
foreach (DataGridViewRow row in csv_datagridview.SelectedRows)
destList.Add(row.DataBoundItem);
optimaldataGridView.DataSource = destList;
}
Make sure you have no events attached to the grids that may affect the selection.
I have a dataGridVew1 on my windows form that I am populating from SQL using SQL Adapter named in my case "sda".
You can see how I update my grid below (maybe I am doing something wrong):
SqlConnection con = new SqlConnection("connection string"); //defining connection
con.Open();
string sql_command = "Select * from Test_Table";
SqlCommand command = new SqlCommand(sql_command, con); // defining the command
DataSet set = new DataSet("SQL_table");
SqlDataAdaptersda = new SqlDataAdapter(command); //defining the adapter and make it accept changes
sda.AcceptChangesDuringFill = true;
sda.AcceptChangesDuringUpdate = true;
set.Clear(); //just to make sure my adapter is empty
cmdBuilder = new SqlCommandBuilder(sda); //creating the command builder so I can save the changes
sda.Fill(set, "SQL_table"); // fill the dataset
dataGridView1.DataSource = set;
dataGridView1.DataMember = "SQL_table"; //fill datagrid
dataGridView1.CellValueChanged -= dataGridView1_CellValueChanged;
dataGridView1.CellValueChanged += dataGridView1_CellValueChanged; //look for cell value changed (I am using this in other scope)
When I manually change a value to any cell of the grid I use a button to save the changes to the database using:
private void button2_Click(object sender, EventArgs e)
{
sda.Update(set.Tables["SQL_table"]);
}
It works perfectly.
I have added a second button to change a cell value in the datagrid for the selected row, but I have trouble saving those changes.
private void button3_Click(object sender, EventArgs e)
{
if (dataGridView1.SelectedRows.Count > 0) //I am checking to see if any row is selected
{
row_index = this.dataGridView1.SelectedRows[0].Index; //to get the selected row index
this.dataGridView1.Rows[row_index].Cells[2].Value = "change"; //I am changing the cell text on column 2 on the selected row
dataGridView1.EndEdit(); //added this to try an make it work
sda.Update(set.Tables["SQL_table"]); //trying to update the database
}
else
MessageBox.Show("Please first select the row with the quote that is awaiting feedback."); // in case no row is selected
}
This does not save the data to the database. I also tried pressing the other save button afterward but no result, no data is saved in the database even if the value "changed" is visible in the grid.
I know I cannot put the save command in the CellValueChanged event because it does not take the last change.
How can I make it work in a separate button as mentioned above? What I need is to:
1. Press the button - that changes the value of a cell
2. commit the changes in the database.
Thank you.
Danut
EDIT 1: on Bolu's request
I am using the CellValueChanged event to update a column in my datagrid when other cells are changed:
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex > -1 && e.ColumnIndex < 13)
{
DateTime datetime_send = DateTime.Now;
dataGridView1.Rows[e.RowIndex].Cells[13].Value = datetime_send;
}
}
I tried putting the update in the event but it does not save, so I am using the separate button to call the database save. (but this is another story). Now I just want to save the changes that i do with button3, which is update one cells value and then save in the database.
I'd like to erase all row in a datatable located in a dataset and then update the DataBase using the method Update() of TableAdapter.
The insert works fine, I put it so you can see what I'm doing. I tried the method Clear() for datatable which was supposed to erase all row but at the moment it does nothing.
I would like to use a kind of SQL query like DELETE * FROM demande; but I dont get how to do it
protected void InsertDemande_Click(object sender, EventArgs e)
{
//TB = textBox
//Parsing date (5th row of my dataTable is type date)
string[] tabdate = TB_date_demande.Text.Split('/');
DateTime date = new DateTime(int.Parse(tabdate[2]), int.Parse(tabdate[1]), int.Parse(tabdate[0]));
//In my dataset "Demande", on my table "Demande", i add a new row type "demande" with all good parameters
ds_Demande.Demande.AddDemandeRow(TB_demande_ID.Text, TB_user_ID.Text, TB_nom_fichier.Text, int.Parse(TB_poids_fichier.Text), date);
ta_Demande.Update(ds_Demande);//update the database
LabelResponse.Text = "Ajout effectué avec succès";
GridViewDemande.DataBind();//refresh gridview
}
protected void ClearTable_Click(object sender, EventArgs e)
{
ds_Demande.Demande.Clear();//doesn't seem to do anything
ta_Demande.Update(ds_Demande);
GridViewDemande.DataBind();
}
// Clear all rows of each table.
ds_Demande.Clear();
// alternatively:
foreach(var row in ds_Demande.Rows) {
row.Delete();
}
for(int i = 0; i<ds_Demande.Count; i++)
{
ds_Demande.Rows[i].Delete();
}