ComboBox usage

C

Cralis

I have a List of data objects.
I need to populate a ComboBox with the 'Description' field from the
objects.
I can do that with cmbBx.Items.Add( myObject.Description.ToString() );

myObject has 2 fields for example. id and description.

Later, I need to get the id of the selected item in the ComboBox...

In Delphi, I'd create a StringList, and add the ID to that, and then
just match up the index of the combobox with the corrasponding index
of the StringList to objtain the selected descriptions ID.

Is there a better way to do this in C#?
 
M

Morten Wennevik [C# MVP]

I have a List of data objects.
I need to populate a ComboBox with the 'Description' field from the
objects.
I can do that with cmbBx.Items.Add( myObject.Description.ToString() );

myObject has 2 fields for example. id and description.

Later, I need to get the id of the selected item in the ComboBox...

In Delphi, I'd create a StringList, and add the ID to that, and then
just match up the index of the combobox with the corrasponding index
of the StringList to objtain the selected descriptions ID.

Is there a better way to do this in C#?

Yes, just add the items as they are to the ComboBox
Then set the DisplayMember property of the ComboBox
And the ValueMember property

ComboBox.DisplayMember = "Description";
ComboBox.ValueMember = "Id";

You can then get the selected id by using ComboBox.SelectedValue
Or, in case ValueMember doesn't work, use

MyObject myObject = (MyObject)ComboBox.SelectedItem
 
C

Cralis

Sounds like exactly what I need. But it's not working. Am I doing it
wrong?

cmbModels.Items.Clear();

cmbModels.Items.Add("Show All");
cmbModels.Items.Add("Not Model Specific");

cmbModels.DisplayMember = "description";
cmbModels.ValueMember = "id";

List<IModel> models = doModels.getListOfModels(false);

foreach (IModel model in models)
{
cmbModels.Items.Add(model);
}
cmbModels.SelectedIndex = 0;
 
M

Morten Wennevik [C# MVP]

Sounds like exactly what I need. But it's not working. Am I doing it
wrong?

cmbModels.Items.Clear();

cmbModels.Items.Add("Show All");
cmbModels.Items.Add("Not Model Specific");

cmbModels.DisplayMember = "description";
cmbModels.ValueMember = "id";

List<IModel> models = doModels.getListOfModels(false);

foreach (IModel model in models)
{
cmbModels.Items.Add(model);
}
cmbModels.SelectedIndex = 0;

Well, you are adding a mix of objects. You need to create IModel objects with description "Show All" and "Not Model Specific". You can then use the DataSource property as well

private void Method()
{
cmbModels.Items.Clear();

List<IModel> models = new List<IModel>();
models.Add(new Model("Show All"));
models.Add(new Model("Not Model Specific"));
models.AddRange(doModels.getListOfModels(false));

cmbModels.DataSource = models;
cmbModels.DisplayMember = "Description";
cmbModels.ValueMember = "Id";
}

public interface IModel
{
string Description { get; set;}
int Id { get;set;}
}

public class Model : IModel
{
string description;
int id;
public string Description { get { return description; } set{ description = value; } }
public int Id { get { return id; } set { id = value; } }
public Model(string description)
{
this.Description = description;
}
}

However, using a DataSource, you may not be able to specify the selectedindex at the time you set the DataSource, but as the default index is 0 anyway you won't need to set it at all. The IModel and Model objects are added for comparison. Note the capitalization of the Description and Id properties. Properties should always start with a capital letter.
 
P

Peter Duniho

Sounds like exactly what I need. But it's not working. Am I doing it
wrong?

It's hard to say whether you're doing it wrong, given that you didn't post
all of the code.

But it appears you have the correct general idea. Do make sure that
IModel has the properties you've assigned, of course, named exactly as the
strings you assign to the ComboBox properties..

Pete
 
C

Cralis

I have this:

public interface IModel
{
int id { get; set;}
string description { get;}
bool deleted { get; set;}
string manufacturer { get; set;}
string model { get; set;}
string edition { get; set;}
}

So it does seem my interface is OK. My part object does have : IPart.

I'm confused how you can do this:
models.Add(new Model("Show All"));
models.Add(new Model("Not Model Specific"));

How would it allow that? And if you can do this, can you not assign a
hard coded ID?
 
C

Cralis

To add to that, the ComboBox is being populated, and visually, is
correct. But then I select an item, I am saying:

private void PopulateList()
{
lvParts.Items.Clear();
List<IPart> parts;

if (cmbModels.SelectedIndex < 1) // Not the first 2 items
{
parts = doParts.GetListOfParts();
}
else
{
parts =
doParts.GetListOfParts(Convert.ToInt32(cmbModels.SelectedValue.ToString())); //
ERROR
}

On the line marked as //ERROR, it says: Object reference not set to
instance of an object.

Not sure why.
 
P

Peter Duniho

[...]
On the line marked as //ERROR, it says: Object reference not set to
instance of an object.

Not sure why.

You should debug it. You may find it useful to break that line into a
sequence of lines using local variables, so that it is easier to look at
each evaluation that occurs.

Obviously at some point you are trying to do something when something else
has returned null. I suspect SelectedValue is returning the null, but
there's no way to know for sure. You, however, have access to the code
and a debugger (I assume). It should not be difficult to find out what's
wrong.

I also agree with Morten that you should figure out a way to have "dummy"
IModel instances that correspond to "Show All" and "Not Model Specific".
Again, you are in the best position to determine how to do that.

Pete
 
G

GS

I was playing around with enum for a little while. I end up using Alex
Kolesnichenko, 2005 HumanReadable Attribute.cs form chap project
one caveat when you set the combobox box to his arraylist of
HumanReadablePair
you should also set
the displayMember to "HumanReadableName"


for example

in form_load


I have
ResourceManager resources =
new ResourceManager("RegexParse.Strings",
Assembly.GetExecutingAssembly()); // "RegexParse" is my namespace for the
project

// Get human-readable enum values
ArrayList regexCategories =

EnumToHumanReadableConverter.Convert(typeof(regexCategory), resources);
// note regexCategory is a **public** enum type iwthin the
class

// Bind controls to data
comboBoxRegexCategory.DataSource = (ICollection)regexCategories;
comboBoxRegexCategory.DisplayMember = "HumanReadableName";
comboBoxRegexCategory.SelectedItem = regexCategory.eSimple;

I don't pretend to understand why I need public scope for the enum to work
but it worked for me

I don't need coding classes per enum combo but I do have to either use
attributs on enum or enter the relevant info in Strings.resx


good luck

ref: Humanizing the Enumerations - The Code Project - C# Programming
you could even compile the HumanReadableAttribute.cs into a dll and shared
among your projects if you wish
 
M

Morten Wennevik [C# MVP]

To add to that, the ComboBox is being populated, and visually, is
correct. But then I select an item, I am saying:

private void PopulateList()
{
lvParts.Items.Clear();
List<IPart> parts;

if (cmbModels.SelectedIndex < 1) // Not the first 2 items
{
parts = doParts.GetListOfParts();
}
else
{
parts =
doParts.GetListOfParts(Convert.ToInt32(cmbModels.SelectedValue.ToString())); //
ERROR
}

On the line marked as //ERROR, it says: Object reference not set to
instance of an object.

Not sure why.

Cralis, did you read my reply? You are adding a mix of objects. Although the IModel objects do have the specified properties, a String object does not. You can't have different objects in the list if you want to use DisplayMember/ValueMember. Since the string object's description andid properties cannot be resolved, the ValueMember is ignored and all objects are displayed using object.ToString(). If you insist on mixing objects, then you need to use SelectedItem and cast the returned object toits proper type.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top