C# – Winforms DataBinding vs PropertyChanged Event Ordering Issue

cdata-bindingeventswinforms

I'm sorry if this has been asked before, but I did try digging through the multitude of DataBinding questions available and couldn't find one that matched my problem.

I'm doing a unidirectional databinding between a listbox index and some property on one of my entities, but I also need to run some additional logic after the databinding takes place. I tried doing it like this:

listBox.DataBindings.Add("SelectedIndex", entity, "Property", true, DataSourceUpdateMode.OnPropertyChanged);
listBox.SelectedIndexChanged += (s,e) => view.Refresh();

The problem is that the event handler runs before the databinding updates, but view.Refresh() depends on the value of entity.Property being updated. This results in my view not being refreshed until the the next time I change my index.

Is there any way to solve this with databinding? At the moment I've resorted to not using databinding whenever I have this scenario, and doing it manually instead:

listBox.SelectedIndex = entity.Property;
listBox.SelectedIndexChanged += OnIndexChanged;

private void OnIndexChanged(object sender, EventArgs e)
{
    entity.Property = listBox.SelectedIndex;
    view.Refresh();
}

But I'd prefer to avoid this since I'm using databinding for everything else and would like to keep consistency.


Update

I've found the solution. It looks like the Binding object itself holds BindingComplete event which is perfect for this. And since the DataBindings.Add method returns me the Binding object I can chain both together. My code therefore becomes:

listBox.DataBindings.Add("SelectedIndex", entity, "Property", true, DataSourceUpdateMode.OnPropertyChanged).BindingComplete += (s,e) => view.Refresh();

My only question now is if need to take care of unregistering this event manually, or if I can just call listBox.DataBindings.Clear(); and be done with it.

Best Answer

The method you're using returns an instance of a Binding. Why not listen to the BindingComplete event of the returned binding and call the Refresh method from there? The code will probably need to evaluate fields such as BindingCompleteContext and Exception to ensure the event is being triggered on a datasource change. You don't need to call listBox.DataBindings.Clear(). The bindings get removed when the control is disposed. You usually don't need to manually unregister the event, and I think in you're case, you don't need to manually unregister the event.