How can I ADD, Delete and Edit multiple rows "containing textboxes" to Gridview
Without inserting to DB
I tried
Gridview1.rows.add(datarow)
And for delete
Gridview1.rows.remove(datarow)
but without detecting selected row
You can use the approach in code below for this. In the addRow method shown, a new grid row is inserted. The logic is that we need to re-bind the grid to a new data source that contains the original rows plus a new empty row. You can use a similar approach for delete ( create a new data source with deleted rows excluded and then rebind the grid).
When deleting use the method deleteRow. I have assumed that you have a check box control with an id of chkDelete in the grid row, which when checked would mean the row needs to be deleted. You can delete multiple rows at the same time using the method of deleteRow.
If you use the below two methods for adding a row and deleting row(s) then automatically your edited text boxes would have their new values retained always i.e. editing would then be automatically taken care of.
Assumptions made : Also, I have assumed that there are 3 text boxes in grid row in addition to a check box. Because there are 3 textboxes, so the DataTable being created in methods below should contain 3 columns for these 3 textboxes and these columns should be of string type.
Add a Row
protected void addRow()
{
DataTable dt = new DataTable();
//add code to create columns for this data table
//only create columns for textbox data
dt.Columns.Add("Column1", typeof(string));
dt.Columns.Add("Column2", typeof(string));
dt.Columns.Add("Column3", typeof(string));
DataRow dr = null;
//build a data source of existing rows
foreach (GridViewRow gridRow in grid1.Rows)
{
dr = dt.NewRow();
//set only text box values in new data source
//so checkbox column for row selection will be ignored
TextBox txtColumn1 = gridRow.FindControl("txtColumn1") as TextBox;
TextBox txtColumn2 = gridRow.FindControl("txtColumn2") as TextBox;
TextBox txtColumn3 = gridRow.FindControl("txtColumn3") as TextBox;
dr[0] = txtColumn1.Text;
dr[1] = txtColumn2.Text;
dr[2] = txtColumn3.Text;
dt.Rows.Add(dr);
}
//create the row in data sourec for the new grid row
dr = dt.NewRow();
dt.Rows.Add(dr);
//bind the grid view, which will now show you the new added row in addition to original rows
grd.DataSource = dt;
grd.DataBind();
}
Delete Row(s)
protected void deleteRow()
{
DataTable dt = new DataTable();
//add code to create column for this data table
//only set column for textbox columns
dt.Columns.Add("Column1", typeof(string));
dt.Columns.Add("Column2", typeof(string));
dt.Columns.Add("Column3", typeof(string));
//build a data source of existing rows
foreach (GridViewRow gridRow in grid1.Rows)
{
//get whether the checkbox for deleting row is checked or not
CheckBox chkDelete = gridRow.FindControl("chkDelete") as CheckBox;
//do not add original row if it was checked to be deleted
if(!chkDelete.Checked)
{
dr = dt.NewRow();
//set only text box values in new data source
//so checkbox column for row selection will be ignored
TextBox txtColumn1 = gridRow.FindControl("txtColumn1") as TextBox;
TextBox txtColumn2 = gridRow.FindControl("txtColumn2") as TextBox;
TextBox txtColumn3 = gridRow.FindControl("txtColumn3") as TextBox;
dr[0] = txtColumn1.Text;
dr[1] = txtColumn2.Text;
dr[2] = txtColumn3.Text;
dt.Rows.Add(dr);
}
}
//bind the grid view, which will now NOT have the deleted rows
grd.DataSource = dt;
grd.DataBind();
}
Related
I have binded a datagridview with access database table. I want to add a new custom column to DataGridView when the program loads. This column contains the auto incremented number "Serial Number" for the rows in the DataTable. The code is below,
using (var conn = new OleDbConnection(DatabaseObjects.ConnectionString))
{
conn.Open();
command = new OleDbCommand("SELECT s.RollNo, s.SName, s.FName, s.DOB, c.Class, s.[Section],s.Picture from students as s left outer join classes as c " +
"on c.ClassID = s.ClassID", conn);
dTable = new DataTable();
dTable.Load(command.ExecuteReader());
dgvDisplay.Columns.Add("SrNo", "Sr No"); // Adding "Serial No" Column to DataGridView
dgvDisplay.DataSource = dTable;
dgvDisplay.Sort(dgvDisplay.Columns["RollNo"], ListSortDirection.Ascending);
// Change Column Headings
dgvDisplay.Columns["RollNo"].HeaderText = "Roll No";
dgvDisplay.Columns["SName"].HeaderText = "Student Name";
dgvDisplay.Columns["FName"].HeaderText = "Father Name";
dgvDisplay.Columns["DOB"].HeaderText = "Date Of Birth";
// Serial Number code
int srNo = 1;
foreach(DataGridViewRow row in dgvDisplay.Rows)
{
row.Cells["SrNo"].Value = srNo;
srNo++;
}
}
But When I run the program the Serial number Column is empty. This column have to show numbers like 1,2,3.. for rows in gridview.
Now I changed the code for new column addition. I try this code below
dTable.Columns.Add(new DataColumn("SrNo", typeof(Int32))); // Adding "Serial No" Column to DataTable
dgvDisplay.DataSource = dTable;
dgvDisplay.Sort(dgvDisplay.Columns["RollNo"], ListSortDirection.Ascending);
// Serial Number code
int srNo = 1;
foreach (DataRow row in dTable.Rows)
{
row["SrNo"] = srNo;
srNo++;
}
This generate the Serial No but according to the order of the DataTable as the Record Rows are inserted to it.
I am still unclear what you want. I will assume from the picture that you want the column “SrNo” to have the numbers 1, 2, 3… etc.… instead of the “pre-sorted” index order. This is doable; however, it appears there may be some confusion as to setting a cell value in the “grid” as opposed to setting a cell value in the data source.
Example, looking at the first code snippet the code gets a DataTable dTable from a data base. Then the code adds a column to the GRID. Then the data source is set to the grid. Then the GRID is sorted. Finally, a loop through all the rows in the GRID to set the SrNo values. This is straight forward and from my tests… this SHOULD WORK. You state that the column is empty however in my tests this code worked as expected with 1, 2, 3 … in the “SrNo" column. It is unclear where this code is called so I would conclude something else is going on after this code is called.
As other have commented, it may be better to put the column into the DataSource DataTable itself. This is doable, however, there is one problem from the approach you are using… you need to SORT the data table FIRST before you add the “SrNo” Numbers AND the table that we add the ”SrNo” column to CAN NOT be sorted. Therefore, you need to get a “new” table from the “sorted” table.
It is unclear why you do not do all this when you initially query the data base, however, below is an example of what I described above.
To start let us see “why” we can NOT use a “pre” sorted DataTable to add the numbers to. First, we get a data table. Then sort the data table, then use it as a data source to the grid. If we add the new column to the GRID, then… this works just fine. However, if we add the column to the DataTable and loop through all the rows in the data table like…
foreach (DataRow row in dTable.Rows) {
row["SrNo"] = srNo;
srNo++;
}
This is NOT going to work because the loop is NOT going to loop through the “sorted” order. This is what I meant earlier when I said. “it cannot be a sorted table.” With that said, it would appear that a simple solution would be to get a NEW table that is already sorted. THEN add the “SrNo” numbers to that table.
In the Example below, if you comment out the line…
dTable = dTable.DefaultView.ToTable();
you will see the items are not added in the proper order.
A global DataTable is used, however this is unnecessary.
DataTable dTable;
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
//LoadDGV();
LoadDGV2();
}
LoadDGV() is the first snippet of code adding the column to the GRID and it works as expected.
private void LoadDGV() {
dTable = GetTable();
dgvDisplay.Columns.Add("SrNo", "Sr No"); // Adding "Serial No" Column to DataGridView
dgvDisplay.DataSource = dTable;
dgvDisplay.Sort(dgvDisplay.Columns["ID"], ListSortDirection.Ascending);
int srNo = 1;
foreach (DataGridViewRow row in dgvDisplay.Rows) {
row.Cells["SrNo"].Value = srNo++;
}
}
LoadDGV2() adds the column to the data table. The key line of code to make it work is… dTable = dTable.DefaultView.ToTable();
private void LoadDGV2() {
dTable = GetTable();
dTable.DefaultView.Sort = "ID";
dTable = dTable.DefaultView.ToTable();
dTable.Columns.Add(new DataColumn("SrNo", typeof(Int32))); // Adding "Serial No" Column to DataTable
int srNo = 1;
foreach (DataRow row in dTable.Rows) {
row["SrNo"] = srNo++;
}
dgvDisplay.DataSource = dTable;
}
A method to get some test data to complete the example.
private DataTable GetTable() {
DataTable dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Name", typeof(string));
Random rand = new Random();
for (int i = 0; i < 20; i++) {
dt.Rows.Add(rand.Next(1, 200), "Name_" + i);
}
return dt;
}
Hope that makes sense.
Hellou to everyone.
I would love the assistance from you guys.
My problem is like this:
I have this datagridview which I fill using datasource (a query to a db table). I only created manually one column which contain a checkbox. When the binding is complete I can click the checkboxes to select the row and I can select multiples rows this way.
I want to put the selected rows into a datatable (so I can read it and do some sql queries with the information on it) BUT when I read the selected rows to put them inside a datatable I need to skip the checkbox column (the first one).
How can I achieve this?
Okay, for future reference, I'm gonna post here how I fixed it.
DataTable dt = new DataTable();
if (dgvPedidos.SelectedRows.Count > 0)
{
foreach (DataGridViewColumn column in dgvPedidos.Columns)
dt.Columns.Add();
int i = 0;
foreach(DataGridViewRow row in dgvPedidos.Rows)
{
if (Convert.ToBoolean(dgvPedidos.Rows[i].Cells["chkPedido"].Value) == true)
{
dt.Rows.Add();
dt.Rows[i][1] = row.Cells[1].Value.ToString();
dt.Rows[i][2] = row.Cells[2].Value.ToString();
dt.Rows[i][3] = row.Cells[3].Value.ToString();
dt.Rows[i][4] = row.Cells[4].Value.ToString();
dt.Rows[i][5] = row.Cells[5].Value.ToString();
dt.Rows[i][6] = row.Cells[6].Value.ToString();
dt.Rows[i][7] = row.Cells[7].Value.ToString();
dt.Rows[i][8] = row.Cells[8].Value.ToString();
dt.Rows[i][9] = row.Cells[9].Value.ToString();
i++;
}
}
dt.Columns.RemoveAt(0);
I am having trouble displaying the XML on my c# WinForm.
My XML file looks like this:
<HotelDatabase>
<Hotel Name="ABC" Location="XYZ">
<Room Type="Single" Count="5" Price="2000" />
<Room Type="Superior" Count="3" Price="4000" />
</Hotel>
<Hotel Name="DEF" Location="LMN">
<Room Type="Single" Count="5" Price="2000" />
<Room Type="Superior" Count="3" Price="4000" />
</Hotel>
</HotelDatabase>
My Code for displaying the data in DataGridView looks like this:
var dataSet = new DataSet();
dataSet.ReadXml(Properties.Settings.Default.HotelDB);
dataGridViewHotelList.DataSource = dataSet.Tables[0];
When I run this code, only Name and Location is displayed. I want all the attributes in the Hotel element and its child element to be displayed in a datagridview.
You are loading XML data to grid correctly, but you should know when you bind DataGridView to a DataTable it shows columns of the data table not the columns of related tables.
You can not show a relation in a single DataGridView. To show child items of a hotel, you can use another DataGridView in the same form to show child items of hotel and bind the second grid to rooms of a hotel:
var ds = new DataSet();
ds.ReadXml("path to xml file");
dataGridView1.DataSource = ds.Tables["Hotel"]; //Tables[0]
dataGridView2.DataSource = ds.Tables["Hotel"]; //Tables[0]
dataGridView2.DataMember = "Hotel_Room"; //ds.Tables[0].ChildRelations[0].RelationName;
This way you will have a master-detail relation between your data grids. By click on each hotel row, you will see its rooms.
You also have some other options, for example:
You can create a DataGridViewButtonColumn to the grid that opens a form which shows a grid containing rooms of selected hotel.
You can use a DataGrid control which can show a link to child items of a row. To do so, it's enough to set hotels as data source of data grid control: this.dataGrid1.DataSource = ds.Tables["Hotel"];
You can convert the XML to a datatable and the just plug it in to your gridview with DataTable.ReadXML(), here is example code from MSDN:
private static void DemonstrateReadWriteXMLDocumentWithString()
{
DataTable table = CreateTestTable("XmlDemo");
PrintValues(table, "Original table");
string fileName = "C:\\TestData.xml";
table.WriteXml(fileName, XmlWriteMode.WriteSchema);
DataTable newTable = new DataTable();
newTable.ReadXml(fileName);
// Print out values in the table.
PrintValues(newTable, "New table");
}
private static DataTable CreateTestTable(string tableName)
{
// Create a test DataTable with two columns and a few rows.
DataTable table = new DataTable(tableName);
DataColumn column = new DataColumn("id", typeof(System.Int32));
column.AutoIncrement = true;
table.Columns.Add(column);
column = new DataColumn("item", typeof(System.String));
table.Columns.Add(column);
// Add ten rows.
DataRow row;
for (int i = 0; i <= 9; i++)
{
row = table.NewRow();
row["item"] = "item " + i;
table.Rows.Add(row);
}
table.AcceptChanges();
return table;
}
private static void PrintValues(DataTable table, string label)
{
Console.WriteLine(label);
foreach (DataRow row in table.Rows)
{
foreach (DataColumn column in table.Columns)
{
Console.Write("\t{0}", row[column]);
}
Console.WriteLine();
}
}
And if you need to know how to bind your datagridview to a datatable, here, is a link on how to do that.
How can I show my controls even if my table columns are null using gridview? All I know is ShowHeaderWhenEmpty="true"
If datasource of gridview is null, you can create a temporery datatable and assign it as a datasuource of gridview.
if (GridView1.DataSource == null)
{
DataTable dt = new DataTable();
dt.Columns.Add("Name");
DataRow dr = dt.NewRow();
dr[0] = "";
dt.Rows.Add(dr);
GridView1.DataSource=dt;
GridView1.DataBind();
}
If your data is NULL then there is no data to show. In order to show the controls, you need to have data.
I'd try to create a dummy row if the db returns null.
if(db.rows.count < 1)
{
//add a row with dummy values
}
Hope this helps.
you can try this:
dataGridView1.Rows.Add(num_rows);
i am working with Desktop Application and i am trying to create a datatable from a datagridview. but i only want to add those rows when checkbox is selected or checked. currently i created a datatable from a whole datagridview like this.
DataTable tbl = (DataTable)dataGridView1.DataSource;
I have added a checkbox coloumn inside datagridview.. so please guide me how to add selected rows to a new datatable
Thanks.. Here is the new code Update
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
if (Convert.ToBoolean(dataGridView1.Rows[i].Cells[0].Value) == true)
{
DataRow dr0 = tbl.NewRow();
dr0["ID"] = dataGridView1.Rows[i].Cells["ID"].Value;
dr0["BikeCC"] = dataGridView1.Rows[i].Cells["BikeCC"].Value.ToString();
dr0["ChassisModel"] = dataGridView1.Rows[i].Cells["ChassisModel"].Value.ToString();
dr0["BikeCC"] = dataGridView1.Rows[i].Cells["BikeCC"].Value.ToString();
dr0["ChassisModel"] = dataGridView1.Rows[i].Cells["Chassismodel"].Value.ToString();
tbl.Rows.Add(dr0);
}
}
objMdl.RecordTable = tbl;
This is the way i could find to add selected rows into a new datatable... it is lenghty but i am still facing little issues. which i will post in a bit for your look.
Suppose your checkbox column is named yourCheckBoxColumn:
DataTable tbl = ((DataTable)dataGridView1.DataSource).Clone();//Clone structure first
var rows = dataGridView1.Rows.OfType<DataGridViewRow>()
.Where(r=>Convert.ToBoolean(r.Cells["yourCheckBoxColumn"].Value))
.Select(r=>((DataRowView)r.DataBoundItem).Row);
foreach(var row in rows)
tbl.ImportRow(row);