sdrest
sdrest

Reputation: 35

Winforms how to set combobox Selectedindex with datasource?

I have a class like

public example class {
    public string Name {get; set;}
    public object A {get; set;}
    public object B {get; set;}
    ....
}

I have a list of examples, and I want to bind the list to a combobox and show by its name.

var examples= new List<example>(){ exampleA, exampleB ,exampleC};
comboBox_ExampleSelect.DataSource = examples;
comboBox_ExampleSelect.DisplayMember = "Name";

when user choose the item in combobox, I can get the selected object

var selectedExample = comboBox_ExampleSelect.SelectedItem;

but when I try to set SelectedItem/SelectedIndex by code, it can't work. I found that the itemsCollection of combobox is null How do I do?

Update 12/22 I found it might be timing issue. I create combobox manualy. It work if I assign datasource after add combobox to main form. Is it necessary?

sample code as follow

   public List<Example> _examples = new List<Example>();

   public class GUIBox
   {
       public ComboBox ExampleChooseComboBox;

       public GUIBox()
       {
           ExampleChooseComboBox = new ComboBox()
           {
               Location = new Point(10, 10),
               Name = "comboBox1",
               Size = new Size(100, 20),
               FormattingEnabled = true
           };
       }

       public void AssignList(List<Example> example)
       {
           ExampleChooseComboBox.DataSource = new List<Example>(example);
           ExampleChooseComboBox.DisplayMember = "Name";

           ExampleChooseComboBox.SelectedIndex = 0;
       }
   }
   public Form1()
   {

       InitializeComponent();

       _examples = new List<Example>()
       {
           new Example() {Id = "1", Name = "Example1"},
           new Example() {Id = "2", Name = "Example2"},
       };

       var gui = new GUIBox();
       
       
       //gui.AssignList(_examples); ======> fail here

       this.Controls.Add(gui.ExampleChooseComboBox);

       gui.AssignList(_examples);  //======> works here
   }

Upvotes: 0

Views: 113

Answers (2)

Karen Payne
Karen Payne

Reputation: 5117

Usually its common to select an item by the value shown in the ComboBox. Below FindString is used to find an item by the property Name. If say (keeping with the class I'm using) you want to find by Id let me know.

Note, .DisplayMember is not set, ToString value is used as .DisplayMember.

public partial class StackoverflowForm : Form
{
    public StackoverflowForm()
    {
        InitializeComponent();

        List<Item> list =
        [
            new Item() { Id = 1, Name = "One" },
            new Item() { Id = 2, Name = "Two" },
            new Item() { Id = 3, Name = "Three"}
        ];

        comboBox1.DataSource = list;

        var xx = list.Select((item, indexer) => 
            new { Item = item, Index = indexer }).ToList();
        var selected = xx.FirstOrDefault(x => x.Item.Id == 2);
        if (selected is not null)
        {
            comboBox1.SelectedIndex = selected.Index;
        }

    }

    private void SelectedItemButton_Click(object sender, EventArgs e)
    {
        Item item = comboBox1.SelectedItem as Item;
        MessageBox.Show($"Id: {item!.Id} - {item.Name}");
    }
}

public class Item
{
    public int Id { get; set; }
    public string Name { get; set; }
    public override string ToString() => Name;
}

Upvotes: 0

IV.
IV.

Reputation: 9243

Your question states:

I try to set SelectedItem/SelectedIndex by code, it can't work.

The intent of the code you posted seems to be making a list of objects of Example class and binding that list to a combo box. Your code is assigning items instead of examples however, and we have to assume the worst about what items might be because it's not shown. If you were to follow through with assigning the examples collection you should be able to set the combo box as you say by either SelectedItem or SelectedIndex. Here's some code where I tested it both ways.

public partial class MainForm : Form
{
    public MainForm() => InitializeComponent();
    protected override async void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        Example 
            exampleA = new Example(),
            exampleB = new Example(), 
            exampleC = new Example();

        var examples = new List<Example> 
        {
            exampleA,
            exampleB,
            exampleC,
        };

        comboBox.DataSource = examples;
        comboBox.DisplayMember = "Name";

        await localCycleWaitCursor();

        // Select exampleB programmatically from index
        comboBox.SelectedIndex = 1;

        await localCycleWaitCursor();

        // Select exampleC programmatically from Example object
        comboBox.SelectedItem = exampleC;


        async Task localCycleWaitCursor()
        {
            await Task.Delay(TimeSpan.FromSeconds(2));
            Cursor.Position = PointToScreen(new Point(20, 30));
            Cursor = Cursors.WaitCursor;
            await Task.Delay(TimeSpan.FromSeconds(1));
            Cursor = Cursors.Default;
        }
    }
}

Example class

class Example
{
    public Example() => _genID++;

    private static char _genID = 'A';
    public string Name { get; set; } = $"Example {_genID}";
    public object A { get; set; } = $"Object-A-{_genID}";
    public string B { get; set; } = $"Object-B-{_genID}";
}

Upvotes: 0

Related Questions