DataGridView NullReferenceException on InitializeEditingControlValue after losing focus
I have a DataGridView bound to a List[of Parts]. The last item in the list is always a 'dummy part', which is there to create an extra row in the grid so the user can start typing into the first cell to add a part to the list. As soon as the user types more than x characters into that particular cell, a new DataGridView with search results appears under the cell where he is typing (a bit look Google's suggestions), and he can select one of the matches to add the part to the list.
I do this by handling the EditControlShowing event, which assigns the 'editing control' to a TextBox开发者_开发问答 variable which has a handler for TextChanged.
The bug:
I want the focus to change to the second DataGridView (search results) if the user hits the down arrow key. The EditControlShowing handler works fine first time, moving the focus to the second DataGridView and leaves the first DataGridView in a 'seemingly' functional state, i.e. all other event handlers work. But the second time the EditControlShowing handler fires, the DataGridView throws the NullReferenceException on InitializeEditingControlValue. Because it is the DataGridView's own call which throw the error, the debugger brings me to "Application.Run" in my code, which isn't helpful. However, I determined that the call which causes the DataGridView to go into that state, and the point at which exception is thrown, is when I steal focus from the first DataGridView by calling Focus() on the second DataGridView (or any other control for that matter). If however I let the user change focus to the DataGridView (e.g. by clicking with the mouse), then the DataGridView stays fine.
Does anyone know why stealing focus away from a DataGridView during a handler for EditControlShowing should result in it behaving differently afterwards?
I've tried CancelEdit, Refresh, Enable/Disable etc...
Any suggestions on helping me find out what is going on within the DataGridView? I can't spot anything obvious by inspecting it at breakpoints before and after. I don't even know how to find out what object is null as its the DataGridView's own code...
Many thanks.
OK, I resolved this using BeginInvoke in the TextChanged event handler (code is in Boo but should make sense):
//The event handler
private def CellAsTextBoxTextChanged(sender as object, e as EventArgs):
...
self.BeginInvoke(ShowPartSelectionArea, currentCell, _CellAsTextBox.Text)
//The method which amongst other things, sets the focus to another control
private def ShowPartSelectionArea(currentCell as DataGridViewCell, searchString as string):
...
AnotherDataGridView.Focus()
...
I had previously tried using BeginInvoke directly at the point of calling Focus() on the other control, like so:
private def CellAsTextBoxTextChanged(sender as object, e as EventArgs):
...
ShowPartSelectionArea(currentCell, _CellAsTextBox.Text)
private def ShowPartSelectionArea(currentCell as DataGridViewCell, searchString as string):
...
self.BeginInvoke(AnotherDataGridView.Focus())
...
But the latter didn't work, perhaps because the first way actually allows the DataGridView's cell to finish everything it does whereas the second way doesn't.
So for anyone facing the same problem, I'd advise playing about with where in the call stack you use BeginInvoke.
精彩评论