Help: Need to cause DataGrid row to "flush" contents

J

Junkguy

I need some help programmatically causing a row in a DataGrid to "flush"
its contents to its bound data (in Visual Studio 6 using Windows Forms
with C#).

My issue is I want to send an update to a database from a menu command
while the user is editing a DataGrid. This is unusual in regard to
examples and normal practice in that the cell of the DataGrid still has
the focus. In all examples I can find, the user normally presses a
button on a Form. This practice causes the DataGrid to lose focus and
automatically flush the current row's contents to its bound data member.
But when I attempt to perform an update while the user is STILL editing
data in a row, the DataSet updates WITHOUT that particular row.

I attempted to circumvent this problem by simply setting the focus of
another control on the form (e.g. btnSave.Focus()), hoping that the
DataGrid would lose focus and flush its row contents to the DataSet, but
this proved to be inexplicably ineffective. The row was still not
flushed. I don't know if a Focus() call needs to iterate once through
the event chain before it finalizes or what.

I really want to do this the right way. I don't want to use a hack like
selecting another row before updating, but I can't find any method in
DataGrid that will force its contents to flush to its bound data. Does
anyone have the definitive procedure on this. Perhaps I'm simply missing
an obvious or well known method here?
 
N

Nicholas Paldino [.NET/C# MVP]

Junkguy,

I think that the best way to do this would be to call the EndEdit method
on the data grid before you perform the action. This will allow you to end
the current edit and should update the underlying data source when done.

Hope this helps.
 
E

Erald Kulk

junkguy, what I do is the following:

this.grdWorksheet.CurrentCell = new DataGridCell(0,0);
this.grdWorksheet.CurrentCell = new DataGridCell(0,1);
this.grdWorksheet.CurrentCell = new DataGridCell(0,0);

this way, the focus changes to an existing cell in the datagrid. and
even if the new edited cell is in the same row, the changes will be
updated.

Erald Kulk
 
J

Junkguy

I think that the best way to do this would be to call the EndEdit method
on the data grid before you perform the action. This will allow you to end
the current edit and should update the underlying data source when done.

Hope this helps.


Thanks Nicholas,

Wish it would help, but apparently EndEdit is already being called when
AcceptChanges() is called on the data table. I literally tried getting
the CurrencyManager and calling its EndCurrentEdit() call. It still
refused to work. As usual, there is some esoteric thing that happens to
really really make the thing end and nobody has caught the bug because
the whateveritiscall is getting coincidentally invoked by leaving the
DataGrid.

--Junkguy
 
J

Junkguy

this.grdWorksheet.CurrentCell = new DataGridCell(0,0);
this.grdWorksheet.CurrentCell = new DataGridCell(0,1);
this.grdWorksheet.CurrentCell = new DataGridCell(0,0);

this way, the focus changes to an existing cell in the datagrid. and
even if the new edited cell is in the same row, the changes will be
updated.

Yeah, that's cool.

I had tried

dg.CurrentCell = new DataGridCell(dg.CurrentRowIndex + 1,0);

This makes it go one row down, which I think is safer because if your
datagrid only contains one column, selecting the second cell won't work-
and in a datagrid that allows edits, there is always "one more row" on
the end. Or if you are on that end row, it does not affect it.

I tried earlier

dg.CurrentRowIndex += 1;

But that didn't work for some reason, and it throws an exception if you
are on the end row.

The only issue I have found with the "new cell" idea is when the row you
are currently on has a Validation error, the cell you were editing does
not re-highlight. It does re-hilight when you use the mouse to go to the
next row. Weird.

I really want to find out what the exact procedure is. I have actually
been stepping through the disassembled Microsoft code to see what the
heck they are doing. But that is pretty tedious and difficult and I
still haven't figured it out.

<rant>You know, EVERY other window toolkit I have ever used gives you
the code- which of course makes it easy to figure out what they are
doing. Microsoft hides it. I can see hiding the underlying operating
system but come on! The docs are so poor and they use so many esoteric
methodologies it just makes my job that much harder.</rant>

Until I figure out the correct procedures, I guess I'll use the "new
cell" method you describe.

Thanks for your advice.
 
D

Dmitriy Lapshin [C# / .NET MVP]

Hi,
dg.CurrentCell = new DataGridCell(dg.CurrentRowIndex + 1,0);

I'd suggest

dg.CurrentCell = new DataGridCell(dg.CurrentCell.RowNumber + 1,0);

because CurrentRowIndex is hardwired to the parent table and this approach
won't work for a child table if you bind the grid to a master-detail
dataset.

Unfortunately I cannot access the message that started the thread, could you
please re-post your original problem and I could then probably suggest
something?
 
D

Dmitriy Lapshin [C# / .NET MVP]

Hi,

The CurrencyManager.EndCurrentEdit followed by DataGrid.EndEdit sequence
works just fine for me. Note that it is a two-step sequence and any of the
steps alone won't do the job. If you follow this sequence and it doesn't
work, could you post a code snippet?
 
J

Junkguy

Dmitriy Lapshin said:
The CurrencyManager.EndCurrentEdit followed by DataGrid.EndEdit sequence
works just fine for me.

Thanks,

The thing that concerned me about this was that somebody else might attempt to
call DataGrid.EndEdit() because it was automatically invoked (i.e. I didn't
call BeginEdit). DataGrid.EndEdit() needs a DataGridColumnStyle, row number,
and a boolean. Who the heck is holding this information while I'm editing a
cell? I would like to get them to do the work. Barring that, I'm a little
unsure as to the best way to get the current DataGridColumnStyle as DataGrid
does not seem to provide an easy means to it. How do you do get it securely
and then insure that nobody else will make the EndEdit call?

P.S. Here is the original posting I made as per your request:
 
D

Dmitriy Lapshin [C# / .NET MVP]

The thing that concerned me about this was that somebody else might
attempt to
call DataGrid.EndEdit() because it was automatically invoked (i.e. I didn't
call BeginEdit).

No problem with that. To the best of my knowledge, no exception will be
thrown and no bad thing will happen. The method will just return false.
DataGrid.EndEdit() needs a DataGridColumnStyle, row number, and a boolean.
Who the heck is holding this information while I'm editing a cell?

The row number can be obtained from dataGrid.CurrentCell.RowNumber.
The boolean just means whether you want to commit changes or roll them back.
The column style is the hardest thing. The only way I know is having column
styles created manually through the TableStyles/GridColumnStyles collection
designers and then obtaining the corresponding instance by the column
number. The column number is also determined frin the CurrentCell property.

P.S. I am currently finishing work on a DataGrid article that should cover
this issue in particular.
 
J

Junkguy

DataGrid.EndEdit() needs a DataGridColumnStyle, row number, and a boolean.
Who the heck is holding this information while I'm editing a cell?
[/QUOTE]

Thanks Dmitriy for you response.

We still do not know what called BeginEdit. Some object, somewhere made the
initial call and still holds the info. I think I might just step through the
assembly code and find out.
The row number can be obtained from dataGrid.CurrentCell.RowNumber.
The boolean just means whether you want to commit changes or roll them back.
The column style is the hardest thing. The only way I know is having column
styles created manually through the TableStyles/GridColumnStyles collection
designers and then obtaining the corresponding instance by the column
number.

Well there's the rub isn't it. Getting the current column style is the most
mind-numbingly difficult thing and it should not be. Committing a row to the
data member should not be like pulling teeth. It should be a common
programmer-accessible call without having to go through hoops.


Anyway, thanks again. I look forward to reading your article.
 
D

Dmitriy Lapshin [C# / .NET MVP]

Junkguy,
We still do not know what called BeginEdit. Some object, somewhere made the
initial call and still holds the info. I think I might just step through the
assembly code and find out.

I wonder why would you need to find out this information? In my exerience, I
was always happily calling EndEdit without caring who had called BeginEdit.
When you know the row and the column, that's all you need to force the grid
commit editing.
Well there's the rub isn't it. Getting the current column style is the most
mind-numbingly difficult thing and it should not be. Committing a row to the
data member should not be like pulling teeth. It should be a common
programmer-accessible call without having to go through hoops.

Wholeheartedly agree with this. The DataGrid is full of secrets and
surprises, like a good computer game should be :))
 
J

Junkguy

Dmitriy Lapshin said:
I wonder why would you need to find out this information? In my exerience, I
was always happily calling EndEdit without caring who had called BeginEdit.
When you know the row and the column, that's all you need to force the grid
commit editing.

Just because it would perform all the nessesary steps to clean up after
itself. It may well be that nobody holds the info, and when you leave a cell
(for example) some generic code just finds the current column style and calls
EndEdit itself. If EndEdit is truly all that needs called then your suggestion
is fine.

I was simply concerned that perhaps some call X other than EndEdit was being
called first (i.e. EndEdit is called inside X) and X would have some cleanup
code inside it that should be done (like maybe textbox validation or a
delegate call). If we call EndEdit ourselves and skip this cleanup in call X,
we may well skip some important code, or worse, it may break sometime in the
future when Microsoft ammends call X.

But I'm probably just being paranoid. Thanks for your help.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top