简体   繁体   中英

Get ComboBox selected value from a list which has two types of objects and the combobox is only showing one of them

I'm building a C# application in Windows Forms.
I have a vehicle class and two derived classes car and motorbike.
I then have the vehicles saved into a list.

Now I have a form where I want to show only the cars or only the motorbikes. In a main form there is a button "show cars" and another button "show motorbikes" and they will tell the other form which to list ("type" variable in code below).

In the show form I have a combobox which will show all the cars or motorbikes (only one, not both) that exist and when selecting one, there are textboxes that will show the info from that one.

To populate the combobox I use:

foreach (Vehicle V in GetVehiclesList())
{
    if (type == "Car")
    {
        if (V.WhatIsIt() == "Car")
        {
            combobox.Items.Add(V.GetVehicleName());
        }
    }
    else if (type == "Motorbike")
    {
        if (V.WhatIsIt() == "Motorbike")
        {
            combobox.Items.Add(V.GetVehicleName());
        }
    }
}

Note: WhatIsIt() returns a string with the class' name.

Now the problem is to get the selected vehicle in the combobox to show the info from that vehicle.

If I wanted to show all the vehicles, I would use this:

private void combobox_SelectedIndexChanged(object sender, EventArgs e)
{
    VehicleToShow = GetVehiclesList()[combobox.SelectedIndex];
    vehicle_name_textbox.Text = VehicleToShow.GetVehicleName();
    // and goes on
}

What this does is it gets the index number of the combobox item selected and goes get the vehicle in the list with that same position number. It works because the vehicles are added to the combobox with same position/index as in the list. Therefore, it doesn't work for displaying only one of them (car or motorbike) because the position number in list will fail to be equal to the index in combobox.

So I used the folowing approach:

private void combobox_SelectedIndexChanged(object sender, EventArgs e)
{
    VehicleToShow = null;
    int carposition = 0;
    int motorbikeposition = 0;
    int comboboxindex = combobox.SelectedIndex;

    foreach (Vehicle V in GetVehiclesList())
    {
        if (V.WhatIsIt() == "Car")
        {
            if (carposition == comboboxindex)
            {
                VehicleToShow = V;
            }
            else
            {
                carposition++;
            }
        }
        else if (V.WhatIsIt() == "Motorbike")
        {
            if (motorbikeposition == comboboxindex)
            {
                VehicleToShow = V;
            }
            else
            {
                motorbikeposition++;
            }
        }
    }

    vehicle_name_textbox.Text = VehicleToShow.GetVehicleName();
    // and goes on
}

While this seems to me to be something that should work, when using it, it won't display the info from the vehicle selected in the combobox.

How can I get it to work?

Note: Placing each vehicle type in a different list is not an option. Also, searching list for an object with same name as selected value is not best option since it won't work properly if it has two vehicles with same name. Ideally it would be something similar as the approach I tried to use.

Don't add the names of your objects to the list. Add the actual objects themselves instead; then combobox.SelectedItem immediately contains everything you need without requiring any lookup at all, since it'll be the full object.

The filling of the data:

this.combobox.Items.Clear();
foreach (Vehicle veh in this.GetVehiclesList())
{
    // assuming "type" is a string variable filled up by some other selected value.
    if (!String.Equals(type, typeof(veh).ToString()))
        continue;
    this.combobox.Items.Add(veh);
}

Though derloopkat's suggestion of saving type as an actual Type so you can compare them directly is probably more efficient than string compares. Avoid string compares in code; they are often an ugly programmer shortcut for something that can be done way more elegantly and efficiently internally.

To make them show up in the list correctly, simply add the ToString() function in your vehicle class that returns the actual vehicle name:

public override String ToString()
{
    return this.GetVehicleName()
}

And finally, to retrieve the selected object and update your UI:

private void combobox_SelectedIndexChanged(Object sender, EventArgs e)
{
    // "as" is a "try cast": if the object is not the expected type it will become null.
    this.VehicleToShow = this.combobox.SelectedItem As Vehicle;
    if (this.VehicleToShow == null)
        return; // maybe add code to clear UI
    this.vehicle_name_textbox.Text = this.VehicleToShow.GetVehicleName();
    // fill in the rest
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM