panjo
panjo

Reputation: 3515

How to refresh DataSource of a ListBox

Form has one Combobox and one ListBox. When the "Add" button is clicked, I want to add the selected item from the ComboBox to the ListBox.

public partial class MyForm:Form
{
    List<MyData> data = new List<MyData>();
    private void ShowData()
    {
       listBox1.DataSource = data;
       listBox1.DisplayMember = "Name";
       listBox1.ValueMember = "Id";
    }

    private void buttonAddData_Click(object sender, EventArgs e)
    {
       var selection = (MyData)comboBox1.SelectedItem;
       data.Add(selection);
       ShowData();
    }
}

With this example, the selected item is replaced with the new selection inside ListBox. I need to add the item to the list.

What is wrong with my code?

Upvotes: 58

Views: 117655

Answers (7)

Pixel_95
Pixel_95

Reputation: 984

refreshing also works via

listbox.ItemsSource = null;
listbox.ItemsSource = data;

Upvotes: 0

TheKingArthas
TheKingArthas

Reputation: 11

Maybe this solution has not the better performance, but after many tries and a few hours it was what it worked for me:

This line was executed on the form constructor:

listBox1.DataSource = myData;

This lines were executed after the information was modified:
listBox1.DataSource = new List<Movil>();
listBox1.DataSource = myData;

Hope it helps!

Upvotes: 0

rajeemcariazo
rajeemcariazo

Reputation: 2524

The listbox didn't detect that you have changed the DataSource. It will only refresh when Datasource has changed, so set DataSource to null first:

listBox1.DataSource = null;
listBox1.DataSource = data;

You could also clear the items then set the DataSource again:

listBox1.Items.Clear();
listBox1.DataSource = data;

Upvotes: 20

dwonisch
dwonisch

Reputation: 5785

listbox1.DataSource property looks for value changes but by assigning the same list all the time the value won't really change.

You can use a BindingList<T>, instead of your List<T>, to automatically recognize new items added. Your ShowData() method must be called once at startup.

public partial class MyForm:Form
{
    public MyForm(){
        InitializeComponent();
        ShowData();
    }

    BindingList<MyData> data = new BindingList<MyData>();

    private void ShowData()
    {
       listBox1.DataSource = data;
       listBox1.DisplayMember = "Name";
       listBox1.ValueMember = "Id";
    }

    private void buttonAddData_Click(object sender, EventArgs e)
    {
       var selection = (MyData)comboBox1.SelectedItem;
       data.Add(selection);
    }
}

Upvotes: 87

Frank Odoom
Frank Odoom

Reputation: 1566

Call ShowData() when the form initializes to populate your listbox on initialization

 public Department()
        {
            InitializeComponent();
            ShowData();
        }

ShowData() Method, where BindingSource, DisplayMember and ValueMember are set

private void ShowData()
            {
                using (var uow = new UnitOfWork(new SellContext()))
                {
                    listBox1.DataSource = uow.Departments.GetAll().ToList();
                    listBox1.DisplayMember = "DepartmentName";
                    listBox1.ValueMember = "DepartmentId"; 
                    //listBox1.Invalidate();       
                }
            }

In the implementation below when a department is deleted from database the listbox refreshes with the current collection

private void button1_Click(object sender, EventArgs e)
    {
        try {
            using (var uow = new UnitOfWork(new SellContext()))
            {
                int count = uow.Departments.FindDepartmentByName(txtDeptName.Text.ToString());
                if (count>0)
                {
                    MessageBox.Show("This Department Already Exists", "SellRight", MessageBoxButtons.OK, MessageBoxIcon.Hand);
                }

                else
                {
                    department dept = new department();
                    dept.DepartmentName = txtDeptName.Text.ToString();
                    uow.Departments.Create(dept);
                    if (uow.Complete() > 0)
                    {           
                        MessageBox.Show("New Department Created", "SellRight", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        txtDeptName.Text = "";
                        ShowData();      
                    }
                    else
                    {
                        MessageBox.Show("Unable to add Department", "SellRight", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        txtDeptName.Text = "";
                        ShowData();
                    }
                }
            }                              
        }
        catch(Exception ex)
        {
            ex.ToString();
        }
    }

Upvotes: 0

jduncanator
jduncanator

Reputation: 2194

Alternatively and probably the most correct way to implement this is to use the provided ObservableCollection<T>. It is designed with the sole purpose of implementing INotifyCollectionChanged.

public partial class MyForm : Form
{
    ObservableCollection<MyData> data = new ObservableCollection<MyData>();

    public MyForm()
    {
        listBox1.DataSource = data;
        listBox1.DisplayMember = "Name";
        listBox1.ValueMember = "Id";
    }

    private void buttonAddData_Click(object sender, EventArgs e)
    {
       var selection = (MyData)comboBox1.SelectedItem;
       data.Add(selection);
    }
}

Because ObservableCollection<T> implements INotifyCollectionChanged the DataSource binding will automatically update the ListBox whenever your data changes.

Upvotes: 2

gzaxx
gzaxx

Reputation: 17590

I would suggest to use BindingSource as it would properly update connected controls.

public partial class MyForm : Form
{
    List<MyData> data = new List<MyData>();
    BindingSource bs = new BindingSource();

    public MyForm()
    {
        IntializeComponents();
        bs.DataSource = data;

       listBox1.DisplayMember = "Name";
       listBox1.ValueMember = "Id";
       listBox1.DataSource = bs;
    }

    private void buttonAddData_Click(object sender, EventArgs e)
    {
       var selection = (MyData)comboBox1.SelectedItem;
       data.Add(selection);

       bs.ResetBindings(false);
    }
}

Changing controls data source on fly produces strange result sometime.

Upvotes: 37

Related Questions