How to add a row into datatable on button click event? - c#

In Windows Forms, I want to add row by row into DataGridView on button click event by taking the values from other controls. I am using DataTable in this case and it is bound to DataGridView.
I am using the following code and it is working fine when the data is inserted for the first time. But my problem is when I click the button for the second time, the first row is overwritten with the second row of data.
private void btnAddToGrid_Click(object sender, EventArgs e)
{
LoadDataGridView();
}
private void LoadDataGridView()
{
dgvAdjustment.DataSource = GetAdjustmentTable();
}
private DataTable GetAdjustmentTable()
{
DataTable adjustmentTable = new DataTable();
DataColumn dataColumn;
dataColumn = new DataColumn("SourceOutletID", typeof(int));
adjustmentTable.Columns.Add(dataColumn);
dataColumn = new DataColumn("DestinationOutletID", typeof(int));
adjustmentTable.Columns.Add(dataColumn);
dataColumn = new DataColumn("TransactionDate", typeof(DateTime));
adjustmentTable.Columns.Add(dataColumn);
dataColumn = new DataColumn("MaterialName", typeof(string));
adjustmentTable.Columns.Add(dataColumn);
dataColumn = new DataColumn("AdjustmentType", typeof(int));
adjustmentTable.Columns.Add(dataColumn);
dataColumn = new DataColumn("CurrentBalance", typeof(decimal));
adjustmentTable.Columns.Add(dataColumn);
dataColumn = new DataColumn("AdjustmentQty", typeof(decimal));
adjustmentTable.Columns.Add(dataColumn);
dataColumn = new DataColumn("NewBalance", typeof(decimal));
adjustmentTable.Columns.Add(dataColumn);
DataRow dataRow = adjustmentTable.NewRow();
dataRow[0] = cmbSourceOutlet.SelectedValue;
dataRow[1] = cmbDestinationOutlet.SelectedValue;
dataRow[2] = TransDateTimePicker.Value;
dataRow[3] = cmbMaterialName.SelectedValue;
dataRow[4] = cmbAdjustmentType.SelectedValue;
dataRow[5] = Convert.ToDecimal(lblCurBalVal.Text);
dataRow[6] = Convert.ToDecimal(lblAdjVal.Text);
dataRow[7] = Convert.ToDecimal(lblNewQtyVal.Text);
int insertPosition = adjustmentTable.Rows.Count;
adjustmentTable.Rows.InsertAt(dataRow, insertPosition);
return adjustmentTable;
}
In ASP .NET applications, I use the session state to check whether DataTable is null by using the following code:
protected void Button1_Click(object sender, EventArgs e)
{
try
{
//Check if previous session is exist
if (Session["MyTable"] == null)
{
dtMyTable = new DataTable("MyTable");
dtMyTable.Columns.Add("Id", typeof(int));
dtMyTable.Columns.Add("LName", typeof(string));
}
else
{
//If yes then get it from current session
dtMyTable = (DataTable)Session["MyTable"];
}
//Add new row every time
DataRow dt_row;
dt_row = dtMyTable.NewRow();
dt_row["Id"] = TextBox1.Text;
dt_row["LName"] = TextBox2.Text;
dtMyTable.Rows.Add(dt_row);
//Update session table
Session["MyTable"] = dtMyTable;
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
}
What can I do and how can I make the changes to get the right solution in Windows Forms? Any help will be much appreciated!

In GetAdjustmentTable, you are recreating adjustmentTable every time. So a new row will just overwrite the existing one.
You need to modify the code such that adjustmentTable is only created just once and subsequent calls add rows to it. One way to do that would be to make it a private field and to check if it's null, and create it if it is:
private DataTable _adjustmentTable;
private DataTable GetAdjustmentTable()
{
if (adjustmentTable == null)
{
adjustmentTable = new DataTable();
}
....

Related

I have two datagridview, one on the staff calls, I want to make the other contain the number of staff did the call

The following images show my two datagrid views
From what I understand from your question, you can use the following method
public DataTable numOfCalls(DataTable table)
{
//Initialize Result Table
DataTable numOfCallsTable = new DataTable();
numOfCallsTable.Columns.Add("agentName", typeof(string));
numOfCallsTable.Columns.Add("numOfCall", typeof(int));
// Get the unique agents
DataView view = new DataView(table);
DataTable distinctValues = view.ToTable(true, "agentName");
// Check if there are agents
if (distinctValues.Rows.Count > 0)
{
// Loop thru the agents
for (int i = 0; i < distinctValues.Rows.Count; i++)
{
string agentName = distinctValues.Rows[i]["agentName"].ToString();
// Get all the rows that this agent has
DataRow[] agentRows = table.Select($"agentName='{agentName}'");
// And then fill the second table
DataRow newRow = numOfCallsTable.NewRow();
newRow["agentName"] = agentName;
newRow["numOfCall"] = agentRows.Length;
numOfCallsTable.Rows.Add(newRow);
}
}
return numOfCallsTable;
}
You can call this method every time you add or delete a line to the first table.
update for the button that you asked
private void Button1_Click(object sender, EventArgs e)
{
DataTable dt = new DataTable();
dt = (DataTable)dataGridView1.DataSource;
dataGridView2.DataSource = numOfCalls(dt);
}

How to save Datasource in a List<string> (no sqlconnection etc)

I have asked a similar question here but in my case I need to store multiple sets of datasets for an unknown number of times, not just once. So that is why I am asking here again.
I have multiple datatables with 2 columns in each datatable. One of them is a bool column (checkbox values). The checkbox values are empty when the form loads so up to user to check or uncheck them. Upon updating the checkbox, user press button1 to save only checkbox values in a dataset and this dataset will be saved in a List.
These datatables will then empty out and the same steps repeat for an unknown number of times (form loads empty datatables, user update checkboxes, user press button1). I have used the method below. No errors but when I want to display the List value in datagridview1 in Form2, it was empty. Below is my code. Hope to get help, thanks!
Class 1.cs (where I initiated my List)
public static List<string> list = new List<string>();
Form1.cs
//Create dataset
private DataSet Getdataset()
{
DataSet ds = new DataSet();
DataTable dt1 = new DataTable();
dt1.Columns.Add("Items", typeof(string));
dt1.Columns.Add("Status", typeof(bool));
dt1.Rows.Add("hello");
dt1.Rows.Add("hello");
ds.Tables.Add(dt1);
dgv1.DataSource = dt1;
dgv1.AllowUserToAddRows = false;
DataTable dt2 = new DataTable();
dt2.Columns.Add("Items", typeof(string));
dt2.Columns.Add("Status", typeof(bool));
dt2.Rows.Add("bye");
dt2.Rows.Add("bye");
ds.Tables.Add(dt2);
dgv2.DataSource = dt2;
dgv2.AllowUserToAddRows = false;
return ds;
}
//Save dataset in a List
private void button1_Click(object sender, EventArgs e)
{
DataSet dd = Getdataset();
foreach (DataTable table in dd.Tables)
{
foreach (DataRow row in table.Rows)
{
Class1.list.Add(Convert.ToString(row["Status"]));
}
}
Form2 f = new Form2();
f.ShowDialog();
}
Form2.cs
//Display dataset in datagridview
private void compile_VisibleChanged(object sender, EventArgs e)
{
DataGridViewRow row = (DataGridViewRow)dataGridView1.Rows[0].Clone();
foreach (string item in Class1.list)
{
row.Cells[0].Value = item;
}
dataGridView1.Rows.Add(row);
}
EDIT
As per er-sho comment, I added a messagebox in the code per below and it showed Systems.Collection.Generic.List1[System.String] 7 times (I have 6 checkboxes). There was still no display in the datagridview1 and I initialized the no. of columns, headers for datagridview1 to avoid compilation error. However, see below comment under Gokham’s solution (seems like the data in List is not per expected)
foreach (string item in Class1.list)
{
MessageBox.Show(Class1.list.ToString());
row.Cells[0].Value = item;
}
Everytime, when you click button1, you rewrite your data in dgv1 with default values:
DataTable dt1 = new DataTable();
dt1.Rows.Add("hello");
dt1.Rows.Add("hello");
dgv1.DataSource = dt1;
dt1 will be contains rows with only Item values, but not with Status. You should add code with getting user inputs
UPDATE
To achieve the goal you should make follow steps:
Init dgv1 - add columns and fill rows with default values
private void Form1_Load(object sender, EventArgs e)
{
UpdateDgv1();
}
private void UpdateDgv1()
{
DataSet ds = new DataSet();
DataTable dt1 = new DataTable();
dt1.Columns.Add("Items", typeof(string));
dt1.Columns.Add("Status", typeof(bool));
dt1.Rows.Add("hello");
dt1.Rows.Add("hello");
ds.Tables.Add(dt1);
dgv1.DataSource = dt1;
dgv1.AllowUserToAddRows = false;
}
Get values from dgv1 on button click
private void button1_Click(object sender, EventArgs e)
{
for (var i = 0; i < dgv1.Rows.Count; i++)
{
list.Add(Convert.ToString(dgv1.Rows[i].Cells[1].Value));
}
//restore dgv1
UpdateDgv1();
Form2 f = new Form2();
f.ShowDialog();
//clear list with old values or comment it
//if you want to save history of user inputs
list.Clear();
}
Show list content on datagridview1 of Form2
private void Form2_VisibleChanged(object sender, EventArgs e)
{
dataGridView1.ColumnCount = 1;
foreach (string item in Form1.list)
{
var newRow = dataGridView1.Rows.Add();
//if checkbox from Form1 not checked
if (item == string.Empty)
dataGridView1.Rows[newRow].Cells[0].Value = false.ToString();
else
dataGridView1.Rows[newRow].Cells[0].Value = item;
}
}
Your Getdataset() method doesn't fill Status column of the table. Try
private DataSet Getdataset()
{
DataSet ds = new DataSet();
DataTable dt1 = new DataTable();
dt1.Columns.Add("Items", typeof(string));
dt1.Columns.Add("Status", typeof(bool));
DataRow dr = dt1.NewRow();
dr["Items"] = "Hello";
dr["Status"] = checkBox1.Checked;
dt1.Rows.Add(dr);
ds.Tables.Add(dt1);
dgv1.DataSource = dt1;
dgv1.AllowUserToAddRows = false;
...
return ds;
}
I recommend you using BindingList instead of List and assigning the list as the DataSource for dataGridView1.
public static BindingList<string> list = new BindingList<string>();
Form 2
private void compile_VisibleChanged(object sender, EventArgs e)
{
dataGridView1.DataSource = Class1.list;
}
I think using FormLoad event handler instead of VisibleChanged should be better in your case.
Have a look : Binding List<T> to DataGridView in WinForm

Pass gridview data(one page) to another page's gridview control using winforms

I have two pages in my windows application. Both pages have a gridview control. I can pass textbox values into 2nd form but my problem is, I dont know how to pass whole gridview data into 2nd form.
Form1:
public partial class Billing : Form
{
DataTable dt;
public Billing()
{
InitializeComponent();
SetDataTable();
txtBillNo.Text = Convert.ToString(billno);
}
public void btnEnter_Click(object sender, EventArgs e)
{
int row = dgvBilling.RowCount;
DataRow dr;
if (dgvBilling.RowCount != 0)
{
dr = dt.NewRow();
dr["IName"] = txtIName.Text.Trim();
dr["Icode"] = txtIcode.Text.Trim();
dr["Quantity"] = txtQuantity.Text.Trim();
dr["UnitPrice"] = txtUnitPrice.Text.Trim();
int amount = Convert.ToInt32(txtQuantity.Text.Trim()) * Convert.ToInt32(txtUnitPrice.Text.Trim());
dr["amount"] = Convert.ToString(amount);
dt.Rows.Add(dr);
int total = 0;
for (int i = 0; i < dgvBilling.Rows.Count; ++i)
{
total += Convert.ToInt32(dgvBilling.Rows[i].Cells[5].Value);
txtTotal.Text = "Rs/" + "" + Convert.ToString(total);
}
}
else
{
//dt = SetDataTable();
dr = dt.NewRow();
dr["IName"] = txtIName.Text.Trim();
dr["Icode"] = txtIcode.Text.Trim();
dr["Quantity"] = txtQuantity.Text.Trim();
dr["UnitPrice"] = txtUnitPrice.Text.Trim();
int amount = Convert.ToInt32(txtQuantity.Text.Trim()) * Convert.ToInt32(txtUnitPrice.Text.Trim());
dr["Amount"] = Convert.ToString(amount);
dt.Rows.Add(dr);
int total = 0;
for (int i = 0; i < dgvBilling.Rows.Count; ++i)
{
total += Convert.ToInt32(dgvBilling.Rows[i].Cells[5].Value);
txtTotal.Text = "Rs/" + "" + Convert.ToString(total);
}
RetrieveData();
}
}
public DataTable SetDataTable()
{
dt = new DataTable();
DataColumn dc = new DataColumn("IName", typeof(string));
dt.Columns.Add(dc);
dc = new DataColumn("Icode", typeof(string));
dt.Columns.Add(dc);
dc = new DataColumn("Quantity", typeof(string));
dt.Columns.Add(dc);
dc = new DataColumn("UnitPrice", typeof(string));
dt.Columns.Add(dc);
dc = new DataColumn("Amount", typeof(string));
dt.Columns.Add(dc);
DataGridViewCheckBoxColumn checkBoxColumn = new DataGridViewCheckBoxColumn();
checkBoxColumn.HeaderText = "";
checkBoxColumn.Width = 50;
checkBoxColumn.Name = "checkBoxColumn";
dgvBilling.Columns.Insert(0, checkBoxColumn);
dgvBilling.DataSource = dt;
return dt;
}
private void btnPrintBill_Click(object sender, EventArgs e)
{
PrintBill pb = new PrintBill();
pb.Controls["lblNetAmount"].Text = txtTotal.Text;
pb.Show();
}
}
}
form2:
public partial class PrintBill : Form
{
public PrintBill()
{
InitializeComponent();
Billing bg = new Billing();
dataGridView1.DataSource = bg.RetrieveData();
}
}
When I click PrintBill button I want to show 2nd form with the gridview values of first form...
As a good option you can use a DataTable as data source of your DataGridView and when you need to pass data to other form, use Copy method of that DataTable. Here is an example:
Your GridForm:
public partial class GridForm : Form
{
public GridForm()
{
InitializeComponent();
}
//we will this as data source
private DataTable table;
private void GridForm_Load(object sender, EventArgs e)
{
//Create the data table here and bind it to grid
table = new DataTable();
table.Columns.Add(new DataColumn("IName", typeof(string)));
table.Columns.Add(new DataColumn("Icode", typeof(string)));
table.Columns.Add(new DataColumn("Quantity", typeof(string)));
table.Columns.Add(new DataColumn("UnitPrice", typeof(string)));
table.Columns.Add(new DataColumn("Amount", typeof(string)));
this.dataGridView1.DataSource = table;
}
private void passDataButton_Click(object sender, EventArgs e)
{
//When you need to pass data, use Copy method of data table
var clone = table.Copy();
//Pass data to other form
var f = new OtherForm(clone);
f.ShowDialog();
}
}
Your OtherForm:
public partial class OtherForm : Form
{
DataTable table;
public OtherForm(DataTable value)
{
InitializeComponent();
//get passed data and put it in some member variable for next usages
table = value;
//Bind data to other grid or do other things here or in Form Load event
this.dataGridView1.DataSource = table;
}
}
Actually, you can make that datarow/DataTable a global variable to make it accessible to other class. And also, you can create a public method that returns a datatable like :
public DataTable RetrieveData()
{
DataTable dt;
//retrive necessary data here
return dt;
}

Dynamically creating session on Button Click

Actually i have created one session object and i am storing multiple textbox, radio & checkbox value in that session.
Here is my Code(My Insertion page, where i'll insert values and store in session).
protected void btnRegister_Click(object sender, EventArgs e)
{
//Creating DataTable dt
DataTable dt = new DataTable();
//Creating DataTable Columns
dt.Columns.Add("FName", typeof(string));
dt.Columns.Add("MName", typeof(string));
dt.Columns.Add("LName", typeof(string));
dt.Columns.Add("Phone", typeof(string));
dt.Columns.Add("EId", typeof(string));
dt.Columns.Add("State", typeof(string));
dt.Columns.Add("City", typeof(string));
dt.Columns.Add("Country", typeof(string));
dt.Columns.Add("PCode", typeof(string));
dt.Columns.Add("Gender", typeof(string));
dt.Columns.Add("AOI", typeof(string));
dt.Rows.Add(txtFN.Text, txtMN.Text, txtLN.Text, txtPhone.Text, txtEId.Text, ddlState.Text, ddlCity.Text, txtCountry.Text, txtPCode.Text, rdGender.SelectedValue, cbAOI.SelectedValue);
//Creating Session object to store DataTable dt
Session.Add("Insert", dt);
lblMandatory.Text = "Successfully Inserted into Database";
System.Threading.Thread.Sleep(1000);
Response.Redirect("Home.aspx");
}
I just wanted to know, is there any way to create new session whenever i click Register button i.e., i don't want to overwrite existing session, but on each button click, i want to create new session automatically.
My Home Page, where i'll display this dataTable using GridView
protected void Page_Load(object sender, EventArgs e)
{
if ((!IsPostBack) && (Session["Insert"] != null))
{
//At another place you retrieve datatable:
DataTable dt = new DataTable();
dt = (DataTable)Session["Insert"];
//Binding GridView with DataTable dt
gdvView.DataSource = dt;
gdvView.DataBind();
}
}
My Problem is, everytime GridView column get replaced with new GridView column, since my session get replaced with new values.
So is there any way, i can store new session value into gridview without loosing previous values from gridview.
Ok I get what's your problem now.
You don't need to create a new session everytime
here is a snippets;
DataTable dt;
if (Session["Insert"]_== null) //or nothing
{
dt = new DataTable();
}
else
{
dt = (DataTable)Session["Insert"];
}
//Add to dt.Rows here
//Save it again to Session["Insert"]
//Then bind dt to GridView again
This way you won't need new sessions and your dt data is retained,
//Creating DataTable dt
DataTable dt = new DataTable(); //Declare dt only once. If this wont work put it in a get set property.
protected void Page_Load(object sender, EventArgs e)
{
if ((!IsPostBack)
{
CreateDataTable();
LoadDataTable();
}
gdvView = Nothing; //or Null;
gdvView.DataSource = dt;
gdvView.DataBind();
}
protected void CreateDataTable()
{
//Creating DataTable Columns
dt.Columns.Add("FName", typeof(string));
dt.Columns.Add("MName", typeof(string));
dt.Columns.Add("LName", typeof(string));
dt.Columns.Add("Phone", typeof(string));
dt.Columns.Add("EId", typeof(string));
dt.Columns.Add("State", typeof(string));
dt.Columns.Add("City", typeof(string));
dt.Columns.Add("Country", typeof(string));
dt.Columns.Add("PCode", typeof(string));
dt.Columns.Add("Gender", typeof(string));
dt.Columns.Add("AOI", typeof(string));
}
protected void LoadDataTable()
{
if ((Session["Insert"] == null) //or (Session["Insert"] == nothing)
{
Session.Add("Insert", dt);
}
else {
dt = (DataTable)Session["Insert"];
{
}
protected void btnRegister_Click(object sender, EventArgs e)
{
//Do whatever you need to do as is
dt.Rows.Add(txtFN.Text, txtMN.Text, txtLN.Text, txtPhone.Text, txtEId.Text, ddlState.Text, ddlCity.Text, txtCountry.Text, txtPCode.Text, rdGender.SelectedValue, cbAOI.SelectedValue);
LoadDataTable();
/* Remove this block if you don't need it here */
gdvView = Nothing; //or Null;
gdvView.DataSource = dt;
gdvView.DataBind();
/* Remove this block if you don't need it here */
lblMandatory.Text = "Successfully Inserted into Database";
System.Threading.Thread.Sleep(1000);
Response.Redirect("Home.aspx");
}
You can try the following code. Here, I am testing if there already exist a value in this session, "Insert". If yes, a new row is being appended to it otherwise, a new DataTable is created.
protected void btnRegister_Click(object sender, EventArgs e)
{
//Creating DataTable dt
DataTable dt;
if (Session["Insert"] == null) //or nothing
{
dt = new DataTable();
//Creating DataTable Columns
dt.Columns.Add("FName", typeof(string));
dt.Columns.Add("MName", typeof(string));
dt.Columns.Add("LName", typeof(string));
dt.Columns.Add("Phone", typeof(string));
dt.Columns.Add("EId", typeof(string));
dt.Columns.Add("State", typeof(string));
dt.Columns.Add("City", typeof(string));
dt.Columns.Add("Country", typeof(string));
dt.Columns.Add("PCode", typeof(string));
dt.Columns.Add("Gender", typeof(string));
dt.Columns.Add("AOI", typeof(string));
}
else
{
dt = Session["Insert"] as DataTable;
}
dt.Rows.Add(txtFN.Text, txtMN.Text, txtLN.Text, txtPhone.Text, txtEId.Text, ddlState.Text, ddlCity.Text, txtCountry.Text, txtPCode.Text, rdGender.SelectedValue, cbAOI.SelectedValue);
//Creating Session object to store DataTable dt
Session["Insert"] = dt;
lblMandatory.Text = "Successfully Inserted into Database";
System.Threading.Thread.Sleep(1000);
Response.Redirect("Home.aspx");
}

Can't bind DataTable to GridView

Hey guys I've just started programming and I'm running into a problem. The new Datatable i created doesnt show in GridView2 when button1 is clicked. Although it is filled with data from the "planning" table(checked that dtPlanning is filled with the TextBoxes in comment).
So in short: I want to get DataTable planning into the new DataTable dtPlanning and display it in a gridview.
Code Behind:
protected void Button1_Click(object sender, EventArgs e)
{
DataTable dtPlanning = new DataTable();
dtPlanning.Columns.Add("Courseday", typeof(int));
dtPlanning.Columns.Add("Part", typeof(string));
dtPlanning.Columns.Add("Design", typeof(string));
dtPlanning.Columns.Add("Lesson", typeof(string));
//DataRow dr = planning.Rows[1];
//TextBox2.Text = (dr["Daynumber"]).ToString();
//TextBox3.Text = (dr["Part"]).ToString();
//TextBox4.Text = (dr["Design"]).ToString();
//TextBox5.Text = (dr["Lesson"]).ToString();
for (int i = 0; i < dtPlanning.Rows.Count; i++)
{
DataRow dr = dtPlanning.NewRow();
foreach (DataRow datarow in planning.Rows)
{
dtPlanning.Rows.Add(datarow);
}
}
GridView2.DataSource = dtPlanning;
GridView2.DataBind();
}
Source code:
<asp:GridView ID="GridView2" runat="server">
Thank you for your help.
Logically, dtPlanning.Rows.Count = 0 because this table is just initialized!
Secondly, you cannot Add a row from one table to another, user Import
for (int i = 0; i < planning.Rows.Count; i++)
{
dtPlanning.ImportRow(planning.Rows[i]);
}
I wonder why don't you just use the table planning?
You must:
Add to DataSet a new DataTable
Add to DataTable a new Columns
And GridView2.DataSource=YourNameDataSet.Tables[index_of_DataTable_in_DataSet].DefaultView;

Categories