Click here to Skip to main content
15,886,693 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi all,

I have a listBox items string collection like:

Virtual Serial Port (COM1->COM2) COM1
Virtual Serial Port (COM2->COM1) COM2
USB-Serial device COM3

I want to select an item index using: a string like COM1.

I can not use:
C#
int index = listBox1.FindString(Com1);

because Com1 can appear more than one item.

I have a solution, but I want to make it more simple.
This is what I used:
C#
private void loadSettings()
      {
          if(!string.IsNullOrEmpty(settings.LastPort))
          {
              FindMyString( settings.LastPort);
             if(listBox1.SelectedIndex > -1) buttonOpenPort.PerformClick();
          }
      }

      private void FindMyString(string searchString)
      {
          // Ensure we have a proper string to search for.
          if (searchString != string.Empty)
          {
              List<string> ListBox1Coll = new List<string>();
              foreach (string S in listBox1.Items)
              {
                  string resultremove;
                  string result;
                  if (S.Length > 5) resultremove = S.Remove(0, S.Length - 5);
                  else if (S.Length > 4) resultremove = S.Remove(0, S.Length - 4);
                  else if (S.Length > 3) resultremove = S.Remove(0, S.Length - 3);
                  else resultremove = S;
                  result = resultremove.Substring(resultremove.IndexOf('C'));
                  ListBox1Coll.Add(result.Trim(new char[] { '"' }));
              }

              int index;
              for (int i = 0; i < ListBox1Coll.Count; i++)
              {
                  if (ListBox1Coll[i] == searchString)
                  {
                      index = i;
                      if (index != -1)
                          listBox1.SetSelected(index, true);
                      break;
                  }
              }
          }
      }
Posted
Updated 26-Apr-14 7:44am
v3
Comments
[no name] 26-Apr-14 14:22pm    
If your strings are all in that same format, why can't you simply take the last character of the string? A '1' would tell you it's COM1, a '2' COM2, etc. Or if that doesn't work for you, get the LastIndex of the space character and SubString the rest of the string to the end giving you the COMx string.
GrooverFromHolland 26-Apr-14 16:02pm    
Hi Wes,
You gave me the idea, the last characters of my string are always numbers with a maximum of 255.
I can filter on that.

The listbox item collection can be any type of object, including String, and by default will display the result of obj.ToString();

Now the clever thing is that if a collection is bound via the listbox's DataSource property then the listbox display and the listbox value can be different. The display is governed by the DisplayMember property and the value (returned by SelectedValue) by the ValueMember property.

1) Define a simple class containing two string properties, one for display and one for value.
C#
public sealed class ListBoxItem {
  private String displayField;
  private String valueField;

  public ListBoxItem(String displayString, String valueString) {
    DisplayString = displayString;
    ValueString = valueString;
  }

  public String DisplayString {
    get { return displayField; }
    set { displayField = value; }
  }


  public String ValueString {
    get { return valueField; }
    set { valueField = value; }
  }
}



2) Setup the listbox with a collection of ListBoxItem objects as the DataSource
private void SetupListBox() {
  List<ListBoxItem> myItems = new List<ListBoxItem>();
  myItems.Add(new ListBoxItem("qwerty COMX..COMY", "COM2"));
  myItems.Add(new ListBoxItem("Unreliable COM adapter", "COM5"));
  myItems.Add(new ListBoxItem("Onboard COM", "COM1"));
  // Select DisplayMember and ValueMember with property names from the ListBoxItem class
  lbx.DisplayMember = "DisplayString";
  lbx.ValueMember = "ValueString";
  lbx.DataSource = myItems;
  lbx.SelectedValueChanged += new EventHandler(SelectedValueChanged);
  LoadSettings();
}

private void LoadSettings() {
   // Selecting the item with Value "COM1" will highlight "Onboard COM"
   // and fire SelectedValueChanged
  lbx.SelectedValue = "COM1";
}

private void SelectedValueChanged(object sender, EventArgs e) {
// SelectedValues are ListBoxItem.ValueString
  if (lbx.SelectedValue != null) {
    Debug.Print("Selected port is {0}", lbx.SelectedValue);
  } else {
    Debug.Print("Null - nothing selected");
  }
}


It's a bit of work to setup but gives complete separation of display and value. If SelectedValue is assigned a value which is not in the collection then the highlight is removed and SelectedValue will return null.

Alan.
 
Share this answer
 
Comments
BillWoodruff 27-Apr-14 1:29am    
+5 An excellent answer !
GrooverFromHolland 27-Apr-14 7:27am    
Hi Alan,

I never new there was a difference between value member and display member. This is very useful, not only for me but for many others.
In my original code I already have the two different Arrays with valueStrings, like this:
for (int i = 0; i < ComPortInformation.Count; i++)
{
listBox1.Items.Add(ComPortInformation[i].friendlyName +
" " + ComPortInformation[i].portName);
}

so implementing this is easy.

Thank You very much, answer accepted and a +5!

Groover
Alan N 27-Apr-14 9:07am    
I'm glad that helped. I figured this out a few years ago and can now understand what the Microsoft documentation means.

By the way keep the properties in the helper class public otherwise the names will not be recognised.
As long as your ListBox Items have some sub-string that's unique, you can make finding their indexes easy:
C#
private int getListItemIndex(string match)
{
    int ndx = -1;

    foreach (string s in listBox1.Items)
    {
        if (s.Contains(match))
        {
            ndx = listBox1.Items.IndexOf(s);
            break;
        }
    }

    return ndx;
}
Here each of your Items has the unique string space+COM+integer:
C#
private void sampleTest()
{
    int ndx = getListItemIndex(" COM1");

    switch (ndx)
    {
        case -1:
            // handle no match
            break;
        case 0:
            // handle Item 0
            break;
        case 1:
            // handle Item 1
            break;
        case 2:
            // handle Item 2
            break;
    }
}
Obviously, this type of solution depends on an identifiable regular pattern.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900