I am creating an airline booking system and I have 2 combo boxes. The first is for Departure City and the second is for Arrival City. I want to be able to eliminate the choice in the first combo box from the second, as I don’t want the same city to be able to be submitted as both the departure and arrival city. I am querying the city names from a database.
Here is my code:
public partial class main : Form { public main() { InitializeComponent(); string connectionString = @"Base Schema Name=cyanair;data source=C:UsersClient 0819sourcereposCyanaircyanair.db"; //Departure ComboBox SQLiteConnection conn = new SQLiteConnection(connectionString); try { conn.Open(); SQLiteCommand cmd = new SQLiteCommand(); cmd.Connection = conn; cmd.CommandType = System.Data.CommandType.Text; cmd.CommandText = "SELECT * FROM CyanairAirports"; SQLiteDataAdapter da = new SQLiteDataAdapter(cmd); DataTable dt = new DataTable(); da.Fill(dt); comboDeparture.DataSource = dt; comboDeparture.ValueMember = "Descriptions"; comboDeparture.DisplayMember = "Descriptions"; conn.Close(); } catch (Exception ex) { MessageBox.Show(ex.Message); } } //Arrival ComboBox private void comboDeparture_DisplayMemberChanged(object sender, EventArgs e) { string connectionString = @"Base Schema Name=cyanair;data source=C:UsersClient 0819sourcereposCyanaircyanair.db"; SQLiteConnection conn = new SQLiteConnection(connectionString); **String city = comboDeparture.DisplayMember;** try { conn.Open(); SQLiteCommand cmd = new SQLiteCommand(); cmd.Connection = conn; cmd.CommandType = System.Data.CommandType.Text; cmd.CommandText = "SELECT * FROM CyanairAirports WHERE Descriptions IS NOT '" + comboDeparture.SelectedValue.ToString() + "'"; richTextBox1.Text = "SELECT * FROM CyanairAirports WHERE Descriptions IS NOT '" + comboDeparture.SelectedValue + "'"; SQLiteDataAdapter da = new SQLiteDataAdapter(cmd); DataTable dt = new DataTable(); da.Fill(dt); comboArrival.DataSource = dt; comboArrival.ValueMember = "Descriptions"; comboArrival.DisplayMember = "Descriptions"; conn.Close(); } catch (Exception ex) { MessageBox.Show(ex.Message); } }
Thanks 🙂
Advertisement
Answer
It looks like you’re handling the DisplayMemberChanged
event on comboDeparture
, and trying to update the values of comboArrival
in that handler. However, DisplayMemberChanged
only triggers when the DisplayMember
property changes.
DisplayMember
only tells the control which property to display on a data bound control. It isn’t tied to the index or value selected in the ComboBox
. So, the only time the code to populate comboArrival
runs is in the constructor when you set comboDepartarture.DisplayMember
. Instead, handle either ComboBox.SelectedIndexChanged
or ComboBox.SelectedValueChanged
and set the items of comboArrival
.
A few other important things to note about your code.
First, you should use a parameterized query when running Sql Statements, rather than concatenating strings. Concatenating strings as you’re doing opens you up to SQL Injection Attacks. I’m not familiar with SqlLite and can’t provide you with an example of how to modify your code, but perhaps this question can help.
Second, you don’t need to re-run the query every time you change the selected value in comboDeparture
. Just add comboArrival
‘s data source as a field on the Form
and you can filter it. For example…
public partial class main : Form { // Your constructors... private void comboDepartures_SelectedIndexChanged(object sender, EventArgs e) { if (_arrivalsDataSource == null) { _arrivalsDataSource = new System.Data.DataTable(); // Load _arrivalsDataSource from the database, basically how you're doing it now. comboArrival.DataSource = _arrivalsDataSource.DefaultView; comboArrival.DisplayMember = "Descriptions" comboArribal.ValueMember = "Descriptions" } if (comboDeparture.SelectedIndex == -1) { _arrivalsDataSource.DefaultView.RowFilter = null; // Clear the filter. } else { // Set the filter. _arrivalsDataSource.DefaultView.RowFilter = $"Description <> '{comboDeparture.SelectedValue}'"; } } private System.Data.DataTable _arrivalsDataSource = null; }