I don't understand why this can happen. I have a DataGridView whose DataSource is set to a BindingSource (for filtering and navigating purpose).
myDataGridView.DataSource = myBindingSource;
I have a list of items, Clicking on 1 item will apply a corresponding filter for myBindingSource and in result show only rows which meet the criteria on myDataGridView. Like this:
private void ItemsClicked(object sender, ItemClickedEventArgs e){
myBindingSource.Filter = e.FilterExpression;
}
That works OK when I click on items which make myDataGridView show at least 1 row. But the thing becomes bad when I click on any item which result to 0 rows meeting the corresponding filter expression. The myDataGridView should be empty normally but it throws a lot of exceptions in some dialogs (appeared consequently) (the exceptions are not shown in the code editor window in yellow marker), here is a snapshot of the error dialog:
After clicking the OK button, it still shows me another (the same one) dialog, .... it continues showing many dialogs (which have the same message) until it stops all. I can't understand what that is. I don't know if you need more info but I hope you have experienced a similar kind of exception and give me some suggestion on how to fix this. The dialog says about DataError event, but I don't understand why there is any error here? Please notice that all the Filter will be OK if there at least 1 row in my dataGridView after applying the filter, the error happens only when there is no row after the filter.
Please help me out, Thank you very much in advance!
Here is my answer, I don't really understand this but I've just tried and it works like a charm.
My rule is:
Before applying the filter, just SuspendBinding all controls from the BindingSource using SuspendBinding()
method like this:
myBindingSource.SuspendBinding();
Now, just apply the filter normally like this:
myBindingSource.Filter = "filter expression";
Lastly, using ResumeBinding()
method to re-bind all controls to the BindingSource like this:
myBindingSource.ResumeBinding();
And that's all. In fact myBindingSource has many controls which are bound to it. Maybe it's the reason but I still don't understand it well. I bet if the myBindingSource has only myDataGridView which it binds data to, there won't no need for all 3 steps above, just apply the filter (step 2) right when you need.
I hope this helps others which have encountered, are encountering and will encounter this problem. Again, I don't really understand why it works, and so I hope someone can explain it in a comment. I would really appreciate it. Thanks!
I've found that doing as I described above may have another problem in some case, the safest solution is:
SuspendBinding (as the above description, this is done using the method SuspendBinding() method of BindingSource), but the safest way is to set your DataSource to null.
Apply filter.
ResumeBinding (as the above description, this is done using the method ResumeBinding() of BindingSource), but the safest way is to rebind your control yourself (loop through each control and call Add method of DataBindings, remember to clear DataBindings first). You should have a method for doing this, because we may call to the re-bind method for many times.
And now I'm using this safer way, the way I mentioned before gave me another exception called "VersionNotFoundException" (There is no proposed data to access). The exception occurs at the line of ResumeBinding() call, there must some bug in that method. However I'm using a DataSet of multi-tables and switch between the tables on the same dataGridView. Again, this problem is still too complicated to dig into and understand at once.
I've found that there is no need to suspend binding all controls before applying filter and resume bindings after that. My form has a control which is bound to a special column of the BindingSource (let's call it Column X), I still don't know why this column is special, I just doubt at it and just suspend binding it from BindingSource before applying the filter and bind it again after that. All other controls/columns are not involved.
The only thing I consider as noticeable here is:
=> My main table (Table 1) has a primary key column called A, this table has a foreign key called B which refers to the primary key column in another table (Table 2). The Table 2 has a foreign key which refers to the primary key column called C of another table (Table 3). And in fact, I had a query selecting all columns A, B, C (of course there are others not mentioned here). This relation is what I doubted at, but still unclear to me why and how it could raise error. If not using binding and assign/update all values manually, there would not any error. Binding is something sometimes really complicated.