0

I have a combobox I'm selecting a value from. I want to use the newly selected value in the combobox as a comparison to my database, but I've only been able to return the value that matches with the text that was in the combobox before the selection change.

I've tried changing .text to selected item & selected value, neither of which returns a selection at all.

This is called upon the ComboBox selection change:

    private void StationComboBox_1_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        GetIP();
    }

    private void GetIP()
    {
        string connectionString = "SERVER=localhost;DATABASE=db; UID=PC;Password=pw;";

        MySqlConnection connection = new MySqlConnection(connectionString);

        MySqlCommand cmd = new MySqlCommand("SELECT IP_stations from stations WHERE stationNumber_stations='" + stationComboBox_1.Text + "'", connection); 
        connection.Open();

        string IP = (string)cmd.ExecuteScalar();


        DisplayIP.Text = IP;

This is the code from that ComboBox, which gets its values from the same database, but a different table.

<ComboBox 
    Grid.Column="1" 
    x:Name="stationComboBox_1" 
    FontSize="25" 
    Width="60" 
    HorizontalAlignment="Left" 
    DisplayMemberPath="stationNumber_stations" 
    ItemsSource="{Binding}" 
    Text="0" 
    SelectionChanged="StationComboBox_1_SelectionChanged"
    />

DisplayIP Xaml:

<TextBox x:Name="DisplayIP"/>

Setting up the ComboBoxes:

        public void SQLSetup()
        {
            string connectionString = "SERVER=localhost;DATABASE=db; UID=PC;Password=pw;"; 

            MySqlConnection connection = new MySqlConnection(connectionString); 

            MySqlCommand cmd = new MySqlCommand("Select stationNumber_stations from stations", connection); //Command to select all the station numbers
            connection.Open();


            DataTable dt = new DataTable(); //Creates a new data table
            dt.Load(cmd.ExecuteReader()); //Loads the data table with the values returned from the MySQL command
            connection.Close(); //Closes the MySQL connection

            //Sets the values in the station dropdowns to the values from the data table with the station numbers
            stationComboBox_1.DataContext = stationComboBox_2.DataContext = stationComboBox_3.DataContext = stationComboBox_4.DataContext = stationComboBox_5.DataContext =
                stationComboBox_6.DataContext = stationComboBox_7.DataContext = stationComboBox_8.DataContext = dt;
            stationComboBox_1.ItemsSource = stationComboBox_2.ItemsSource = stationComboBox_3.ItemsSource = stationComboBox_4.ItemsSource = stationComboBox_5.ItemsSource =
                stationComboBox_6.ItemsSource = stationComboBox_7.ItemsSource = stationComboBox_8.ItemsSource = dt.DefaultView;


            //sets an int to the value selected in the station dropdown
            string stationSelection_1 = stationComboBox_1.Text;
            string stationSelection_2 = stationComboBox_2.Text;
            string stationSelection_3 = stationComboBox_3.Text;
            string stationSelection_4 = stationComboBox_4.Text;
            string stationSelection_5 = stationComboBox_5.Text;
            string stationSelection_6 = stationComboBox_6.Text;
            string stationSelection_7 = stationComboBox_7.Text;
            string stationSelection_8 = stationComboBox_8.Text;
        }

I want the DisplayIP TextBox to display the IP of the current selection. However, it is displaying the IP of the previous selection.

Right now, on startup, both the ComboBox & TextBox are empty. I select a station in the ComboBox & the TextBox remains empty. When I select a new station in the ComboBox, the TextBox updates to display the IP address of the first selection.

  • 1
    Please add XAML for the DisplayIP textbox. Please also show the properties of the item class being displayed in the combobox. You should probably use `SelectedValuePath` and `SelectedValue`. You can probably set the textbox text via a binding. You should probably be using `stationComboBox_1.SelectedValue` instead of `stationComboBox_1.Text`. – 15ee8f99-57ff-4f92-890c-b56153 May 09 '19 at 13:15
  • I've added the XAML for the TextBox, exactly what do you mean by the properties of the item class being displayed in the ComboBox? I've added in the setup where the ComboBox is being populated as well. – Schreiberito May 09 '19 at 13:20
  • 1
    I mean what are you populating the ComboBox with? What's in the ItemsSource? Something, some class, perhaps a DataRow, has a property or column named `stationNumber_stations`. Please show me it. – 15ee8f99-57ff-4f92-890c-b56153 May 09 '19 at 13:21
  • I've got that code in as well now. Took me a second to find & post it, it's in the original question at the bottom now. – Schreiberito May 09 '19 at 13:23
  • 1
    Thanks for the update. You don't need to set DataContext in the codebehind on those comboboxes, and as long as you're setting their ItemsSource in codebehind, `ItemsSource="{BInding}"` has no effect in the XAML and should be removed. It only causes confusion to leave it there when it has no effect. You really should learn MVVM and write a viewmodel and do this all via bindings, but that's beyond the immediate scope of this question. – 15ee8f99-57ff-4f92-890c-b56153 May 09 '19 at 13:31
  • 1
    Now please tell me **what are the names of the columns** in your data table. One of them is named `stationNumber_stations`. What are the others? Is one called `IP_stations`? – 15ee8f99-57ff-4f92-890c-b56153 May 09 '19 at 13:32
  • Ahh, that was left over from a way I had been doing it previously that I abandoned, I'll remove the {Binding}s. Trust me, I know I need to learn MVVM & have started on it. The tutorial I started on was great, but I hit a snag in the code I couldn't get working, I think it was a bit outdated. I'm having to start over with another route to learn it. Do you have any good resource suggestions? As far as the columns go, yes, one is IP_stations. The others are id_stations, MAC_stations, & port_stations. – Schreiberito May 09 '19 at 13:41

1 Answers1

1

It looks like when you change the selection in the ComboBox, you want the textbox to display the IP address of the selected station. We know that's in the IP_stations column in the stations table.

We already discussed the fact that ItemsSource="{Binding}" is redundant, so I'm omitting that. I'm omitting the selection-changed handler because that job will be done by a binding. There's no need to re-query the database when the selection changes, because we already have all the columns of all the rows in the DataView displayed in the combobox.

You've already learned DisplayMemberPath, and we'll be using his evil twin, SelectedValuePath.

SelectedValuePath="IPStations" tells the combobox that when the selection changes, it should look at the selected item (in this case a DataRowView from the DataView), and try to find a property or column (column, in our case) by that name. If it finds it, the ComboBox will assign the value of that column to its own SelectedValue property. Then we teach the textbox to update itself by binding its Text property to stationComboBox_1.SelectedValue.

To make that work you'll need to select both values from the table (I neglected this the first time around):

//Command to select all the station numbers and IPs
MySqlCommand cmd = 
    new MySqlCommand("Select stationNumber_stations, IP_stations from stations", 
        connection); 

Done.

<ComboBox 
    Grid.Column="1" 
    x:Name="stationComboBox_1" 
    Width="60" 
    HorizontalAlignment="Left" 
    DisplayMemberPath="stationNumber_stations" 
    SelectedValuePath="IP_stations"
    />
<TextBox
    Text="{Binding SelectedValue, ElementName=stationComboBox_1}" 
    />

ComboBox.Text is only used in WPF in cases where the text of the combobox is editable.

Incidentally, here's what you could have done in the selection changed handler:

private void stationComboBox_1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    var cb = (sender as ComboBox);

    //  If SelectedValuePath is "IP_Stations", this will be the IP address. 
    //  It will be the correct current selected value. 
    var selectedValue = cb.SelectedValue;

    //  Alternatively, we could do it this way:
    var row = cb.SelectedItem as DataRowView;

    if (row != null)
    {
        var selectedIP = row["IP_stations"];
    }
}

The next issue here, at least in my mind, is that you're copying and pasting everything eight times. MVVM could get you out of that mess.

  • Hmmm, it's almost working for me. If I change the ComboBox's SelectedValuePath to stationNumber_stations, it will display the selected station number. However, when I change back to IP_stations, it remains blank. I'm still not totally clear on how the SelectedValuePath queries the database to say "Hey, I picked station 12, IP address xxx.xxx.xx.xx is the value in the corresponding column." – Schreiberito May 09 '19 at 15:11
  • 1
    @Schreiberito Sorry, I neglected one important thing: You'll need to select both columns from the table when you populate the combobox: `Select stationNumber_stations, IP_stations from stations`. SelectedValuePath just looks for the column you tell it to look for in the rows the ComboBox already has -- but (derp) that column has to be in the select list. – 15ee8f99-57ff-4f92-890c-b56153 May 09 '19 at 15:44
  • 1
    That did the trick! That clears up my question about how SelectedValuePath queries the database-it doesn't, haha. I just assumed since it was referring to a column we hadn't already selected that it had to be accessing the database somehow. Thanks for the help as always, you're the best. – Schreiberito May 09 '19 at 16:52