Original Reporter info from Mantis: giovanni.seara
Reporter name: Giovanni Seara
Description:
When editing the DataSet is started through a DBComboBox and in the BeforeEdit an exception is raised, the application automatically closes.
The error occurs because running the EditingDone method is called UpdateRecord where the DataSet state is required to be in write mode. The DataSet state is modified for navigation because the edit is canceled because of the exception in BeforeEdit.
Steps to reproduce:
1 - Implement BeforeEdit of the DataSet to raise an exception.
2 - Keep the DataSet state in navigation.
3 - Initialize the registry editing through the DBComboBox drop-down menu.
I don't fully understand the description. But it seems to me that you are concerned that the program dies without showing an exception dialog. This is different from a TDBEdit which does show an exception dialog. But it dies, too...
I must confess that I don't know how exceptions are handled by the db controls. But usually it is recommended to call "Abort" instead of raising an exception.
So, if you modify the OnBeforeEdit handler to call Abort the program will show a proper message that the dataset is not in edit state, and the program will NOT terminate.
In my case, I need to do a validation on BeforeEdit.
As in the example below:
procedureTForm1.Dataset1BeforeEdit(DataSet:TDataSet);beginifnot(CheckIfCanEdit)thenraiseException.Create('You can not edit.');end;
In this condition, if the user uses the DBComboBox, the application closes.
I have analyzed the DBComboEdit code.
And I came up with the following solution, changing the customdbcombobox.inc file
procedureTCustomDBComboBox.EditingDone;begin{**** Begin ****}ifFDatalink.EditingthenbeginFDataLink.UpdateRecord;inheritedEditingDone;endelseFDatalink.Reset;{**** End ****}end;
Raising an exception will work but it's not recommended. In linux/gtk2 typing something in a dbcombobox that has some text selected will generate two changed events, one for deleting the selected text and one for the typed text. This means two consecutive dialogs that the user will see without apparent reason. If you want still to show a message dialog, raise an EAbort exception and do something like this:
procedureTForm1.NotifyException(Data:PtrInt);beginFNotifyException:=false;ShowMessage('Exception on Edit');end;procedureTForm1.BufDataset1BeforeEdit(DataSet:TDataSet);beginifnotFNotifyExceptionthenbeginFNotifyException:=true;Application.QueueAsyncCall(@NotifyException,0);end;raiseEAbort.Create('bad edit');end;
This fix in r58686 breaks TDBLookupCombobox in unbound mode.
Run attached demo containing a dblookupcombo having no datasource attached. Up to r58685 (incl) it was possible to select an item from the combo, and it remained visible when the dropdown has closed. After r58686 the selected item appears shortly but disappears again after the combo dropdown has closed.
It also breaks #30587 (closed), #33160 (closed) and probably many more fixes that have been done for the DBCombos recently.
wp I tested 30587 and 33160 without problems can you please amend the bug reports and add any extra information so I can reproduce the bugs?, I couldn't try the remaining "many more fixes" a listing with bugs numbers would be needed.
Sorry, my phrase of "many more fixes" probably is an exaggeration, written in memory of several closely related bugs that when I fixed one I broke another one.
Essentially there were three topics:
(1) Mousewheel scrolling of the items of a non-focused DBCombo (#30587 (closed))
(2) Unbound mode of TDBLookupCombobox (mailing list discussion)
(3) Automatic switching to edit mode when an item in a DBCombo is selected (#33160 (closed))
Your new fix solves these three. There is a regression, though, related to (3): Run the attached modified demo of #33160 (closed) with Laz 1.8.4. Select a different item in the combo. The new value is displayed immediately in the grid while the dataset is still in edit mode (see status display in form caption, and you still can press ESC to restore the original value).
Now do the same with Laz trunk. When a different item is selected the dataset goes to edit mode, too, but the new value is not displayed in the grid. You must press ENTER to display the value (the dataset remains in edit mode after the ENTER which is fine).
I don't know whether the old or new behavior is correct, though. The new behavior resembles that of a TEdit where you also type the new text and press ENTER to update the grid (which did not work in 1.8.4 BTW).
About the mentioned regression, it is indeed a fix because otherwise the change would not be cancelable which was a misbehavior in the previous implementation. Moreover it works the same way in Delphi.
To be exact: In the old implementation, selecting a dbcombobox item could still be canceled by pressing Cancel on the dbnavigator because the dataset was still in edit mode. And the new implementation is not exactly compatible with Delphi in which the grid is not updated even when ENTER is pressed after selecting a combobox item.
But in total, I think that the new behavior is more consistent than the old one. Therefore, you can resolve the issue as "fixed".
"To be exact: In the old implementation, selecting a dbcombobox item could still be canceled by pressing Cancel on the dbnavigator because the dataset was still in edit mode."
Yes, but the problem is that the value selected in the combo was prematurely propagated to the record and it appeared in some hypothetical linked grid, so, even if you press ESC in the combo, incorrectly, it won't be undone in the grid. I tested and fixed that specific situation in the old behavior. The fact that it can still be undone in some dbnavigator doesn't make it right as no all programs require one dbnagivator, or grid :) and that without taking into count that it will undone the changes in all yet-to-be posted changes in all other fields not just the one in the linked to the combo.
"And the new implementation is not exactly compatible with Delphi in which the grid is not updated even when ENTER is pressed after selecting a combobox item."
Originally I misread this paragraph, yes this behavior is indeed something we have different than Delphi, the reason is that Delphi doesn't have the EditingDone functionality. In Lazarus this is triggered by the ENTER key and it's supposed to work as if the control changed the focus. So it's expected that the record should get updated and it's compatible with Lazarus. Maybe we could review this behavior for some combobox styles for example it probably makes more sense for csDropDown than for csDropDownList, if desired please submit a bug report.