Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Self Sorting Listbox

Totally stumped by something that seems easy, and has been done to death... Yet still stumped.

What I want to do: I've got a WinForms ListBox. Its items are populated with objects, the DisplayMember is set. As the app runs, the data in the listed items might change, including the field behind the DisplayMember. I want the text displayed in the ListBox to change when this happens, and I also want the ListBox to re-sort itself so the items remain in alphabetical order.

A BindingList works fine to update the displayed text when the data changes, but for the life of me, I can't get it to sort.

I reviewed this: http://msdn.microsoft.com/en-us/library/ms993236.aspx

Plus numerous threads here about how to do this, but none of it seems to work for a ListBox.

Setting the Sorted property on the ListBox is similarly unhelpful.

What do I need to do to get a ListBox to sort itself?

like image 212
Jack Avatar asked Sep 20 '10 01:09

Jack


3 Answers

You can use a BindingSource object. Just drag-n-drop it into your form and point your ListBox.DataSource property to this BindingSource object. Then go to the BindingSource's properties and define Sort as you need.

Then in code you can set myBindingSource.DataSource = myCollection and voila, your listbox is populated and sorted. Easy.

like image 156
Alexey Raga Avatar answered Nov 20 '22 07:11

Alexey Raga


As with Patrol02's post, however you may want to try setting the DataSource to null and then reassigning it based on an event triggered by the list size changing. You could use the observer pattern on the collection, overriding the Add and Remove methods to notify watchers to rebind themselves.

like image 34
Antony Koch Avatar answered Nov 20 '22 07:11

Antony Koch


Resetting the DataSource will effectively sort the ListBox:

    listBox1.DataSource = null;
    listBox1.DataSource = myBindingList;
    listBox1.DisplayMember = "MyField";

But that's not automatic. As I understand, sorting should happen whenever the field behind the DisplayMember is updated, through an event or something like that...

See my complete test anyway:

public partial class Form1 : Form
{
    public BindingList<ABC> myBindingList = new BindingList<ABC>();

    public Form1() {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e) {
        myBindingList.Add(new ABC("zzz"));
        myBindingList.Add(new ABC("aaa"));
    }

    private void button2_Click(object sender, EventArgs e) {
        myBindingList[0].MyField = "ccc"; // was "zzz"
        myBindingList[1].MyField = "ddd"; // was "aaa"

        listBox1.DataSource = null;
        listBox1.DataSource = myBindingList;
        listBox1.DisplayMember = "MyField";
    }

    private void Form1_Load(object sender, EventArgs e) {
        listBox1.DataSource = myBindingList;
        listBox1.DisplayMember = "MyField";

    }
}

public class ABC  {
    public string MyField { get; set; } 
    public ABC(string val) {
        MyField = val;
    }
}
like image 1
Gabriel Avatar answered Nov 20 '22 06:11

Gabriel