I am working on a program in which a combobox's options are dependent on another combobox's selected option. The selected item from the first combobox chooses which options are in the second combobox. Does anyone know how to do this?
This is the button that adds the information to the first combobox
try
{
CustomerAccount aCustomerAccount = new CustomerAccount(txtAccountNumber.Text, txtCustomerName.Text,
txtCustomerAddress.Text, txtPhoneNumber.Text);
account.Add(aCustomerAccount);
cboClients.Items.Add(aCustomerAccount.GetCustomerName());
ClearText();
}
catch (Exception)
{
MessageBox.Show("Make sure every text box is filled in!", "Error", MessageBoxButtons.OK);
}
And here is the selectedIndex for the first combobox.
private void cboClients_SelectedIndexChanged(object sender, EventArgs e)
{
CustomerAccount custAccount = account[cboClients.SelectedIndex] as CustomerAccount;
if (custAccount != null)
{
txtAccountNumberTab2.Text = custAccount.GetAccountNumber();
txtCustomerNameTab2.Text = custAccount.GetCustomerName();
txtCustomerAddressTab2.Text = custAccount.GetCustomerAddress();
txtCustomerPhoneNumberTab2.Text = custAccount.GetCustomerPhoneNo();
}
}
Add a SelectedIndexChanged event handler for the first ComboBox. Use it to clear the content of the second ComboBox and populate it with the related items:
public Form1()
{
InitializeComponent();
for(int i = 0; i < 10; i++) {
comboBox1.Items.Add(String.Format("Item {0}", i.ToString()));
}
comboBox1.SelectedIndex = 0;
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
comboBox2.Items.Clear();
for (int i = 0; i < 5; i++)
{
comboBox2.Items.Add(String.Format("Item_{0}_{1}",
comboBox1.SelectedItem, i.ToString()));
}
comboBox2.SelectedIndex = 0;
}
Related
I'm trying to create textboxes based on the amount selected from the drop down list; however say I select 2 it shows the 2 textboxes, and I go and select 3 then the 3 textboxes is added to the other 2 textboxes making it 5 textboxes. I tried null the control cache but one extra textbox seem to always be adding.
protected List<Control> ControlCache
{
get { return (List<Control>)(Session["cachedControlsForPageX"] = (Session["cachedControlsForPageX"] as List<Control>) ?? new List<Control>()); }
set { Session["cachedControlsForPageX"] = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
foreach (var control in ControlCache)
{
ContentPlaceHolder1.Controls.Add(control);
ContentPlaceHolder1.Controls.Add(new LiteralControl(" "));
}
}
else
ControlCache = null;
}
protected void ddlCount_SelectedIndexChanged(object sender, EventArgs e)
{
int count = Convert.ToInt32(ddlCount.SelectedItem.Value);
for (int i = 0; i < count; i++)
{
ControlCache = null;
TextBox tx = new TextBox();
tx.MaxLength = 10;
ContentPlaceHolder1.Controls.Add(tx);
ContentPlaceHolder1.Controls.Add(new LiteralControl(" "));
ControlCache.Add(tx);
}
}
I have a comoboBox that is binded to sql database, and I added a default text at index 0 like this
string s = "< -------------Select an application ----------->";
applicationComboBox.Items.Insert(0, s);
applicationComboBox.SelectedIndex = 0;
I am wondering if there is a way to disable my button if the the string s at index 0 is select? In my comboBox, I binded the data with the while(SQLReader.Read()) method instead of using ValueMember and `DisplayMember
Here is what I tried but no luck
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
for (int i = 1; i < applicationComboBox.Items.Count; i++)
{
string value = applicationComboBox.GetItemText(applicationComboBox.Items[0]);
string s = "<------------- Select an application ----------->";
if (value == s)
{
exportButton.Enabled = false;
MessageBox.Show(value); //nothing happen
this.teacherCheckListBox.DataSource = null;
teacherCheckListBox.Items.Clear();
}
else
{
exportButton.Enabled = true;
}
}
}
}
Use SelectedIndex property to know which item is selected and disable the button if it is first item.
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox1.SelectedIndex == 0)
{
exportButton.Enabled = false;
}
}
I am working on a Visual Studio extension and my current goal is to set up a menu item in the Tools menu. When clicked on this menu item will open a WinForms window containing a ListView, 3 textboxes, and a button. The idea is when you click on one of the rows in the ListView the data from that row will be populated in the textboxes so that you can update it. If you click the button a new row is added and the textboxes are cleared. However, I'm having an issue with getting the index of the row that I've selected.
private int _index;
private void newSourceBtn_Click(object sender, EventArgs e)
{
// Add new row to the ListView
ListViewItem row = new ListViewItem();
row.SubItems.Add("new");
row.SubItems.Add(String.Empty);
row.SubItems.Add(String.Empty);
remoteSourceListView.Items.Add(row);
int index = remoteSourceListView.Items.Count - 1;
remoteSourceListView.Items[index].Selected = true;
newSourceAdded = true;
sourceNameTextBox.Clear();
sourceUrlTextBox.Clear();
}
public void SourceName_TextChanged(object sender, EventArgs e)
{
remoteSourceListView.Items[IndexSelected].SubItems[1].Text = sourceNameTextBox.Text;
}
public void SourceURL_TextChanged(object sender, EventArgs e)
{
string url = sourceUrlTextBox.Text;
if ((url.StartsWith("http")) || (url.StartsWith("https")) || (url.StartsWith("git")))
{
sourceBranchTextBox.Enabled = true;
}
remoteSourceListView.Items[IndexSelected].SubItems[2].Text = url;
}
public void SourceBranch_TextChanged(object sender, EventArgs e)
{
}
public void SourcesListView_SelectedIndexChanged(object sender, EventArgs e)
{
ListView.SelectedListViewItemCollection selectedRows = remoteSourceListView.SelectedItems;
foreach (ListViewItem row in selectedRows)
{
sourceNameTextBox.Text = row.SubItems[1].Text;
sourceUrlTextBox.Text = row.SubItems[2].Text;
IndexSelected = row.Index;
if (row.SubItems[3].Text != "")
{
sourceBranchTextBox.Enabled = true;
sourceBranchTextBox.Text = row.SubItems[3].Text;
}
}
}
public int IndexSelected
{
get { return _index; }
set { _index = value; }
}
This code shows the button click event which adds the new row to the ListView, the text changed events for each of the textboxes which updates the row in the ListView (sorta), and the selected index changed event for the ListView which is where I'm getting the index of the row that was just selected. While debugging, I noticed that when I click on a row I'm getting the correct index in the selected index changed event; however, when I call IndexSelected from either of the text changed events it is always giving me a different index.
Any suggestions?
From the code posted I can't find any reason that explain the behavior documented.
A possible reason could be the insertion/deletion of new/existing ListViewItem in a position before the saved RowIndex.
However another approach is possible. Instead of keeping the RowIndex you could try to set a global property to the ListViewItem selected and reuse this instance when you need to set its subitems.
In this way you avoid problems if the number of ListViewItems change and some item is inserted/removed before the saved RowIndex. However a safeguard against a null value should be provided.
private ListViewItem CurrentItemSelected {get;set;}
......
public void SourcesListView_SelectedIndexChanged(object sender, EventArgs e)
{
ListView.SelectedListViewItemCollection selectedRows = remoteSourceListView.SelectedItems;
foreach (ListViewItem row in selectedRows)
{
sourceNameTextBox.Text = row.SubItems[1].Text;
sourceUrlTextBox.Text = row.SubItems[2].Text;
CurrentItemSelected = row;
if (row.SubItems[3].Text != "")
{
sourceBranchTextBox.Enabled = true;
sourceBranchTextBox.Text = row.SubItems[3].Text;
}
}
}
public void SourceName_TextChanged(object sender, EventArgs e)
{
if(CurrentItemSelected != null)
CurrentItemSelected.SubItems[1].Text = sourceNameTextBox.Text;
}
However, I am a bit perplexed by your code. Do you have the property MultiSelect set to true? Because if it is set to false then your code doesn't need to loop.
public void SourcesListView_SelectedIndexChanged(object sender, EventArgs e)
{
if(remoteSourceListView.SelectedItems.Count > 0)
{
// With MultiSelect = false; there is only one selected item.
CurrentItemSelected = remoteSourceListView.SelectedItems[0];
sourceNameTextBox.Text = CurrentItemSelected.SubItems[1].Text;
sourceUrlTextBox.Text = CurrentItemSelected.SubItems[2].Text;
if (CurrentItemSelected.SubItems[3].Text != "")
{
sourceBranchTextBox.Enabled = true;
sourceBranchTextBox.Text = CurrentItemSelected.SubItems[3].Text;
}
}
}
I'm new here to Stack Overflow so please excuse any improper form/etiquette. Thanks!
EDIT: I guess my questions is not about how to fix the NullReference Exception, but rather how to deal with it not correctly "Exiting" the combobox when I click outside of it.
I am having an issue with my DataGridViewComboBoxCell setup that I am using. First of all, I have a datagridview that contains 3 columns which, upon the user enabling editing, populates the cells with a DataGridViewComboBoxCell. In each row, These 3 cells are dependent on selected item in the previous cell(except for the first ComboBoxCell). The issue I am having is if I click on the first ComboBox and I let it show the drop down list but I don't actually select anything and I move to the next ComboBoxCell and try to click it to view its list of items it stops the program and creates an error for "NullReference Exception was unhandled". This exception comes up under "static void Main()" at Application.Run(new MainForm());
Code that handles changing ComboBox selected index which should auto populate the other ComboBoxes.
private void LoadRules_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
DataGridViewComboBoxEditingControl cbx = e.Control as DataGridViewComboBoxEditingControl;
if (cbx != null)
{
if (this.LoadRulesDataGridView.Columns[LoadRulesDataGridView.CurrentCell.ColumnIndex].Name.Equals("OEM"))
{
ComboBox cmbprocess = e.Control as ComboBox;
cmbprocess.SelectedIndexChanged += new EventHandler(OEMBox_SelectedIndexChanged);
cmbprocess.SelectedIndexChanged += new EventHandler(ModelBox_SelectedIndexChanged);
}
}
}
private void OEMBox_SelectedIndexChanged(object sender, EventArgs e)
{
NetMonDB.DBManager dbConn = new NetMonDB.DBManager(ConnStr, this.LogWarning, this.LogError);
ComboBox cmbprocess = (ComboBox)sender;
int row = this.LoadRulesDataGridView.CurrentCell.RowIndex;
string OEM = cmbprocess.SelectedItem.ToString();
this.RulesGridModels(row, cmbprocess, dbConn, OEM);//this method gets the required info from the database and loads it into the ComboBox
cmbprocess.SelectedIndexChanged -= new EventHandler(OEMBox_SelectedIndexChanged);
}
private void ModelBox_SelectedIndexChanged(object sender, EventArgs e)
{
NetMonDB.DBManager dbConn = new NetMonDB.DBManager(ConnStr, this.LogWarning, this.LogError);
ComboBox cmbprocess = (ComboBox)sender;
int row = this.LoadRulesDataGridView.CurrentCell.RowIndex;
string Model = cmbprocess.SelectedItem.ToString();
string OEM = cmbprocess.SelectedItem.ToString();
this.RulesGridOSVersions(row, cmbprocess, dbConn, OEM, Model);//this method gets the required info from the database and loads it into the ComboBox
cmbprocess.SelectedIndexChanged -= new EventHandler(ModelBox_SelectedIndexChanged);
}
Methods that update the ComboBoxes.
private void RulesGridModels(int r, ComboBox comboBox, NetMonDB.DBManager dbConn, string rowOEM)
{
//MessageBox.Show(this.LoadRulesDataGridView.Rows[0].Cells[4].Value.ToString());
DataGridViewComboBoxCell cbo = new DataGridViewComboBoxCell();
for (int i = 0; i < comboBox.Items.Count; i++)
{
cbo.Items.AddRange(comboBox.Items[i]);
}
try
{
cbo.Items.Clear();
cbo.Items.AddRange("");
if (this.LoadRulesDataGridView.Rows[r].Cells[4].Value == null)
this.LoadRulesDataGridView.Rows[r].Cells[4].Value = "";
NetMonDB.Phone OEMPhone = dbConn.getOEMId(rowOEM);
foreach (NetMonDB.Phone phone in dbConn.getModel(OEMPhone))
{
cbo.Items.Add(phone.Model);
}
this.LoadRulesDataGridView.Rows[r].Cells[5] = cbo;
}
catch (Exception e)
{
LogError("RulesGridModels", e.ToString());
}
}
private void RulesGridOSVersions(int r, ComboBox comboBox, NetMonDB.DBManager dbConn, string rowOEM, string rowModel)
{
DataGridViewComboBoxCell cbo = new DataGridViewComboBoxCell();
for (int i = 0; i < comboBox.Items.Count; i++)
{
cbo.Items.AddRange(comboBox.Items[i]);
}
try
{
cbo.Items.Clear();
cbo.Items.AddRange("");
NetMonDB.Phone CurrentPhone = dbConn.getOEMId(rowOEM);
CurrentPhone.Model = rowModel;
foreach (NetMonDB.Phone phone in dbConn.getOSVersion(CurrentPhone))
{
cbo.Items.Add(phone.OSVersion);
}
this.LoadRulesDataGridView.Rows[r].Cells[6] = cbo;
}
catch (Exception e)
{
LogError("RulesGridOSVersions", e.ToString());
}
}
Where the exception is caught.
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());//Crashes at this Point
}
I had the same problem in a situation like this, What I found as a solution of this problem is to use SelectionChangeCommitted instead of SelectedIndexChanged event for combobox.
I have a form with databound combobox, with dropstyle set as dropdown, so users could type in the combobox.
My problem is that when users type in the combobox and the value typed matches one of the values bound to the combobox it won't change the selectedindex, even though I've tried too. Instead, it sets the selected index to -1 (and thus the selected value is null).
Can anyone help? here's my code (one of my tries, i tried other approaches but none helped).
private void setCombo()
{
comboFromOther.DisplayMember = "tbl10_KupaID";
comboFromOther.ValueMember = "tbl10_KupaID";
comboFromOther.DataSource = dsKupotGemel.Tables[0];
}
private void comboToOther_TextChanged(object sender, EventArgs e)
{
comboDetail = changedComboText(2, comboToOther.Text);
textToOther.Text = comboDetail[0];
if (comboDetail[0] == "")
{
}
else
{
comboToOther.SelectedIndex = System.Int32.Parse(comboDetail[1]);
comboToOther.SelectedValue = System.Int32.Parse(comboDetail[2]);
}
}
private string[] changedComboText(int iComboType, string comboString)
{
if (groupCalculate.Visible == true)
{
groupCalculate.Visible = false;
}
string[] kupaDetail = new string[3];
kupaDetail[0] = "";
kupaDetail[1] = "";
kupaDetail[2] = "";
for (int i = 0; i <= dsKupotGemel.Tables[0].Rows.Count - 1; i++)
{
if (comboString == dsKupotGemel.Tables[0].Rows[i][0].ToString())
{
kupaDetail[0] = dsKupotGemel.Tables[0].Rows[i][1].ToString();
kupaDetail[1] = i.ToString();
kupaDetail[2] = comboString;
break;
}
else
{
}
}
return kupaDetail;
}
Maybe there is an error in your code?
Here is a working sample:
// Fields
private const string NameColumn = "Name";
private const string IdColumn = "ID";
private DataTable table;
Next, initialization
// Data source
table = new DataTable("SomeTable");
table.Columns.Add(NameColumn, typeof(string));
table.Columns.Add(IdColumn, typeof(int));
table.Rows.Add("First", 1);
table.Rows.Add("Second", 2);
table.Rows.Add("Third", 3);
table.Rows.Add("Last", 4);
// Combo box:
this.comboBox1.DisplayMember = NameColumn;
this.comboBox1.ValueMember = IdColumn;
this.comboBox1.DataSource = table;
this.comboBox1.DropDownStyle = ComboBoxStyle.DropDown;
this.comboBox1.TextChanged += comboBox1_TextChanged;
this.comboBox1.SelectedIndexChanged += this.comboBox1_SelectedIndexChanged;
Event handlers - TextChanged:
private void comboBox1_TextChanged(object sender, EventArgs e)
{
for (int i = 0; i < table.Rows.Count; i++)
{
if (table.Rows[i][NameColumn].ToString() == this.comboBox1.Text)
{
this.comboBox1.SelectedValue = table.Rows[i][IdColumn];
break;
}
}
}
Event handlers - SelectedIndexChanged:
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
// Do here what is required
}
With this code, as soon as user types full name of item into combo box, SelectedIndexChanged is invoked through TextChanged.
There is also such thing as AutoCompleteMode, AutoCompleteSource. Don't know where they fit into your application.