views:

586

answers:

2

Hi,

I'm trying to figure out how data binding with BindingSource is supposed to work I want a DataGridView to be populated with the content of a List<> upon update of the list.

I can see the List grow and verify it's being filled when I check the debugger. I thought the BindingSource would fire an event when the List is changed. But none of the available is fired. How do I become notified when the underlying list is changed?

I follow the instructions and have the following test code:

    Data d;
    BindingSource bs;

    public Form1()
    {
        InitializeComponent();
        bs = new BindingSource();
        d = new Data();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        bs.DataSourceChanged += new EventHandler(bs_DataSourceChanged);
        bs.ListChanged += new ListChangedEventHandler(bs_ListChanged);
        bs.DataMemberChanged += new EventHandler(bs_DataMemberChanged);
        bs.CurrentChanged += new EventHandler(bs_CurrentChanged);
        bs.CurrentItemChanged += new EventHandler(bs_CurrentItemChanged);

        bs.DataSource = d.list;
        dataGridView1.DataSource = bs;
    }
    // ... all the handling methods caught with a break point in VS.

    private void button1_Click(object sender, EventArgs e)
    {
        d.addOneItem();
    }
+1  A: 

If you want to get notified when a property get's changed you'll need to implement INotifyPropertyChanged

See here for an example.

Mez
It wouldn't work with List<>, as Marc Gravell stated. So I'm following the approach with BindingList.
rdoubleui
+2  A: 

List<T> doesn't support change events; BindingList<T> would be a good substitute to support this scenario, and it also supports item-level change events if your type T implements INotifyPropertyChanged.

In 3.0 and above, there is also ObservableCollection<T>, which acts similarly to BindingList<T>. It all comes down to interfaces such as IBindingList, IBindingListView, etc.


From comments; for a 2.0/3.0 example of adding a Find to BindingList<T>:

public class MyBindingList<T> : BindingList<T>
{
    public T Find(Predicate<T> predicate)
    {
        if (predicate == null) throw new ArgumentNullException("predicate");
        foreach (T item in this)
        {
            if (predicate(item)) return item;
        }
        return default(T);
    }
}

Note that in 3.5 (or in .NET 2.0/3.0 with LINQBridge and C# 3.0) you don't need this - any of the LINQ extension methods would do the same thing.

Marc Gravell
This works, thanks, however with BindingList I don't have a compare method, to which I could pass a predicate (which I found extremely useful). I was using that to prevent duplicates in the List... Will I get around looping through the list checking the existence by a object property?
rdoubleui
You could use LINQ, which would work fine. Or subclass `BindingList<T>` and add some missing methods (very easy to do - let me know if you want to see how to do this with a predicate).
Marc Gravell
I'd like to know how to solve that with an own predicate.
rdoubleui