How to add control cells programmatically in a gridview C# .net? - c#

Every row have to has a dropdownlist and a submit button.
So I made a List for data.
I added them like this.
enter image description here
//In my code behind
List<data> listdatainfo = new List<data>();
protected void Button1_Click(object sender, EventArgs e){
SqlDataReader detaillist = comm2.ExecuteReader();
while (detaillist.Read())
{
rmainfo tempinfo = new rmainfo();
tempinfo.itemdetail= detaillist["itemdetail"].ToString();
tempinfo.creditmemo= detaillist["creditmemo"].ToString();
tempinfo.submit= "0";//it will be filled 0 or 1
listdatainfo .Add(tempinfo);
}
loadDataTable();}
//it was referenced from here http://asp.net-informations.com/gridview/without-database.htm
private void loadDataTable()
{
DataSet ds = new DataSet();
DataTable dt;
dt = new DataTable();
DataColumn itemdetail;
DataColumn creditmemo ;
CommandField submit = new CommandField();
submit.EditText = "Edit";
submit.ShowEditButton = true;
itemdetail= new DataColumn("itemdetail",Type.GetType("System.String"));
creditmemo = new DataColumn("creditmemo ",Type.GetType("System.String"));
submit = new CommandField();
dt.Columns.Add(itemDetail);
dt.Columns.Add(creditMemo);
dt.Columns.Add("submit"); //it's for submit button
foreach (data tempinfo in listdatainfo )
{
DataRow dr;
dr = dt.NewRow();
dr["Item Detail"] = tempinfo.itemDetail;
dr["Credit Memo"] = tempinfo.creditMemo;
dr["submit"] = submit;
dt.Rows.Add(dr);
}
ds.Tables.Add(dt);
GridView2.DataSource = ds.Tables[0];
GridView2.DataBind();
}}
public class data
{
public string itemDetail { get; set; }
public string creditMemo { get; set; }
public string submit { get; set; }
}
As i expected, this line occured an error this line.
dr["submit"] = submit;
How can i add a button each row? or any component?
It was easier in classic asp.....
Please help.

You have to add the buttons in the GridView model instead of the datatable that is feeding it.

Related

Add a new row in bounded dataGridView on button click

I have a datagridview and filling it using datatable as datasource .
I want to add a new row on button click , using method to first unbound it and then add new row in it . As the following :
dataGridView1.AutoGenerateColumns = false;
dataGridView1.DataSource= null;
dataGridView1.Rows.Add();
But instead of adding new row below the existing row , it clears the existing data in row. I think present that row as new row.
how can I add the new row below the existing row and keep the data in other rows safe .
NOTE -- columns of datagridview view are custom columns .
If you need to keep safe the existing rows, you must retain the datasource. Can try the following please?
public partial class Form1 : Form
{
DataTable dt;
public Form1()
{
InitializeComponent();
InitDataGridView();
}
private void InitDataGridView()
{
dt = new DataTable();
dt.Columns.Add("A"); dt.Columns.Add("B");
var dr = dt.NewRow();
dr["A"] = "A-init"; dr["B"] = "B-init";
dt.Rows.Add(dr);
dataGridView1.DataSource = dt;
}
private void button2_Click(object sender, EventArgs e)
{
var dr = dt.NewRow();
var counter = dt.Rows.Count;
dr["A"] = "A-" + counter; dr["B"] = "B-" + counter;
dt.Rows.Add(dr);
}
}

Adding multiple row from one datagridview to datagridview c# windows form

i have this piece of code through which i am inserting one grid view data to another
private void btnADD_Click(object sender, EventArgs e)
{
DataTable dt = new DataTable();
DataRow dr;
dt.Columns.Add("LOB");
dt.Columns.Add("Quantity");
dt.Columns.Add("Name");
dt.Columns.Add("Packing");
dt.Columns.Add("Price");
dt.Columns.Add("Code");
dr = dt.NewRow();
dr["LOB"] = txtLOB.Text;
dr["Quantity"] = txtQuantity.Text;
dr["Name"] = txtName.Text;
dr["Packing"] = txtPacking.Text;
dr["Price"] = txtPrice.Text;
dr["Code"] = txtBachNo.Text;
dt.Rows.Add(dr);
gridviewDtaInserted.DataSource = dt;
}
i am able to insert one row at a time but i want to insert many rows one after another.
You should declare DataTable as globally because every time on Button click it has instantiated with new key word.
Try this:
DataTable dt = new DataTable();
dt.Columns.Add("LOB");
dt.Columns.Add("Quantity");
dt.Columns.Add("Name");
dt.Columns.Add("Packing");
dt.Columns.Add("Price");
dt.Columns.Add("Code");
private void btnADD_Click(object sender, EventArgs e)
{
DataRow dr;
for(int i = 0; i <= RowsCountThatYouWantToIsert; i++)
{
dr = dt.NewRow();
dr["LOB"] = txtLOB.Text;
dr["Quantity"] = txtQuantity.Text;
dr["Name"] = txtName.Text;
dr["Packing"] = txtPacking.Text;
dr["Price"] = txtPrice.Text;
dr["Code"] = txtBachNo.Text;
dt.Rows.Add(dr);
}
gridviewDtaInserted.DataSource = dt;
}
IF you are reading from one view to another you can use a looping structure to go through each iteration. I would suggest a for loop so that you can use the current numerical iteration as part of the instruction. if you want to ammend the first view to the second then you may want to use
DataTable dt = new DataTable();
DataTable dt2 = new DataTable();
dt=(DataTable)DataGridViewer1.datasource;
dt2=(DataTable)DataGridViewer2.datasource;
dt2.Merge(dt);
DataGridViewer2.datasource=dt2;
The DataSource property, from a DataGridView accepts a collection of objects.
So, I would suggest you to add how many rows you want to that public collection of objects, and at the end to update the DataSource
gridviewDtaInserted.DataSource = myCollection;
See here more info: MSDN
Also, here is a nice question may help you.
As a skeleton you can design in this way:
public class TestFunctional {
public TestFunctional(){
DataItems = new List<DataItem>();
}
public List<DataItem> DataItems { get; set; }
private void AddOneItem(){
var newItem = new DataItem {
LOB = "a",
Quantity = 1,
Name = "A",
Packing = true,
Code = "a1"
};
DataItems.Add(newItem);
RefreshGrid();
}
private void AddMultipleItems(){
var newItem1 = new DataItem {
LOB = "a",
Quantity = 1,
Name = "A",
Packing = true,
Code = "a1"
};
var newItem2 = new DataItem {
LOB = "b",
Quantity = 2,
Name = "B",
Packing = false,
Code = "b2"
};
DataItems.Add(newItem1);
DataItems.Add(newItem2);
/*or use DataItems.AddRange( ... ) */
RefreshGrid();
}
private void RefreshGrid()
{
gridviewDtaInserted.Rows.Clear();
gridviewDtaInserted.Refresh();
gridviewDtaInserted.DataSource = DataItems;
}
}
public class DataItem{
public string LOB { get; set; }
public double Quantity { get; set; }
public string Name { get; set; }
public bool Packing { get; set; }
public decimal Price { get; set; }
public string Code { get; set; }
}
I hope it will help you. Otherwise, ask :)
Edit:
Also, try to use the BindingList instead of List, I am not sure, but maybe it will automatically update the DataSource of the grid as soon an item is inserted in the collection.
BindingList<DataItem> DataItems

How to add new row on click winforms

I have a winforms application that I am developing, I have hit a dead end. What I am trying to do is on each "click", add a new row to my DataTable with the values input in the form. This Datatable is the DataSource for my DataGridView. Can someone point me in the right direction on how this can be achieved.
Articles I looked at:
How to add new row to datatable gridview
My code:
private void btnAdd_Click(object sender, EventArgs e)
{
//inserting into order table
DataTable dt = new DataTable();
string articleId = cmbArticle.Text;
string productDescription = txtDesc.Text;
string type = txtType.Text;
string materialType = txtMaterial.Text;
string size = cmbSizes.Text;
string quantity = txtQuantity.Text;
try
{
dt.Columns.Add("Article");
dt.Columns.Add("Description");
dt.Columns.Add("Type");
dt.Columns.Add("Material");
dt.Columns.Add("Size");
dt.Columns.Add("Quantity");
dt.Columns.Add("DateTime");
DataRow dr = dt.NewRow();
//addrows
dr["Article"] = articleId;
dr["Description"] = productDescription;
dr["type"] = type;
dr["Material"] = materialType;
dr["Size"] = size;
dr["Quantity"] = quantity;
dt.Rows.Add(dr);
dgvView.DataSource = dt;
}
catch (Exception ex)
{
}
}
On each click you are creating a new DataTable which would be with just one row, You need to create DataTable once and then just keep adding rows to in the click. Define your DataTable at class level and then in your event just add a new row to it.
DataTable dt = new DataTable(); //at class level
private void Form1_Load(object sender, EventArgs e)
{
CreateDataTableColumns();
//.... your code
}
Then have a method to create table structure, call that method once from your From_Load event.
private void CreateDataTableColumns()
{
dt.Columns.Add("Article");
dt.Columns.Add("Description");
dt.Columns.Add("Type");
dt.Columns.Add("Material");
dt.Columns.Add("Size");
dt.Columns.Add("Quantity");
dt.Columns.Add("DateTime");
}
Later add rows to your class level DataTable in Add event.
private void btnAdd_Click(object sender, EventArgs e)
{
string articleId = cmbArticle.Text;
string productDescription = txtDesc.Text;
string type = txtType.Text;
string materialType = txtMaterial.Text;
string size = cmbSizes.Text;
string quantity = txtQuantity.Text;
try
{
DataRow dr = dt.NewRow();
//addrows
dr["Article"] = articleId;
dr["Description"] = productDescription;
dr["type"] = type;
dr["Material"] = materialType;
dr["Size"] = size;
dr["Quantity"] = quantity;
dt.Rows.Add(dr);
dgvView.DataSource = dt;
}
catch (Exception ex)
{
}
}
(I believe you are doing something with the exception object in your catch block, like logging, showing message to user etc)

listbox error: Items collection cannot be modified when the DataSource property is set

I have 2 listboxes in a window form, one on left and one on right. The
1st listbox have some items while the 2nd listbox is empty. Also there
are 2 buttons between the 2 listboxes which used to move item from/to
the 1st and 2nd listbox
My problem here is that after I bind the data to the 1st listbox (from
a database, using DisplayMember and ValueMember) , and I try to move 1
of the item from this 1st listbox to the 2nd listbox and I want that
the selected item is also removed from the 1st listbox by:
private void btnMoveRight_Click(object sender, EventArgs e)
{
ADD();
}
private void ADD()
{
int c = listJobBox.Items.Count - 1;
` for(int i= c; i>=0; i--)
{
if(listJobBox.GetSelected(i))
{
lstAssignedJobs.Items.Add(listJobBox.Items[i]);
listJobBox.Items.Remove(listJobBox.SelectedItem); ---error line
But the selected item is not removed from the 1st listbox.
it displays error message "Items collection cannot be modified
when the DataSource property is set."
can any one give me the solution to my problem.
Add a boolean column to your DataTable object, something like IsSelected.
Then instead of binding your listbox1 directly to the table, bind it to a BindingSource. Add 2 bindingsources to your form using the designer. And place this code in your code behind file.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.InitializeDataObjects();
}
private void InitializeDataObjects()
{
this.InitData();
this.InitBindingSources();
}
private void InitData()
{
ds = new DataSet();
var dt = new DataTable("Table1");
dt.Columns.Add("Name", typeof(string));
ds.Tables.Add(dt);
}
private void InitBindingSources()
{
bindingSource1 = new BindingSource();
bindingSource2 = new BindingSource();
bindingSource1.DataSource = ds;
bindingSource1.DataMember = "Table1";
bindingSource2.DataSource = ds;
bindingSource2.DataMember = "Table1";
listBox1.DataSource = bindingSource1;
listBox1.DisplayMember = "Name";
listBox2.DataSource = bindingSource2;
listBox2.DisplayMember = "Name";
}
}
Then when you load your data, do the following:
private void btnLoadAndBind_Click(object sender, EventArgs e)
{
this.FetchData(this.ds.Tables["Table1"]);
this.AddSelectedColumn(this.ds.Tables["Table1"]);
this.bindingSource1.Filter = "IsSelected = false";
this.bindingSource2.Filter = "IsSelected = true";
}
private void FetchData(DataTable dataTable)
{
string CS = "your connectionstring";
using (SqlConnection con = new SqlConnection(CS))
{
try
{
SqlDataAdapter da = new SqlDataAdapter();
con.Open();
var sqlcmd = new SqlCommand("SELECT Name FROM sometable", con);
sqlcmd.CommandType = CommandType.Text;
da.SelectCommand = sqlcmd;
da.Fill(dataTable);
}
catch (Exception ex)
{
MessageBox.Show("exception raised");
throw ex;
}
}
}
private void AddSelectedColumn(DataTable suppliersDataTable)
{
var dc = new DataColumn("IsSelected", typeof(bool));
suppliersDataTable.Columns.Add(dc);
foreach (DataRow dr in suppliersDataTable.Rows)
{
dr["IsSelected"] = false;
}
}
Now your listboxes are both connected to the same datatable and filtered based on the IsSelected property / column. Just set this column to true or false and it will flip from box to box. Your eventhandler of a button could look like this:
public void button_Click(object sender, EventArgs e)
{
if (this.bindingSource1.Current!= null)
{
var dr = ((DataRowView)this.bindingSource1.Current).Row;
dr["IsSelected"] = true;
}
}
This works!
Things will be become much simpeler if you use a typed dataset. Most of the bindings then can be done in the designer and your code behind will shrink to 20 lines of code....
Lets say listbox1 is bound to datatable1 (it could be any other collection type) and listbox2 is bound to datatable2. When you click on move button, remove the selected item from the collection i.e datatable1 and add that item to other collection i.e. datatable2 and re-bind the listbox1 and lisbox2.
Here is a rough working example:
public partial class Form1 : Form
{
private DataTable _dataSource1;
private DataTable _dataSource2;
public Form1()
{
InitializeComponent();
_dataSource1 = GetData1();
_dataSource2 = GetData2();
Initialize();
}
private void btnMove_Click(object sender, EventArgs e)
{
MoveItem();
}
void Initialize()
{
listBox1.DataSource = _dataSource1;
listBox1.DisplayMember = "Fruits";
listBox1.ValueMember = "Fruits";
listBox2.DataSource = _dataSource2;
listBox2.DisplayMember = "Fruits";
listBox2.ValueMember = "Fruits";
}
DataTable GetData1()
{
var dt = new DataTable();
dt.Columns.Add("Fruits");
dt.Rows.Add(new object[] {"Apple"});
dt.Rows.Add(new object[] { "Orange" });
dt.Rows.Add(new object[] { "Grapes" });
return dt;
}
DataTable GetData2()
{
var dt = new DataTable();
dt.Columns.Add("Fruits");
return dt;
}
void MoveItem()
{
var index = listBox1.SelectedIndex;
var dataRowToRemove = _dataSource1.Rows[index];
var listItem = dataRowToRemove[0] as string;
_dataSource1.Rows.Remove(dataRowToRemove);
var dataRowToAdd = _dataSource2.NewRow();
dataRowToAdd[0] = listItem;
_dataSource2.Rows.Add(dataRowToAdd);
Initialize();
}
}

multicolumn combo box in asp.net

I have a Database table with two fields MainAccount and MainDescription table have following data MainAccount 10 MainDescription Capital,MainAccount 20 MainDescription Account Receiable,MainAccount 30 MainDescription Account Payable
I have a asp.net page with DropDownList and a text box. I want to get all data in DropDownList here is my code
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
using (SqlDataAdapter adapter = new SqlDataAdapter("select distinct MainAccount,MainDescription from chart", db.con))
{
DataTable datatable = new DataTable();
adapter.Fill(datatable);
List<ListItem> list = new List<ListItem>();
foreach (DataRow dr in datatable.Rows)
{
string descr = string.Format("{0} | {1}", dr[0].ToString(), dr[1].ToString());
list.Add(new ListItem(descr));
}
list = list.OrderBy(a => a.Text).ToList();
DropDownList1.DataSource = list;
DropDownList1.DataBind();
}
}
}
this code is working fine to display all MainAccount and Main Description in DropDownList.
This is what I have now:
And this is the result I'm looking for:
To get the second picture result , I have tried this with example , see the two images below.
Add a property class
public class Columns
{
// obviously you find meaningful names of the 2 properties
public string MainAccount { get; set; }
public string MainDescription { get; set; }
public string Concatenate {get ; set ;}
}
then
if (!IsPostBack)
{
using (SqlDataAdapter adapter = new SqlDataAdapter("select distinct MainAccount,MainDescription from chart", db.con))
{
DataTable datatable = new DataTable();
adapter.Fill(datatable);
List<Columns> list = new List<Columns>();
foreach (DataRow dr in datatable.Rows)
{
list.Add(new Columns { MainAccount =dr[0].ToString() ,
MAinDescription = dr[1].ToString(),
Concatenate = string.Format("{0} | {1}",dr[0].ToString(), dr[1].ToString())});
}
list = list.OrderBy(a => a.MainAccount).ToList();
DropDownList1.DataSource = list;
DropDownList1.DataValueField = "MainDescription";
DropDownList1.DataTextField = "Concatenate";
DropDownList1.DataBind();
}
}
Then use the on SelectedIndexChanged property of the dropdown and set your text box value.
Example i just run this below.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace DropDown
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
List<Columns> list = new List<Columns>();
for (int i = 0; i < 10; i++)
{
list.Add(new Columns
{
MainAccount = "1" + i,
MainDescription = "Main Account Desc" + i,
Concatenate = string.Format("{0} | {1}", "1" + i, "Main Account Desc" + i)
});
}
DropDownList1.DataSource = list;
DropDownList1.DataValueField = "MainDescription";
DropDownList1.DataTextField = "Concatenate";
DropDownList1.DataBind();
}
}
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
TextBox1.Text = DropDownList1.SelectedValue.ToString();
}
}
}
Below is the resulting image.
Second image
Also i noticed you changed the combobox text to the mainAccount after selection. Just to let you know you cant just Reset the combobox text to an item that does not exist in the list . However i suggest you use a public array or struct, populate your array onload, then later populate your list from the array. After selection, you can then refresh your dropdown from the array/list as well and reset the datatextfield to your mainAccount column. Then set the selected to a row where the MainDescription column = Textbox text. I hope this helps. Let us know if you need more help achieving this ?
You can bind MainAccount (i.e. 10,20,30,40) to dropdownlist.
And on selected index change you can display MainDescription.
like this-
DataRow[] drDesc= dt.Select(filter expression)
i think that the best solution may be by creating a class that contains a definition of two variables and set the datasource of the DropDownlist by a list of this class
public class DropDownDataSource
{
public string Text { set; get; }
public string Value { set; get; }
}
then we will modify your code to work with the new way
List<DropDownDataSource> list = new List<DropDownDataSource>();
foreach (DataRow dr in datatable.Rows)
{
var item = new DropDownDataSource
{
Text = dr[0].ToString() + " | " + dr[1].ToString(),
Value = dr[1].ToString()
};
list.Add(item);
}
DropDownList1.DataSource = list;
DropDownList1.DataTextField = "Text";
DropDownList1.DataValueField = "Value";
DropDownList1.DataBind();
and in the SelectedIndexchanged Event of the DropDownList1 we will write this code to bring the value of selected item and bint it in the textbox
protected void DropDownList1_OnSelectedIndexChanged(object sender, EventArgs e)
{
TextBoxValue.Text = DropDownList1.SelectedValue;
}

Categories

Resources