Dynamic ComboBox Button Duplicating Data - c#

I am experiencing a problem where I have a button to populates a FlowLayoutPanel. All works well, and the combobox is generated. However, there is a small bug in the data populating of the combobox. I have a Binding source set up from my database and I link to the combobox in the following manner. The data is populated as expected, however, when I create another combobox using the same button, it always fills it with the same selection of data as the combobox above or below. The bizarre occurrence also happens when I have many more comboboxes. Here is my code. Any suggestions?
private void additionalpartbtn_Click(object sender, EventArgs e)
{
string fieldname = "addpart";
int fieldnamecount = 0;
ComboBox newcombobox = new ComboBox();
newcombobox.Name = fieldname + fieldnamecount;
newcombobox.DataSource = sqlpartBindingSource;
newcombobox.DisplayMember = "part";
additionalpartspnl.Controls.Add(newcombobox);
ComboBox newsidecombobox = new ComboBox();
newsidecombobox.Name = "side" + fieldname + fieldnamecount;
newsidecombobox.DataSource = sqlsideBindingSource;
newsidecombobox.DisplayMember = "side";
newsidecombobox.Size = new System.Drawing.Size(40, 21);
additionalpartspnl.Controls.Add(newsidecombobox);
fieldnamecount++;
}

Related

Combobox Selected Value going "null" on GridView_CellClick Event

I am using Winforms with C# and I am getting this result.
I have a gridview where some data are loaded and in cell click event, the data is displayed on text boxes and combobox, however, one of the combobox has gone crazy and not displaying the data on select. When debugging the code, the SelectedValue goes to null while on other combo boxes, the value changes.
Below are the codes used.
Gridview cell click event
if (e.RowIndex != -1)
{
DataGridViewRow grid = stockGridView.Rows[e.RowIndex];
txtStockId.Text = grid.Cells[0].Value.ToString();
txtBarcode.Text = grid.Cells[1].Value.ToString();
cmbQtyDescId.SelectedValue = grid.Cells[2].Value;
txtQtyDesc.Text = grid.Cells[3].Value.ToString();
txtBrandName.Text = grid.Cells[4].Value.ToString();
txtProductName.Text = grid.Cells[5].Value.ToString();
txtUnitPrice.Text = grid.Cells[6].Value.ToString();
txtRetailPrice.Text = grid.Cells[7].Value.ToString();
txtStockInHand.Text = grid.Cells[8].Value.ToString();
cmbCategory.SelectedValue = grid.Cells[9].Value;
cmbSupplier.SelectedValue = grid.Cells[10].Value;
chkIsTaxable.Checked = Convert.ToBoolean(grid.Cells[11].Value);
}
Populate Combobox. For the other combo boxes, I am using the same code
public static void FillCombo(List<QuantityDescriptionModel> quantityDescriptions, ComboBox control)
{
control.DataSource = quantityDescriptions;
control.ValueMember = "Id";
control.DisplayMember = "QtyDescription";
}
Screenshots attached
Data not loaded on cell_click
Data loaded without cell_click

Pushing values from DataView built on one Windows Form to another Windows Form

I have 2 windows forms. One form with datagridview and button, and the other form with labels. More or less like Master-Detail design. I have 2 related tables in database. I can fill the datagridview nicely with data from the main table. First I select data on datagridview, and I want to use the button to display the values on the labels located on another form.
Once data is loaded on datagridview; I use the following code for the methods to filter the underlying tables based on selection made from datagridview:
[form 2]
public DataView EnterpriseView()
{
foreach (DataGridViewRow row in Viewer.SelectedRows)
identifier = row.Cells["BusinessName"].Value.ToString();
var EnterpriseVw = new DataView(EnterpriseDT)
{
RowFilter = "BusinessName = '" + identifier + "'"
};
return EnterpriseVw;
}
After returning the view, I want to use the button to push the information to another form that has the labels. I'm not sure about how to get this working. I tried different codes of my own, and it doesn't work
My issue how to code the button_click event. And is there another event I need to call for this to work? How does the button know if I have selected something on the datagridview? How does the datagridview know I have clicked the button? I tied something like this for the button:
[form 2]
private void button1_Click(object sender, EventArgs e)
{
index = Viewer.SelectedRows[0].Index;
Viewer.Rows[index].Selected = true;
//EnterpriseView();
//DetailsView();
//this.Click += new EventHandler(Viewer_SelectionChanged);
if (Viewer.Rows[index].Selected == true)
{
var frm1 = new form1(); //form with labels
//foreach(DataGridViewRow row in Viewer.SelectedRows)
frm1.Publish(); //method that assigns data to labels
}
It doesn't work
I tried using somthing like this for the labels:
[form 1]
public void Publish()
{
var frm2 = new form2();
var vEnterprise = frm2.EnterpriseView();
Email.DataBindings.Add("Text", vEnterprise, "EmailAddress");
}
To Get values from Selected Row of the DataGridView you need to change some properties :
First You need to set SelectionMode to FullRowSelect.
Second You need to set MultiSelect to False.
You can do it through the properties tab.
Then we can use dataGridView1.SelectedRows it will return DataGridViewSelectedRowCollection a list of the selected rows, but since we disabled multiSelect there will always be just one so we can use [0].
Now in the Button_click event Handler
private void button1_Click(object sender, EventArgs e)
{
// To Get The Selected Row
var dr = dataGridView1.SelectedRows[0];
// The Cells Property is going to return DataGridViewCellCollection a list again
// Basically the columns so the first one will be the first column and so on
string item1 = dr.Cells[0].Value.ToString();
string item2 = dr.Cells[1].Value.ToString();
string item3 = dr.Cells[2].Value.ToString();
}
In the Form with the labels Define a second constructor.
Say we Have 3 Labels
We gonna define a second constructor that takes 3 Strings, Like this
public TheSecondForm(String S1, String S2,String S3)
{
label1.Text = S1;
label2.Text = S2;
label3.Text = S3;
}
Then The button Event Handle will become like this :
private void button1_Click(object sender, EventArgs e)
{
var dr = dataGridView1.SelectedRows[0];
string item1 = dr.Cells[0].Value.ToString();
string item2 = dr.Cells[1].Value.ToString();
string item3 = dr.Cells[2].Value.ToString();
// What was added
TheSecondForm frm2 = new TheSecondForm(item1, item2, item3);
frm2.Show();
}
By Now the labels will be populated.

Selected index combobox winforms

Ok, very dumb question but i haven't really found an answer on internet.
I have multiple comboboxes on a form. The binding of each combobox is on form_load.
When the form loads, the first item is selected on the form. This is obvious, but I don't want this. So i used in the form_load the following code:
private void InvoiceView_Load(object sender, EventArgs e)
{
// Bind list of customers to combobox
CustomerComboBox.DataSource = invoicePresenter.getCustomers();
CustomerComboBox.DisplayMember = "CustomerName";
CustomerComboBox.ValueMember = "CustomerId";
// Bind list of products to combobox
productCombobox.DataSource = invoicePresenter.getProducts();
productCombobox.DisplayMember = "ProductName";
productCombobox.ValueMember = "ProductId";
// Bind list of vat codes to combobox
vatComboBox.DataSource = invoicePresenter.getTaxCodes();
vatComboBox.DisplayMember = "taxCodeShortDescr";
vatComboBox.ValueMember = "taxCodeId";
// Set comboboxes empty
CustomerComboBox.SelectedItem = null;
productCombobox.SelectedItem = null;
vatComboBox.SelectedItem = null;
}
This works. But the textboxes are still giving me the data of the first item ? My guess is because its in the selectedIndexChanged. But i have no clue what to use else.
If I put the combobox.selectedIndex = -1; I face the same issue.
the code:
private void CustomerComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
// Bind the selected customer itemvalues to the texboxes
txtCustomerName.Text = ((tbl_customer)CustomerComboBox.SelectedItem).CustomerName.ToString();
txtAddress.Text = ((tbl_customer)CustomerComboBox.SelectedItem).CustomerAddress.ToString();
txtPostalCode.Text = ((tbl_customer)CustomerComboBox.SelectedItem).CustomerPostalCode.ToString();
txtCity.Text = ((tbl_customer)CustomerComboBox.SelectedItem).CustomerCity.ToString();
txtCountry.Text = ((tbl_customer)CustomerComboBox.SelectedItem).CustomerCountry.ToString();
txtVatNumber.Text = ((tbl_customer)CustomerComboBox.SelectedItem).CustomerCountryCode.ToString() + ((tbl_customer)CustomerComboBox.SelectedItem).CustomerVat.ToString();
}
One would think, because im using selecteditem in the textbox binding, it would be null also. But this is not the case.
Interestingly, seems like you've hit one of the WF data binding quirks. The problem is caused by the fact that the CurrencyManager class which maintains every list data source does not allow setting the Position property to -1 (thus Current to null) when the list count is not zero. Since the ComboBox is synchronizing the SelectedIndex with the CurrencyManager.Position, this effectively prevents having an unselected item.
As a workaround, if the data bound mode of the list portion is not essential for you, replace the line
CustomerComboBox.DataSource = invoicePresenter.getCustomers();
with
foreach (var customer in invoicePresenter.getCustomers())
CustomerComboBox.Items.Add(customer);
Do the same for the other comboboxes that need such behavior.
You can remove the handler for the SelectedIndex_Changed event of combobox, bind data, then add the handler back. like this :
private void InvoiceView_Load(object sender, EventArgs e)
{
this.CustomerComboBox.SelectedIndexChanged -= new EventHandler(CustomerComboBox_SelectedIndexChanged);
this.productCombobox.SelectedIndexChanged -= new EventHandler(productCombobox_SelectedIndexChanged);
this.vatComboBox.SelectedIndexChanged -= new EventHandler(vatComboBox_SelectedIndexChanged);
// Bind list of customers to combobox
CustomerComboBox.DataSource = invoicePresenter.getCustomers();
CustomerComboBox.DisplayMember = "CustomerName";
CustomerComboBox.ValueMember = "CustomerId";
// Bind list of products to combobox
productCombobox.DataSource = invoicePresenter.getProducts();
productCombobox.DisplayMember = "ProductName";
productCombobox.ValueMember = "ProductId";
// Bind list of vat codes to combobox
vatComboBox.DataSource = invoicePresenter.getTaxCodes();
vatComboBox.DisplayMember = "taxCodeShortDescr";
vatComboBox.ValueMember = "taxCodeId";
this.CustomerComboBox.SelectedIndexChanged += new EventHandler(CustomerComboBox_SelectedIndexChanged);
this.productCombobox.SelectedIndexChanged += new EventHandler(productCombobox_SelectedIndexChanged);
this.vatComboBox.SelectedIndexChanged += new EventHandler(vatComboBox_SelectedIndexChanged);
}

ComboBox data binding

I have a combobox control on form that pull its data (Displays and values) from some datasource. On another side I have table with one row. I want when app is lauching, combobox set selectedvalue or selecteditem to value of one column in above row. And when user has changed combobox it will persist change to row. I have tried to bind SelectedValue to this column, but it doesn't work. Combobox just sets on start to first item. What is problem?
EDIT
This is a Win Forms project.
Here is the binding code:
this.comboBoxCountries = new System.Windows.Forms.ComboBox();
this.countriesBindingSource = new System.Windows.Forms.BindingSource(this.components);
//
// comboBoxCountries
//
this.comboBoxCountries.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.searchCriteriaBindingSource, "Postcode", true));
this.comboBoxCountries.DataBindings.Add(new System.Windows.Forms.Binding("SelectedValue", this.searchCriteriaBindingSource, "CountryCode", true));
this.comboBoxCountries.DataSource = this.countriesBindingSource;
this.comboBoxCountries.DisplayMember = "Name";
this.comboBoxCountries.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBoxCountries.FormattingEnabled = true;
this.comboBoxCountries.Location = new System.Drawing.Point(190, 19);
this.comboBoxCountries.Name = "comboBoxCountries";
this.comboBoxCountries.Size = new System.Drawing.Size(156, 21);
this.comboBoxCountries.TabIndex = 2;
this.comboBoxCountries.ValueMember = "Code";
this.comboBoxCountries.SelectedValueChanged += new System.EventHandler(this.comboBoxCountries_SelectedValueChanged);
//
// countriesBindingSource
//
this.countriesBindingSource.DataMember = "Countries";
this.countriesBindingSource.DataSource = this.dbDataSetCountries;
//
// dbDataSetCountries
//
this.dbDataSetCountries.DataSetName = "dbDataSetCountries";
this.dbDataSetCountries.SchemaSerializationMode = System.Data.SchemaSerializationMode.IncludeSchema;
//
// searchCriteriaBindingSource
//
this.searchCriteriaBindingSource.AllowNew = false;
this.searchCriteriaBindingSource.DataMember = "SearchCriteria";
this.searchCriteriaBindingSource.DataSource = this.dbDataSetSearchCriteria;
this.searchCriteriaBindingSource.BindingComplete += new System.Windows.Forms.BindingCompleteEventHandler(this.searchCriteriaBindingSource_BindingComplete);
//
// dbDataSetSearchCriteria
//
this.dbDataSetSearchCriteria.DataSetName = "dbDataSetSearchCriteria";
this.dbDataSetSearchCriteria.SchemaSerializationMode = System.Data.SchemaSerializationMode.IncludeSchema;
EDIT2
As I have mentioned in my comment below, I have another textbox that is binded to another DataMember of same binding source and textbox working fine. It's appear with appropriate value. When I change DataMember on same datamember on which I set selectedvalue property of combobox binding it's also show a good result and work properly.
Thanks in advance!
Take a look at the DisplayMember and ValueMember properties of the combobox. You need to tell the ComboBox what member from the datasource to display in the drop down, and what value to give when SelectedValue is requested.
It sounds like your ComboBox is bound to a static list while your rows are not. You might consider using a BindingSource that you set the ComboBox and the DataGridView's DataSource to. That way when the DGV navigates to a new row, the ComboBox will be updated with the value for the new row.
Here is a link to the ComboBox on MSDN: http://msdn.microsoft.com/en-us/library/system.windows.forms.combobox.aspx
I find it out. So for managing with this issue you should remove SelectedValue databinding from visual studio data bound menu and put an appropriate code to add this databinding in some place after filling all bindingsources:
private void MainForm_Load_1(object sender, EventArgs e)
{
this.searchCriteriaTableAdapter1.Fill(this.dbDataSetCountries.SearchCriteria);
this.searchCriteriaTableAdapter.Fill(this.dbDataSetSearchCriteria.SearchCriteria);
comboBoxCountries.DataBindings.Add("SelectedValue", this.dbDataSetCountries.SearchCriteria, "CountryCode");
}

how to dynamically add combobox in windows forms(C#) and bound it to a column of a table in sql database

My windows form has an ADD button which adds a combo box to the form after each click. The problem is, i am not able to bind it to a table column at run time. Using an existing databinding source selects the same value in all the combo boxes. I am coding in C#
here is the sample code :
ComboBox ocbNext = new ComboBox();
//HAVE set the rest of the properties right, the problem is with the databinding
ocbNext.DataSource = this.dummysubjectBindingSource;
ocbNext.DisplayMember = "sub_name";
ocbNext.ValueMember = "sub_name";
this.Controls.Add(ocbNext);
I added a DataSet to the solution and droped the Employees table (from Northwind) in the designer, which automatically created the employeesBindingSource. I dropped a combobox and a button on the Form and I set the DataSource and DataMember of the combo. Then I handled some events:
private void Form1_Load(object sender, EventArgs e)
{
this.employeesTableAdapter.Fill(this.dS.Employees);
}
private int _i = 0;
private void button1_Click(object sender, EventArgs e)
{
ComboBox combo = new ComboBox();
combo.DataSource = this.employeesBindingSource;
combo.DisplayMember = this.dS.Tables[0].Columns[++_i].ColumnName;
combo.Location = new Point(comboBox1.Location.X, comboBox1.Location.Y + comboBox1.Height * _i);
this.Controls.Add(combo);
}
So on each click, a new combo is added onto the form dynamically right under the previous combo. The combo is also bound to the next column in the Employees table (no boundary checks however).
As you can see, this is pretty easy stuff. Hope this helps.
Okay, so here is a variation of the code that could help you with that other question you asked in the comments of this answer.
It assumes you have a Form with a button and a DataSet with table Employees. On button click it creates a combo, and fills it with data (the Name column of Employees). Each time you add a combo, it gets its own copy of the data (this is important to be able to remove items from one combo at a time). Then, every time you select a value in the combo, the combo is disabled and the other combos don't have that selected value in their list.
private int _i = 0;
private void button1_Click(object sender, EventArgs e)
{
DataSet dataS = dS.Clone();
this.employeesTableAdapter.Fill((DS.EmployeesDataTable)dataS.Tables[0]);
BindingSource bindSource = new BindingSource(dataS, "Employees");
ComboBox combo = new ComboBox();
combo.Name = this.dS.Tables[0].Columns[0].ColumnName + (++_i).ToString();
combo.DataSource = bindSource;
combo.DisplayMember = this.dS.Tables[0].Columns[1].ColumnName; //This column is the Name of Employee
combo.Location = new Point(button1.Location.X, button1.Location.Y + combo.Height * _i);
combo.SelectedIndexChanged += new EventHandler(comboBox_SelectedIndexChanged);
this.Controls.Add(combo);
}
private void comboBox_SelectedIndexChanged(object sender, EventArgs e)
{
foreach (Control ctrl in this.Controls)
{
if (ctrl is ComboBox && ctrl != sender && ctrl.Enabled)
{
((BindingSource)((ComboBox)ctrl).DataSource).RemoveAt(((ComboBox)sender).SelectedIndex);
}
}
((ComboBox)sender).Enabled = false;
}
This is pretty close to what you require, or easily adaptable to meet your expectations. Enjoy and please select an answer as the accepted one. Thanks!
Option 1: Fill the combobox with strings:
this.comboBox1.Items.Add("Syed");
this.comboBox1.Items.Add("Baqar");
Option 2: Fill the combobox with an array of strings:
this.comboBox1.Items.AddRange(new object[] { "Syed", "Baqar" });
You need to add controls to the parent window first, and then set the data source.
ComboBox ocbNext = new ComboBox();
this.Controls.Add(ocbNext);
ocbNext.DisplayMember = "sub_name";
ocbNext.ValueMember = "sub_name";
ocbNext.DataSource = this.dummysubjectBindingSource;
Should be fine if you create a new local ComboBox variable in the clickevent. If you use a global variable for the ComboBox this might explain your problems. But without a sample how you're doing it's hard to see what's really happening, so think this is just a rough guess

Categories