-2

I have a windows form app and a there is a combobox, which is filled from a txt file.

        List<string> lines = System.IO.File.ReadLines(path).ToList();

        foreach (string l in lines)
        {
            combobox.Items.Add(l);
        }

As a result of a button, i would like to change the path. Is it possible? I changed the path but nothing happened, i think because i need to call the constructor again, but the button is in a different window, the combobox is in another window.

  • If you change variable named `path` in your program, then nothing will happen, because your combo box is not binded to any datasource, and you dont reload data source by changing the path only. If you want to load items to combo box, you can definie `Click` event of a button. Inside you can ask user for path, or just change it the way you want. Then you need to call `combobox.Items.Clear()` to remove all existing items in combo box. And then you have to load it again with new path, but not only by changing path variable, but run the attached code again. – Bartosz Olchowik Apr 26 '22 at 07:42
  • 1
    Don't add the items in a loop. Populate the list and then bind that to the control. Any changes to the bound list will then be reflected in the control. Even then, the control won't visually refresh unless you use the right type of list. Either bind via a `BindingSource` and then call the appropriate method to refresh or else use a `BindingList` and it will refresh automatically. – John Apr 26 '22 at 07:57

3 Answers3

0

You can create a method that takes a path to your txt file as a parameter. Then you can call that method on Form_Load and Button_Click with different paths.

    private void Form1_Load(object sender, EventArgs e)
    {
        populateCombo(path);
    }

    private void populateCombo(string path)
    {
        comboBox1.Items.Clear();
        List<string> lines = System.IO.File.ReadLines(path).ToList();

        foreach (string line in lines)
        {
            comboBox1.Items.Add(line);
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        populateCombo(differentPath);
    }
0

Even though you have selected an answer, as mentioned by john a better path is to use a BindingList. In the code below a custom BindingList is used to provide a single method to add items to the current data which keeps your code clean. You can use a standard BindingList, for the second load use a foreach to append data.

There are two buttons, first to load from a text file and in turn load the ComboBox for the first time, second button appends to the data. Both use hard coded file names, that you can easily change.

Place the following in a class file in your project.

Source

public class BindingListSpecial<I> : BindingList<I>
{
    private readonly List<I> _baseList;

    public BindingListSpecial() : this(new List<I>()) { }

    public BindingListSpecial(List<I> baseList) : base(baseList)
    {
        _baseList = baseList ?? throw new ArgumentNullException();
    }

    public void AddRange(IEnumerable<I> vals)
    {
        if (vals is ICollection<I> collection)
        {
            int requiredCapacity = Count + collection.Count;
            if (requiredCapacity > _baseList.Capacity)
                _baseList.Capacity = requiredCapacity;
        }

        bool restore = RaiseListChangedEvents;
        try
        {
            RaiseListChangedEvents = false;
            foreach (I v in vals)
                Add(v); // We cant call _baseList.Add, otherwise Events wont get hooked.
        }
        finally
        {
            RaiseListChangedEvents = restore;
            if (RaiseListChangedEvents)
                ResetBindings();
        }
    }
}

Form code

public partial class Form1 : Form
{
    private BindingListSpecial<string> _bindingList;
    public Form1()
    {
        InitializeComponent();
    }

    private void LoadButton1_Click(object sender, EventArgs e)
    {
        _bindingList = new BindingListSpecial<string>(File.ReadAllLines("TextFile1.txt").ToList());
        comboBox1.DataSource = _bindingList;
    }
    private void LoadButton2_Click(object sender, EventArgs e)
    {
        _bindingList.AddRange(File.ReadAllLines("TextFile2.txt").ToList());
    }
}
Karen Payne
  • 4,341
  • 2
  • 14
  • 31
0

There's a more little and simple solution rather than clearing and adding items. You can use the DataSource property instead of doing this. But you must use an array instead of a list. Or either it won't work. You can use ReadAllLines(string) instead of ReadLines(string).

Also read this reference.

private void Form1_Load(object sender, EventArgs e)
{
    populateCombo(path);
}

private void populateCombo(string path)
{
    comboBox1.DataSource = System.IO.File.ReadAllLines(path);
}

private void button1_Click(object sender, EventArgs e)
{
    populateCombo(differentPath);
}