I created a CheckBoxField and added it to my GridView, I would like to know how I can add a checkbox to each row of the new column:
CheckBoxField field = new CheckBoxField();
field.HeaderText = "Export ?";
gv.Columns.Add(field);
I've done similar with a DataGridView (WinForms). This code should help you get a good bit on the way:
// add new checkbox to source
var checkBoxColumn = new DataGridViewCheckBoxColumn();
checkBoxColumn.HeaderText = "Move";
checkBoxColumn.Name = "chkMove";
// add new binding
dgCheckBoxes.Columns.Insert(0, checkBoxColumn);
// set values
foreach (DataGridViewRow row in dgCheckBoxes.Rows)
{
if (true)
{
row.Cells["chkMove"].Value = true;
}
else
{
row.Cells["chkMove"].Value = false;
}
}
For a WebForms solution, you should be able to use this Demo from Microsoft: Adding a GridView Column of Checkboxes
Related
I am currently working on a system. I have a datagridview with a contextmenu and an edit and delete button on it. I want to pass the value of the selected rows to a textbox when I click the edit on contextmenu.
I have successfully passed the value to the textbox but the only values that show are from the last inputted data to whatever row I click. I don't know how to get the id, can someone please help me fix my problem? :(
Here is my code:
private void BtnEdit_Click(object sender, EventArgs e)
{
frmAddEditStudent frm = new frmAddEditStudent(this);
cn.Open();
cm = new SqlCommand("SELECT s.studentID, s.studentNo, s.Lname, s.Fname, s.MI, s.gender, s.yearLevel, s.section, s.studImage, g.name, g.contactNo, g.address FROM Student s INNER JOIN Guardian g ON g.studentNo = s.studentNo WHERE g.studentNo = s.studentNo AND s.isActive = 'true' AND s.studentID = studentID", cn);
cm.Parameters.AddWithValue("studentID", lblID.Text);
for (int i = 0; i < guna2DataGridView1.Rows.Count; i += 1)
{
frm.btnSave.Enabled = false;
frm.lblTitle.Text = "Edit Student Details";
frm.lblID.Text = guna2DataGridView1.Rows[i].Cells[1].Value.ToString();
frm.txtStudentNo.Text = guna2DataGridView1.Rows[i].Cells[2].Value.ToString();
frm.txtLname.Text = guna2DataGridView1.Rows[i].Cells[3].Value.ToString();
frm.txtFname.Text = guna2DataGridView1.Rows[i].Cells[4].Value.ToString();
frm.txtMI.Text = guna2DataGridView1.Rows[i].Cells[5].Value.ToString();
frm.cboGradeLevel.Text = guna2DataGridView1.Rows[i].Cells[7].Value.ToString();
frm.cboSection.Text = guna2DataGridView1.Rows[i].Cells[8].Value.ToString();
frm.txtGuardianName.Text = guna2DataGridView1.Rows[i].Cells[9].Value.ToString();
frm.txtContactNo.Text = guna2DataGridView1.Rows[i].Cells[10].Value.ToString();
frm.txtAddress.Text = guna2DataGridView1.Rows[i].Cells[11].Value.ToString();
//Load Image
byte[] bytes = (byte[])guna2DataGridView1.Rows[i].Cells[12].Value;
MemoryStream ms = new MemoryStream(bytes);
frm.studImage.Image = Image.FromStream(ms);
//Retrieve gender value to radio button
if (guna2DataGridView1.Rows[i].Cells[6].Value.ToString() == "Male")
{
frm.rbMale.Checked = true;
}
else
{
frm.rbFemale.Checked = true;
}
}
cn.Close();
frm.ShowDialog();
It does not show up the data in the row that I selected, instead it only shows the last row in my database table.
You can get the current row or the selected rows from a datagridview in the following way (I think ID is cell with Index 1):
Console.WriteLine(guna2DataGridView1.CurrentRow.Cells[1].Value.ToString());
foreach (DataGridViewRow loRow in guna2DataGridView1.CurrentRow.SelectedRows)
{
Console.WriteLine(loRow.Cells[1].Value.ToString());
}
But you overwrite the form values in your loop every time.
It seems that your form can only display one row and not a collection.
And what about the command cm??
Not able to insert new rows at particular position in DataGridView by using DataGridView.Rows.Insert or DataGridView.Rows.InsertCopy methods.
ErrorMessage: Rows cannot be programmatically added to the DataGridView's rows collection when the control is data-bound.
DataGridViewRow dgwr = new DataGridViewRow();
dgwr.CreateCells(myDataGridView);
myDataGridView.AllowUserToAddRows = true;
myDataGridView.AllowUserToDeleteRows = true;
myDataGridView.Rows.Insert(5, dgwr);
OR
myDataGridView.AllowUserToAddRows = true;
myDataGridView.AllowUserToDeleteRows = true;
myDataGridView.Rows.InsertCopy(5, 2);
enter image description here
I'm facing a very common issue and I've tried almost every solution but none of them solved my problem. I've created a Grid View and I want it to have dynamic columns. Four columns among them must have some controls(textbox,label and checkbox) so I've created it as Template Fields(below code)
TemplateField tf4 = new TemplateField();
tf4.HeaderText = "Sr.No";
CustomerBillingGrid.Columns.Add(tf4);
TemplateField tf1 = new TemplateField();
tf1.HeaderText = "Select";
CustomerBillingGrid.Columns.Add(tf1);
TemplateField tf2 = new TemplateField();
tf2.HeaderText = "Misc";
CustomerBillingGrid.Columns.Add(tf2);
TemplateField tf3 = new TemplateField();
tf3.HeaderText = "Total";
CustomerBillingGrid.Columns.Add(tf3);
Then I've created Bound fields that displays database query result (below code)
if (ds.Tables[0].Rows.Count > 0)
{
int num = 2;
foreach (DataColumn col in ds.Tables[0].Columns)
{
BoundField bf = new BoundField();
bf.HeaderText = col.ColumnName;
bf.DataField = col.ColumnName;
CustomerBillingGrid.Columns.Insert(num, bf);
num++;
}
CustomerBillingGrid.DataSource = ds;
CustomerBillingGrid.DataBind();
}
After than I've Dynamically generated controls for GridView.
protected void GenrateDynamicControls()
{
Label lblSNo = new Label();
lblSNo.ID = "lblSNo";
lblSNo.Text = "1";
Page.Form.Controls.Add(lblSNo);
CheckBox chkSelect = new CheckBox();
chkSelect.ID = "chkSelect";
chkSelect.AutoPostBack = true;
Page.Form.Controls.Add(chkSelect);
TextBox txtMisc = new TextBox();
txtMisc.ID = "txtMisc";
Page.Form.Controls.Add(txtMisc);
TextBox txtTotal = new TextBox();
txtTotal.ID = "txtTotal";
Page.Form.Controls.Add(txtTotal);
}
I've called this method on every Postback
if (!IsPostBack)
{
if (!Convert.ToBoolean(ViewState["DynamicControlsGenrated"]))
{
GenrateDynamicControls();
}
}
The problem I'm facing is that all these dynamic controls gets lost every postback and the second problem is that how to add those dynamically generated controls inside GridView and keep it persistence.
Thanks,
In the case of dynamic control creation inside the grid view, you need to recreate the controls each time on postback and make sure to disable view state mode in grid view.
ViewStateMode="Disabled"
I have this form that lets user choose a (Code - Product) item from a comboxbox. input quantity and price and Add it to a list.
Loading the inventories to the form
private List<Inventory> inventories = new Inventory().read_inventory();
Setting the ComboBox with values
private void set_drop_down_inventory()
{
cb_inventory.DisplayMember = "name";
cb_inventory.DataSource = inventories;
cb_inventory.ResetText();
cb_inventory.SelectedIndex = -1;
}
When a user selects a product, it will create a new instance.
private void cb_inventory_SelectionChangeCommitted(object sender, EventArgs e)
{
var selected_inventory = (cb_inventory.SelectedItem as Inventory);
sales_order_detail = new Sales_Order_Detail(selected_inventory, 0);
tx_description.Text = selected_inventory.description;
tx_price.Text = selected_inventory.get_price_str();
}
Once the user adds the item it triggers this code.
private void btn_add_item_Click(object sender, EventArgs e)
{
// Set the inputted data into the instance before adding to the list
sales_order_detail.description = tx_description.Text.ToString();
sales_order_detail.quantity = tx_quantity.Value;
sales_order_detail.price = Convert.ToDecimal(tx_price.Text);
// Adding the instances to a List
sales_order.sales_order_details.Add(sales_order_detail);
// Sets the Datagrid to provide the data+
initialize_datagrid(sales_order_detail);
}
This is how i initialize the datagrid because i need to manually display the columns -- this is where i am not sure what to do - i believe i do not need to manually add a new row every time a user adds an item because this datagrid is bounded to the List<>, so whatever instance is added to the List<> it will be added to the grid when i trigger the dgv.Refresh()
private void initialize_datagrid(Sales_Order_Detail sales_order_detail)
{
dgv_sales_order_details.Columns.Clear();
dgv_sales_order_details.DataSource = null;
dgv_sales_order_details.Refresh();
dgv_sales_order_details.AutoGenerateColumns = false;
// Set the datasource to the list where the item is added
dgv_sales_order_details.DataSource = sales_order.sales_order_details;
DataGridViewComboBoxColumn product_code_col = new DataGridViewComboBoxColumn();
DataGridViewColumn description_col = new DataGridViewColumn();
DataGridViewColumn quantity_col = new DataGridViewColumn();
DataGridViewColumn price_col = new DataGridViewColumn();
DataGridViewColumn account_col = new DataGridViewColumn();
DataGridViewComboBoxCell product_cell = new DataGridViewComboBoxCell();
DataGridViewTextBoxCell description_cell = new DataGridViewTextBoxCell();
DataGridViewTextBoxCell amount_cell = new DataGridViewTextBoxCell();
product_cell.DisplayMember = "name";
// They have the same Datasource as the combobox above.
product_cell.DataSource = inventories;
product_code_col.CellTemplate = product_cell;
product_code_col.DataPropertyName = nameof(sales_order_detail.inventory.name); //This binds the value to your column
product_code_col.HeaderText = "Code";
product_code_col.Name = "name";
description_col.CellTemplate = description_cell;
description_col.DataPropertyName = nameof(sales_order_detail.description);
description_col.HeaderText = "Description";
description_col.Name = "description";
quantity_col.CellTemplate = amount_cell;
quantity_col.DataPropertyName = nameof(sales_order_detail.quantity);
quantity_col.HeaderText = "Quantity";
quantity_col.Name = "quantity";
quantity_col.DefaultCellStyle.Format = "0.00";
quantity_col.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
price_col.CellTemplate = amount_cell;
price_col.DataPropertyName = nameof(sales_order_detail.price);
price_col.HeaderText = "Price";
price_col.Name = "price";
price_col.DefaultCellStyle.Format = "0.00";
price_col.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
dgv_sales_order_details.Columns.Add(product_code_col);
dgv_sales_order_details.Columns.Add(description_col);
dgv_sales_order_details.Columns.Add(quantity_col);
dgv_sales_order_details.Columns.Add(price_col);
dgv_sales_order_details.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
}
This is the result when the item is added but as you can see the combobox column has not displayed value, it only shows the value when i click the combobox column. and when i change the value in the combobox above the list, the value in the combobox column also changes. it seems that they are binded.
My Goal is to be able add a row to the datagrid where the comboboxcolumn displays what i selected and to fix to combobox duplicated selection.
Please comment if it needs more clarification so i could correct it. Thanks!
DataGridViewComboBoxColumn c = new DataGridViewComboBoxColumn();
c.Name = "ComboColumn";
c.DataSource = dataTable;
c.ValueMember = "ID";
c.DisplayMember = "Item";
dataGridView1.Columns.Add(c);
To select a particular value you set the Value property of a given cell.
dataGridView1.Rows[rowIndexYouWant].Cells["ComboColumn"].Value = 1;
Note that the type here is important! IF you say you get a System.FormatException. This can be caused by setting the wrong type to the value.
When you set the value to 1 you are assigning an int - if for some reason you have strings in the ID column you will get the System.FormatException exception you are seeing.
If the types differ you need to either update the DataTable definition or set the value to a string:
dataGridView1.Rows[rowIndexYouWant].Cells["ComboColumn"].Value = "1";
for adding rows you might need
dataGridView1.Rows.Add();
int z=0;
for (int a = 0; a < dataGridView1.comlumncount; a++)
{
dataGridView1.Rows[z].Cells[a].Value = "yourvalue";
z++;
}
for your reference check this Link you might get your problem solved
I've managed to solve it, this is my solution. This is best solution i've come up so far. Please comment if you have any correction. so we could improve it. I hope this will help others too.
Created a DataGridView Handler so i could reuse it in the other forms and add more conditions for it be flexible.
namespace Project.Classes
{
public static class DGV_Handler
{
public static DataGridViewComboBoxColumn CreateInventoryComboBox()
{
DataGridViewComboBoxColumn combo = new DataGridViewComboBoxColumn();
// This lets the combo box display the data selected
// I set the datasource with new instance because if i use the Datasource used in the combobox in the item selection. the combobox in the grid and that combox will be binded. if i change one combobox the other one follows.
combo.DataSource = new Inventory().read_inventory();
combo.DataPropertyName = "inventory_id";
combo.DisplayMember = "name";
combo.ValueMember = "inventory_id";
combo.Name = "inventory_id";
combo.HeaderText = "Code";
combo.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft;
return combo;
}
public static DataGridViewComboBoxColumn CreateGLAccountComboBox()
{
DataGridViewComboBoxColumn combo = new DataGridViewComboBoxColumn();
combo.DataSource = new Account().read();
combo.DataPropertyName = "gl_account_sales";
combo.DisplayMember = "account_name";
combo.ValueMember = "account_id";
combo.Name = "account_id";
combo.HeaderText = "Account";
combo.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft;
return combo;
}
public static DataGridViewTextBoxColumn CreateTextBox(string dataproperty, string headertext, string name, bool is_numbers)
{
DataGridViewTextBoxColumn textbox = new DataGridViewTextBoxColumn();
textbox.DataPropertyName = dataproperty;
textbox.HeaderText = headertext;
textbox.Name = name;
if (is_numbers)
{
textbox.DefaultCellStyle.Format = "0.00";
textbox.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
}
return textbox;
}
}
}
When the form is loaded i initialize the datagrid like this.
private void initialize_datagrid()
{
dgv_sales_order_details.Columns.Clear();
dgv_sales_order_details.Refresh();
dgv_sales_order_details.AutoGenerateColumns = false;
dgv_sales_order_details.DataSource = bindingSource1;
dgv_sales_order_details.Columns.Add(DGV_Handler.CreateInventoryComboBox());
dgv_sales_order_details.Columns.Add(DGV_Handler.CreateTextBox("description","Description", "description", false));
dgv_sales_order_details.Columns.Add(DGV_Handler.CreateTextBox("quantity","Quantity","quantity", true));
dgv_sales_order_details.Columns.Add(DGV_Handler.CreateTextBox("price", "Price", "price", true));
dgv_sales_order_details.Columns.Add(DGV_Handler.CreateGLAccountComboBox());
dgv_sales_order_details.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
dgv_sales_order_details.RowHeadersVisible = false;
dgv_sales_order_details.EditMode = DataGridViewEditMode.EditOnEnter;
}
Code when adding a new row
private void btn_add_item_Click(object sender, EventArgs e)
{
if(validate_selection())
{
// Set the properties to be included in the DGV Column
var selected_row = (cb_inventory.SelectedValue as Inventory);
var selected_gl_account = (cb_gl_account.SelectedValue as Account);
string description = tx_description.Text;
decimal quantity = tx_quantity.Value;
decimal price = Convert.ToDecimal(tx_price.Text);
int gl_account_id = selected_gl_account.account_id;
// When something new is added to the bindingsource, the DGV will be refresh
bindingSource1.Add(new Sales_Order_Detail(selected_row, description, quantity, price, 0, gl_account_id));
clear_item_selection();
}
}
Result
i have a gridview that creates a new row with a new gridview in it
the method of creating the second gridview is :
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "PopExtendedGrid")
{
GridView _gridView = (GridView)sender;
int _rowIndex2 = int.Parse(e.CommandArgument.ToString());
GridView _ChildGrid = new GridView();
Control x = _gridView.Rows[_rowIndex2 + 1].Cells[1].Controls[1];
int Oid = int.Parse(((Label)x).Text);
_ChildGrid.DataSource = hs.GetExtendedGrid(Oid);
_ChildGrid.ID = "ChildGrid";
_ChildGrid.AutoGenerateColumns = false;
_ChildGrid.CssClass = "ChildGridS";
_ChildGrid.HeaderStyle.CssClass = "CreateHead";
BoundField one = new BoundField();
one.DataField = "ItemID";
one.HeaderText = "קוד מוצר";
_ChildGrid.Columns.Add(one);
BoundField two = new BoundField();
two.DataField = "ItemName";
two.HeaderText = "שם מוצר";
_ChildGrid.Columns.Add(two);
BoundField three = new BoundField();
three.DataField = "ItemSize";
three.HeaderText = "גודל מוצר";
_ChildGrid.Columns.Add(three);
GridViewRow tr = new GridViewRow(_rowIndex2 + 2 +10*this.GridView1.PageIndex,-1 , DataControlRowType.EmptyDataRow , DataControlRowState.Normal);
TableCell tc = new TableCell();
tc.ColumnSpan = _gridView.Columns.Count;
tc.Controls.Add(_ChildGrid);
tr.Cells.Add(tc);
if ((DataView)Session["dataSource"] != null)
{
DataView dv = (DataView)Session["dataSource"];
this.GridView1.DataSource = dv;
this.GridView1.DataBind();
}
else
{
if (Session["lvl"].ToString() == "high")
{
PopulateGridViewAdmin();
}
else
{
PopulateGridViewUser();
}
}
this.GridView1.Controls[0].Controls.AddAt(_rowIndex2 + 2, tr);
Session["ChildIndex"] = (_rowIndex2 + 2).ToString();
_ChildGrid.DataBind();
}
}
and i thought that when ever i will need to execute another command or something that is related to the gridview i will remove the row like this:
this.GridView1.Controls[0].Controls.RemoveAt(int.Parse(Session["ChildIndex"].ToString()));
and then repopulate the mastergridview but before i get the chance to do so this error keeps poping up:
Failed to load viewstate. The control tree into which viewstate is being loaded must match the control tree that was used to save viewstate during the previous request. For example, when adding controls dynamically, the controls added during a post-back must match the type and position of the controls added during the initial request.
im very frustrated by this and i will take any answer with great gratitude
thanks in advance
You may not need to track ViewState for that control since it's dynamic, so try setting EnableViewState to false and see if that helps.