RowState and bound controls - what triggers a change to "Modified"

G

Guest

I have a Windows form that displays a database table in a DataGrid. When you
click on a row, the row's values get copied to bound TextBoxes below, and
when the "Save" button is clicked the database is updated (as is the DataGrid
row) with changed values in the TextBoxes. Here are some observations:

1) When changes are typed into a text box and "Save" is clicked, the changes
are reflected in the DataSet.Tables().Rows().ItemArray value, but not in the
bound DataGrid. The RowState is "Unchanged" until EndEdit() is executed, when
it becomes "Modified". The changes are reflected in the DataGrid after the
Update command has completed.

2) When changes are programmatically made to the Text property of the text
box, changes are not reflected in the DataSet, either in the ItemArray value
or visually in the DataGrid. RowState remains "Unchanged".

3) When changes are programmatically made to the DataSet Item itself, they
are visible in both the DataGrid and TextBox and RowState is "Modified" after
EndEdit().

So my question is what specifically related to the bound control causes the
RowState property to be changed to Modified? The documentation that I have
found all say that it is when the dataset is modified, but I've not seen a
more explicit definition of what that means.

I want to see the same behavior when I programmatically update the bound
TextBox as when the user types in a change (as in #1 above).

Thanks in advance....

Tim
 
C

Cor Ligthert [MVP]

Tim,

A rowchange or an endcurrentedit of the bindingmanager (if there is a change
of course).

I hope this helps,

Cor
 
B

Bart Mermuys

Hi,

timbobd said:
I have a Windows form that displays a database table in a DataGrid. When
you
click on a row, the row's values get copied to bound TextBoxes below, and
when the "Save" button is clicked the database is updated (as is the
DataGrid
row) with changed values in the TextBoxes. Here are some observations:

1) When changes are typed into a text box and "Save" is clicked, the
changes
are reflected in the DataSet.Tables().Rows().ItemArray value, but not in
the
bound DataGrid. The RowState is "Unchanged" until EndEdit() is executed,
when
it becomes "Modified". The changes are reflected in the DataGrid after the
Update command has completed.

DataRow:
When you make changes to a DataRow then the RowState becomes Modified
immediately, *unless* you first call DataRow.BeginEdit(), then the row will
become Modified after calling DataRow.EndEdit().

DataRowView:
When you make changes to a DataRowView then DataRow.BeginEdit will be
implicitly called, so you need to call DataRowView.EndEdit which calls
DataRow.EndEdit, before the RowState changes to Modified.

Related to the binding:
All changes are made to a DataRowView, never directly to a DataRow.
Calling CurrencyManager.EndCurrentEdit()calls EndEdit() on the current
DataRowView.

After the EndCurrentEdit() the DataGrid will see that the RowState changed
and pick up the new values, it doesn't require an update for that.

Also, EndEdit() may be called implicitly. (eg. when you navigate to another
row)
2) When changes are programmatically made to the Text property of the text
box, changes are not reflected in the DataSet, either in the ItemArray
value
or visually in the DataGrid. RowState remains "Unchanged".

3) When changes are programmatically made to the DataSet Item itself, they
are visible in both the DataGrid and TextBox and RowState is "Modified"
after
EndEdit().

So my question is what specifically related to the bound control causes
the
RowState property to be changed to Modified?

Two things :
1) A TextBox writes its Text to a DataViewRow when the Text is changed *and*
is validated.
(Validated here means the user must Enter and Leave the TextBox)

2) CurrencyManger.EndCurrentEdit()

HTH,
Greetings
 
G

Guest

Thanks for the reply, Bart! However, I have not been able to resolve my
issue. To review, I want programmatic changes to the bound TextBox.Text
property to trigger a RowState of "Modified", the same as if the changes were
typed into the TextBox.

Bart Mermuys said:
Two things :
1) A TextBox writes its Text to a DataViewRow when the Text is changed *and*
is validated.
(Validated here means the user must Enter and Leave the TextBox)

2) CurrencyManger.EndCurrentEdit()

I added an EndCurrentEdit statement, but the behavior is the same: RowState
remains "Unchanged" with programmatic updates, but becomes "Modified" with
manual typed changes.

Help! Thanks in advance....

Tim
 
B

Bart Mermuys

Hi,

timbobd said:
Thanks for the reply, Bart! However, I have not been able to resolve my
issue. To review, I want programmatic changes to the bound TextBox.Text
property to trigger a RowState of "Modified", the same as if the changes
were
typed into the TextBox.

But it is _not_ the same. If you make changes in the TextBox by typing then
the RowState will not become Modified until you call EndCurrentEdit().

' Change text
SomeTextBox.Text = "abc"

' Force write to DataRowView
Dim temp As Control = ActiveControl
SomeTextBox.Select()
temp.Select()

' Get the row into modified state
' It is important for the code below that you use the same
' DataSource and DataMember(without any field) as the
' ones you used for binding SomeTextBox:
BindingContext( dataSource, dataMember ).EndCurrentEdit()


If the TextBox is made invisible from designer then it won't work, you can
make it invisible in form load instead.

Note that i prefer to write directly to the underlying datasource:

Dim drv As DataRowView = DirectCast( _
BindingContext( dataSource, dataMember ).Current, _
DataRowView)

drv( "samefieldastextbox") = "set from code"

' call EndEdit if you want rowstate Modified
drv.EndEdit()


HTH,
Greetings
 
G

Guest

Bart Mermuys said:
But it is _not_ the same. If you make changes in the TextBox by typing then
the RowState will not become Modified until you call EndCurrentEdit().

' Change text
SomeTextBox.Text = "abc"

' Force write to DataRowView
Dim temp As Control = ActiveControl
SomeTextBox.Select()
temp.Select()

This works nicely, in fact I had already tried something similar (using
Focus instead of Select). But there is a different problem. My TextBox is
bound to an InactiveDate field. I have an "Inactive" check box, that when
checked I set the TextBox.Text property to the current date, when it is
unchecked I clear out the date (both in the CheckedChanged event). When I am
using the paired Select(or Focus) statements, the text box will not clear out
for some reason...the prior value is retained. If I get rid of the Selects,
the text will clear out just fine.
' Get the row into modified state
' It is important for the code below that you use the same
' DataSource and DataMember(without any field) as the
' ones you used for binding SomeTextBox:
BindingContext( dataSource, dataMember ).EndCurrentEdit()


If the TextBox is made invisible from designer then it won't work, you can
make it invisible in form load instead.

Note that i prefer to write directly to the underlying datasource:

Dim drv As DataRowView = DirectCast( _
BindingContext( dataSource, dataMember ).Current, _
DataRowView)

drv( "samefieldastextbox") = "set from code"

' call EndEdit if you want rowstate Modified
drv.EndEdit()

Yes, I tried this also, but as I mentioned in my original post, I do not
want the DataGrid to reflect the changes until the user has clicked "Save".

These are helpful suggestions and I really appreciate your response. I've
about decided to use unbound text boxes instead, not because of the problems
here but because of the overriding code that would be necessary to make
things work properly in different modes (update vs. adding a new row).
Still, it is very helpful for me to better understand the behavior that I've
observed and I am thankful for the information.

Tim
 
B

Bart Mermuys

Hi,
Yes, I tried this also, but as I mentioned in my original post, I do not
want the DataGrid to reflect the changes until the user has clicked
"Save".

Well, then don't call drv.EndEdit(). Since the above code modifies the data
through a DataRowView (not a DataRow), it won't be visible to the DataGrid
until you call EndEdit(). You can postpone it and then call
currencyManager.EndCurrentEdit in the Save method.
These are helpful suggestions and I really appreciate your response. I've
about decided to use unbound text boxes instead, not because of the
problems
here but because of the overriding code that would be necessary to make
things work properly in different modes (update vs. adding a new row).
Still, it is very helpful for me to better understand the behavior that
I've
observed and I am thankful for the information.

You're welcome.

Greetings
 

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