Hi,All.
My test application describes the problem I have encounter with. (I have attached it )
The application is a form containing an ultra grid bound to an ultra data source.1. I change data in a cell.2 Carriage retains in a cell.3. Then I click on the button 'Close' that has the following code in event handler: private void closeBtn_Click(object sender, EventArgs e) { Close(); }4. OnDataSourceCellDataUpdating is fired.5. Form does not close.(// In OnDataSourceCellDataUpdating I set e.Cancel in True specially to show that form in this case cannot be closed. But I want when an user clicks on 'Close' button Form closes anyway.
Do you have an idea what the problem could be? Thanks in advance.
The problem here seems to be the fact that your button's event handler is never actually being hit, the reason being that the ActiveCell of the grid is still in edit mode. When you try to click on the button, the grid must lose focus before a new control can take focus. As part of this operation, the grid is going to try to commit the change of the cell to the underlying data source; since this operation has failed, the grid doesn't leave edit mode. You might want to take a different approach, such as delaying committing anything to your database until you know that the user isn't closing the form.
-Matt
Matt,
Thanks, for your quickly answering my question.Yes, In debug mode I see that OnClick event handler is never fired if grid doesn't leave edit mode, to be more exact if e.Cancel is set to 'True' in OnDataSourceCellDataUpdating handler. But I hoped an UltraDataSource has any ability to know that something tries to close(dispose, etc) it from outside, like it happens when grid, placed on a form, being disposed during form closing(by clicking 'X' button). Actually I show my form(which I attached to this thread)as modal one from main application form to allow the user to setup some values and then save they to the database by clicking on 'OK' button. I use OnDataSourceCellDataUpdating event to prevent cell from updating and showing some warning message in the corresponding cases. But if user would not continue to work with that form he should have ability to close form regardless of whether grid is in edit mode or not.I found the solution that worked, but it seems it's not so good as I would like.1) I inherited from IMessageFilter and implemented PreFilterMessage(ref Message m) to know about clicking on 'Close' button. I store this fact in StorageForFormCloseActions.FormClosing Property.
public bool PreFilterMessage(ref Message m) { if (m.Msg == (int)WindowsMessages.WM_LBUTTONDOWN) { if (HWNDs.Contains(m.HWnd)) //HWNDs collection contains HWND of 'Close' button. { StorageForFormCloseActions.FormClosing = true;// Now I know that form needs to be closed. return false; } return false; } return false; }
2) On the OnFormLoad event handler of my dialog form I add this MessageFilter to application like this: Application.AddMessageFilter(MyMessageFilter);And also store Close Button's HWND to the corresponding collection.
On FormClosed event handler I removed this MessageFilter from application and reset StorageForFormCloseActions.Current.FormClosing to False.3) Since I stored the fact about clciking on the 'Close' button to bool property I can use that inOnDataSourceCellDataUpdating event handler: if (!StorageForFormCloseActions.Current.FormClosing)// If form is being closed there is no need to update cell's value. { .......... }else{ e.cancel = true; // Here we can close form. // I use BeginInvoke for Close() method to let controls perform its actions.}It would be nice to receive from you comments on this.Thanks in advance.Alex.
'
Alex,
As I mentioned there's no way for the UltraDataSource to know that you've clicked the button since, in fact, the button was never clicked and there is nothing to indicate that the form will be closing should the click processing be fully completed. What I had suggested was delaying performing the updates until a later time, such as if the user closes the dialog, which sesm to be what you're doing. What confuses me, however, is why you need to cancel updating the data source; are you passing off an instance of the UltraDataSource to your dialog and then this dialog is directly updating the one shared by the main form? If this is the case, I understand why you're cancelling the updates, but otherwise why bother preventing the cell from being updated if you have an OK button that will save everything that the user did?
I'm not sure what side effects implementing the IMessageFilter will have; it seems like it should work, but I don't know if there will be other implications to doing this (such as if, for whatever reason, the Handle needs to be recreated on the button and then this message filter no longer works). Personally, I would go with a different approach if you have an OK and Cancel button, since these should be what determine whether the data gets updated or not.