views:

1442

answers:

2

I have a form with multiple datagridviews. On save the entire dataset will be serialized to a strongly typed property bound to a sql varbinary(max) Works fine.

Of course the current "dirty" cell will not be saved as mentioned here :

http://stackoverflow.com/questions/963601/datagridview-value-does-not-gets-saved-if-selection-is-not-lost-from-a-cell

My problem is the user could be coming from any one of 20 datagridviews when they click SAVE.

Is there any way, short of checking for a dirty cell in each datagridview to commit any dirty cell before the save ( clicking another textbox control before the save does the trick but calling the focus() of that textbox prior to the save does not )

I was thinking perhaps catching the event of leaving the grid but it seems the base problem is clicking a button (for reasons I think I understand) does not fire lostfocus events for the current control and it doesn't seem the click handler args knows what the last current selected control is.

Guidance appreciated.

TIA

+1  A: 

Hook up all your datagridviews to the same Leave event handler. The leave event is processed before the click event. Inside your leave event, capture the datagridview that just lost focus. When the save button is clicked, check if the last datagrid view that was left has any unsaved data...

Example:

    DataGridView _lastDataGridView = null;
    private void dataGridView_Leave(object sender, EventArgs e)
    {
        _lastDataGridView = sender as DataGridView;
    }

    private void saveButton_Click(object sender, EventArgs e)
    {
        if (_lastDataGridView != null)
        {
            // check if data needs saving...
        }
    }

Edit 1: As for you not receiving the leave event before the click event, I'm not seeing that behavior. To reproduce what I've done, create a form with a DataGridView and a button. Add two text box columns to the DataGridView, hook up the events as described and see if the _lastDataGridView member is set when executing sendButton_Click. It is on my end.

Edit 2: After trying my datagridview I noticed that the data was always being saved. So I suspected you had some different settings. I turned on "VirtualMode." This causes the same behavior that you're describing. If possible, try turning VirtualMode off and see if the data gets saved to the DataGridView as expected. Otherwise try implementing the suggestions outlined in this MSDN article.

Jason D
Thanks, Jason. i will check this now. The button in question is on a toolstrip but perhaps that will not matter. Your suggestion is clear, logical and helpful and should be very easy to test.
Charles Hankey
Let me know how it turns out. In my experience I've always received the leave event before any other event (due to a mouse click) occurs. . . However, I can see one scenario where the toolbar button handler may kick in without losing focus. If that happens, use the Enter event instead, to track which datagridview has focus...
Jason D
the one scenario is if you've hooked up the save command to accelerator keys, such as "Ctrl-S" the focus will still be on the datagridview....
Jason D
You were all quite right, of course, about the leave event firing when you said - the problem is it turns out that by the time the leave event fires the cell has already reverted to its original value and is no long dirty. I have trapped the currentcelldirtystatechanged event as suggesting in the other thread, check for iscurrentcelldirty and then force the commitedit. Of course this fires on each keystroke as the cell is no longer dirty after the commit then becomes dirty again with teh next character. Completely blows up on datetime bound textbox, of course, as the first char is invalid
Charles Hankey
Formatting for currency etc doesn't seem to create a problem. I've bypassed the routine for currentcell.valuetype is gettype(datetime) and the other values work fine.
Charles Hankey
Could you post some sample code to better illustrate your newest issues? Thanks
Jason D
Make it the minimum amount necessary to demonstrate the issue.
Jason D
I'm not sure I'm following Edit2. The grid is not set to virtual mode. In the leave handler I have assigned the sender to a property (lastgrid) of type datagridview. At that point, the lastgrid.isCurrentCelldirty = false and the CurrentCellValue has been set back to the original value for the cell the cursor was in before clicking the toolstrip. This only happens when clicking the toolstrip, which receives the click. I am beginning to suspect it ia framework idiosyncracy ( Strataframe ) so will check with them before speculating further. Thanks for your help. i'll report back.
Charles Hankey
Okay, definitely a toolstrip thing. I put a button directly on the form to save and without any code to make it happen the cell with the current changes is saved with no problem IOW no issue, not even the one in the message link above. Thanks for your patience, i think this case is closed.
Charles Hankey
Sounds good. If you think my help was useful enough to warrant accepting the answer, then by all means, please do.
Jason D
A: 

Why not use the DataGridView's CellEndEdit event to mark a boolean flag that the DGV is dirty? Assuming you are using SQL, you would create an UpdateCommand, SelectCommand, and DeleteCommand for each DGV. When you want to "save" the changes, just call DataAdapter.Update(myDataSet, "TABLE NAME"); for the DataAdapter associated with your DataGridView. I use this technique now for one DGV and it works fine.

0A0D