By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,851 Members | 1,121 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,851 IT Pros & Developers. It's quick & easy.

Databinding to user control

P: n/a
I have a DataGridView displaying data from a DataSet. To the right of that
I have a custom user control which displays one of the data set fields.
The custom user control is bound to the data set object and displays the
data correctly when I move from row to row.

The problem I am having is the data set always reads the data back and
considers it change even when it's not. I am looking for how to change the
following code so the custom user control can set the pencil on the
DataGridView and only cause the data set to be updated if the data is
changed. I don't want to host the control in the DataGridView.

Since I do this with RichTextControls I am assuming its the way I am doing
it and possible.

My guess is I need to enable PropertyChange or Validated but neither work so
obviously I am doing it incorrectly.

//// The data binding in the main form
//// This version uses OnPropertyChanged and I have tried OnValidation.
//
// ctrlMsgEditor1
//
this.ctrlMsgEditor1.Cursor = System.Windows.Forms.Cursors.Default;
this.ctrlMsgEditor1.DataBindings.Add(new
System.Windows.Forms.Binding("MsgData", this.dsMsg1, "Messages.Data", true,
System.Windows.Forms.DataSourceUpdateMode.OnProper tyChanged));
this.ctrlMsgEditor1.Dock = System.Windows.Forms.DockStyle.Right;
this.ctrlMsgEditor1.Location = new System.Drawing.Point(306, 0);
this.ctrlMsgEditor1.MsgData = null;
this.ctrlMsgEditor1.Name = "ctrlMsgEditor1";
this.ctrlMsgEditor1.Size = new System.Drawing.Size(347, 328);
this.ctrlMsgEditor1.TabIndex = 7;

//// The custom user control
[System.ComponentModel.DefaultBindingProperty("MsgD ata")]
public partial class ctrlMsgEditor : UserControl
{
private byte[] _MsgData = new byte[1];
[System.ComponentModel.Bindable(true), Browsable(true),
Category("Data"), Description("Encoded data to be displayed")]
public byte[] MsgData
{
get
{
lock (this)
{
return _MsgData;
}
}
set
{
lock (this)
{
this._MsgData = value;
this.DisplayData(this._MsgData);
}
}
}
public ctrlMsgEditor()
{
InitializeComponent();
}

private void DisplayData(byte[] msgData)
{
/// Display the data
}
}
Regards,
John
Jun 25 '06 #1
Share this Question
Share on Google+
11 Replies


P: n/a
Hi John,

What do you mean, "The data set always reads the data back and considers it
change event when it's not."?

The DataGridView handles the state of row changes correctly in my
experience. DataRows being displayed by a DataGridView are always in an
Unchanged, Modified, Deleted or Added state. While editing a row in the
DataGridView the state of the underlying DataRow remains Unchanged until the
changes are committed by the user, in which case the DataRow becomes
Modified.

Could you possibly have forgotten to call DataSet.AcceptChanges() after you
filled the data? (Calling AcceptChanges() isn't necessary when using a
DataAdapter with the default settings)

BTW, the locks in your get and set accessors for the MsgData property aren't
serving any purpose. Locking the "return" statement is of no use and the
variable assignment and method call should probably not be locked and just
allow race conditions in an asynchronous environment. Also, since it's a
UserControl you'll probably have to call Invalidate to update the display
when MsgData is set so synchronicity will be handled implicitly by the
framework on the UI Thread.

HTH

"John J. Hughes II" <no@invalid.com> wrote in message
news:eH**************@TK2MSFTNGP04.phx.gbl...
I have a DataGridView displaying data from a DataSet. To the right of
that I have a custom user control which displays one of the data set
fields. The custom user control is bound to the data set object and
displays the data correctly when I move from row to row.

The problem I am having is the data set always reads the data back and
considers it change even when it's not. I am looking for how to change
the following code so the custom user control can set the pencil on the
DataGridView and only cause the data set to be updated if the data is
changed. I don't want to host the control in the DataGridView.

Since I do this with RichTextControls I am assuming its the way I am doing
it and possible.

My guess is I need to enable PropertyChange or Validated but neither work
so obviously I am doing it incorrectly.

//// The data binding in the main form
//// This version uses OnPropertyChanged and I have tried OnValidation.
//
// ctrlMsgEditor1
//
this.ctrlMsgEditor1.Cursor = System.Windows.Forms.Cursors.Default;
this.ctrlMsgEditor1.DataBindings.Add(new
System.Windows.Forms.Binding("MsgData", this.dsMsg1, "Messages.Data",
true, System.Windows.Forms.DataSourceUpdateMode.OnProper tyChanged));
this.ctrlMsgEditor1.Dock = System.Windows.Forms.DockStyle.Right;
this.ctrlMsgEditor1.Location = new System.Drawing.Point(306, 0);
this.ctrlMsgEditor1.MsgData = null;
this.ctrlMsgEditor1.Name = "ctrlMsgEditor1";
this.ctrlMsgEditor1.Size = new System.Drawing.Size(347, 328);
this.ctrlMsgEditor1.TabIndex = 7;

//// The custom user control
[System.ComponentModel.DefaultBindingProperty("MsgD ata")]
public partial class ctrlMsgEditor : UserControl
{
private byte[] _MsgData = new byte[1];
[System.ComponentModel.Bindable(true), Browsable(true),
Category("Data"), Description("Encoded data to be displayed")]
public byte[] MsgData
{
get
{
lock (this)
{
return _MsgData;
}
}
set
{
lock (this)
{
this._MsgData = value;
this.DisplayData(this._MsgData);
}
}
}
public ctrlMsgEditor()
{
InitializeComponent();
}

private void DisplayData(byte[] msgData)
{
/// Display the data
}
}
Regards,
John

Jun 25 '06 #2

P: n/a
Well obviously I did not make myself clear. There is nothing wrong with
the dataset and it is working just fine. The problem is the way I have
written my control. When row is selected in the data grid view my custom
control displays one of the columns correctly via the data binding using the
MsgData set property. When the row is changed the new row is also displayed
correctly. The problem is every time the row is changed the MsgData is
read using get and the DataSet considers it changed. So if I do a
dataset.GetChanges() every row viewed reports changes made when no changes
were made. In fact currently the control does not allow changes and
whatever is set is return.

I assume there is some method which I have not found to cause the DataSet to
be notified that the data in the control is being edit. If I do the same
thing but use a string and text field the DataSet does not consider the data
changed just by changing rows but does apply the changes and mark the
DataSet as changed when the text in the control is updated.

Mind you the problem might lay in the DataSet being unable to determine if
the data has changed being its a byte array. If so do I need to supply a
special object to deal with the comparison. I tried using the
IEditableObject to but was unsuccessful.

Thanks for the information on locks.

Regards,
John
"Dave Sexton" <dave@jwa[remove.this]online.com> wrote in message
news:uB**************@TK2MSFTNGP05.phx.gbl...
Hi John,

What do you mean, "The data set always reads the data back and considers
it change event when it's not."?

The DataGridView handles the state of row changes correctly in my
experience. DataRows being displayed by a DataGridView are always in an
Unchanged, Modified, Deleted or Added state. While editing a row in the
DataGridView the state of the underlying DataRow remains Unchanged until
the changes are committed by the user, in which case the DataRow becomes
Modified.

Could you possibly have forgotten to call DataSet.AcceptChanges() after
you filled the data? (Calling AcceptChanges() isn't necessary when using
a DataAdapter with the default settings)

BTW, the locks in your get and set accessors for the MsgData property
aren't serving any purpose. Locking the "return" statement is of no use
and the variable assignment and method call should probably not be locked
and just allow race conditions in an asynchronous environment. Also,
since it's a UserControl you'll probably have to call Invalidate to update
the display when MsgData is set so synchronicity will be handled
implicitly by the framework on the UI Thread.

HTH

"John J. Hughes II" <no@invalid.com> wrote in message
news:eH**************@TK2MSFTNGP04.phx.gbl...
I have a DataGridView displaying data from a DataSet. To the right of
that I have a custom user control which displays one of the data set
fields. The custom user control is bound to the data set object and
displays the data correctly when I move from row to row.

The problem I am having is the data set always reads the data back and
considers it change even when it's not. I am looking for how to change
the following code so the custom user control can set the pencil on the
DataGridView and only cause the data set to be updated if the data is
changed. I don't want to host the control in the DataGridView.

Since I do this with RichTextControls I am assuming its the way I am
doing it and possible.

My guess is I need to enable PropertyChange or Validated but neither work
so obviously I am doing it incorrectly.

//// The data binding in the main form
//// This version uses OnPropertyChanged and I have tried OnValidation.
//
// ctrlMsgEditor1
//
this.ctrlMsgEditor1.Cursor = System.Windows.Forms.Cursors.Default;
this.ctrlMsgEditor1.DataBindings.Add(new
System.Windows.Forms.Binding("MsgData", this.dsMsg1, "Messages.Data",
true, System.Windows.Forms.DataSourceUpdateMode.OnProper tyChanged));
this.ctrlMsgEditor1.Dock = System.Windows.Forms.DockStyle.Right;
this.ctrlMsgEditor1.Location = new System.Drawing.Point(306, 0);
this.ctrlMsgEditor1.MsgData = null;
this.ctrlMsgEditor1.Name = "ctrlMsgEditor1";
this.ctrlMsgEditor1.Size = new System.Drawing.Size(347, 328);
this.ctrlMsgEditor1.TabIndex = 7;

//// The custom user control
[System.ComponentModel.DefaultBindingProperty("MsgD ata")]
public partial class ctrlMsgEditor : UserControl
{
private byte[] _MsgData = new byte[1];
[System.ComponentModel.Bindable(true), Browsable(true),
Category("Data"), Description("Encoded data to be displayed")]
public byte[] MsgData
{
get
{
lock (this)
{
return _MsgData;
}
}
set
{
lock (this)
{
this._MsgData = value;
this.DisplayData(this._MsgData);
}
}
}
public ctrlMsgEditor()
{
InitializeComponent();
}

private void DisplayData(byte[] msgData)
{
/// Display the data
}
}
Regards,
John


Jun 26 '06 #3

P: n/a
Hi John,

I tried to piece together your problem from snippets of your last post. I
have responded to each snippet inline, below. If you could possibly
condense your question into one line, if I haven't answered it in this post,
it would be much easier to answer.
When the row is changed the new row is also displayed correctly. The
problem is every time the row is changed the MsgData is read using get and
the DataSet considers it changed.
Sounds correct to me. If you change a field value in a DataRow the
DataRow.RowState property will become "Modified". The DataSet does not
consider a DataRow changed just by reading a value.
So if I do a dataset.GetChanges() every row viewed reports changes made
when no changes were made.
If you want to commit all changes to a DataSet so that GetChanges() returns
null simply call DataSet.AcceptChanges(). Editing the DataRow in the
DataGridView will cause GetChanges() to return changed DataRows until
DataSet.AcceptChanges() is called. If DataSet.GetChanges() returns null
before the data is bound to a DataGridView it will remain null until a
DataRow is edited and the changes are committed. DataSet.AcceptChanges()
should be called immediately after the DataSet is filled with data, unless
your using a DataAdapter or table adapter will the default settings.
In fact currently the control does not allow changes and whatever is set
is return
Do you mean to say that your control does not provide a way for users to
edit the bound data? The DataSet will not mark a DataRow as "Modified"
because it is bound to a control, it will only mark a DataRow as "Modified"
if the value is changed. Reading a value does not qualify as changing a
value. If you don't provide code in your control that changes the value of
a column in a bound DataRow then the DataRow.RowState will remain
"Unchanged" until the data is edited and committed or the row is deleted.
I assume there is some method which I have not found to cause the DataSet
to be notified that the data in the control is being edit
DataRow.BeginEdit()
DataRow.EndEdit()
DataRow.CancelEdit()
If I do the same thing but use a string and text field the DataSet does
not consider the data changed just by changing rows but does apply the
changes and mark the DataSet as changed when the text in the control is
updated.
Navigating the bound DataSet of a DataGridView will not cause the DataSet to
change the state of one of its DataRows. The value of a DataColumn for a
DataRow must be edited. I suspect that if you are simply navigating the
DataSet by selecting a row in the DataGridView and then detecting changes
using the GetChanges() method that the changes already existed before you
selected the row or you have code executing in an event handler that makes
changes to the underlying DataRow when navigating the data source.
Mind you the problem might lay in the DataSet being unable to determine if
the data has changed being its a byte array. If so do I need to supply a
special object to deal with the comparison.


No. The DataSet will correctly detect changes to a DataColumn of a DataRow
simply by setting the value. The DataSet is not concerned with the Type or
content of the value.

Here's a simple example of using a DataTable as a data source for a
DataGridView. I intend to show when and why the DataTable.GetChanges()
method will return a non-null value. The sample will work with a DataSet
just as well.

Please realize that I have not attempted to build this code.

private DataTable table;

private void InitializeDataAndBind()
{
table = new DataTable();
table.Columns.Add(typeof(string), "Column1");
table.Rows.Add("Row 1");
table.Rows.Add("Row 2");

// commit changes to DataTable
table.AcceptChanges();

DataTable changes = table.GetChanges();

// changes is null

// bind the DataTable to a DataGridView
dataGridView1.DataSource = table;
}

/*
After the data is initialized and bound to the grid select a row in the
grid.
Then execute code to call table.GetChanges() by clicking a button on the
Form.
table.GetChanges will return null unless a DataRow was actually modified.
Using the DataBindings of a custom control will not change this behavior.
If your control modifies a DataRow
then GetChanges() will return a DataTable containing a clone of the modified
DataRow until
table.AcceptChanges() is called. If your control does not modified the
DataRow to which it's bound then
table.GetChanges() will always return null until a DataRow is modified,
deleted or added.
*/

private void TestEdit()
{
// I assume table.GetChanges() returns null at this point for the
purpose of this demonstration
// Call this method before making changes to the DataTable.

// edit a row in code...

DataRow rowInEdit = table.Rows[0];

// call rowInEdit.BeginEdit() if you intend to keep the row in edit mode
until a later time
// in that case changes will not be commited to the row until
rowInEdit.EndEdit() is called.

// edit a row
rowInEdit["Column1"] = "Row 1 (edited)";

// now, table.GetChanges() will return a DataTable containing a clone of
rowInEdit since it was modified

// message will be displayed since the row was modified above
System.Diagnostics.Debug.WriteLineIf(rowInEdit.Row State ==
DataRowState.Modified,
"DataRow is Modified");

// accept all changes to the table
table.AcceptChanges();

DataTable changes = table.GetChanges();

// changes is null

// message will be displayed since all changes have been accepted.
System.Diagnostics.Debug.WriteLineIf(rowInEdit.Row State ==
DataRowState.Unchanged,
"Changes have been accepted. The DataRow is no longer
'Modified'.");
}

HTH
Jun 26 '06 #4

P: n/a
Hi John,
How do you create a custom user control to be binded to a DataSet so the
DataSet knows when the data used by the control is updated?
Actually, your binding your control to the current DataRow of a DataTable,
"Table1", in a DataSet, but this question does clarify your problem.

To answer your question:

control.DataBindings.Add("MsgData", this.dataSet1, "Table1.Data");

where MsgData is a property of control and this.dataSet1 contains a table
named, "Table1", which contains a DataColumn named, "Data".

In your example you have done the same thing using a different overload of
the Add method.
Now in my opinion as I move up and down though the rows the title bar
value should always show -0- unless something is edited.
My opinion as well.
Note in the project is a second custom user control which uses a string
instead of a byte array. If this is used in place of the rich text
control then the records change each time the row changes. I have
concluded from this that the binding does not compare the value but is
using some other method to determine the value has changed.


I created a test to see if the RichTextBox control behaved as you mentioned
but I did not see those results. I bound a DataColumn to the Text property
of a RichTextBox and navigated the DataSet using a DataGridView. It behaved
as expected without modifying the RowState of any DataRows. The
DataSet.GetChanges() property always returns null until I change a DataRow
within the DataGrid.

When and how are you updating the title bar to display the number of
changes? Are you doing anything in that code block that might be changing a
DataRow? Do you have any code anywhere that is modifing any DataRow at any
time?

You must be making changes to a DataRow in code without even realizing it.
Simply binding a DataColumn to a RichTextBox, or any Control for that
matter, does not cause the state of a DataRow to be modified unless the
value of a DataColumn with a DataRow is explicitly changed in code or by the
user.

- Dave Sexton
Jun 26 '06 #5

P: n/a
Hi John,

I just had some time to look at the code you attached.

The DataGridView.SelectionChanged method seems to be raised in the middle of
navigating the data source, not after navigation is complete. To be honest
I don't know why this is happening on that particular event but it seems
that the DataGridView does in fact change the state of a DataRow while
navigating the DataSet, however the changes are lost after navigation is
complete. Perhaps binding to a BindingSource object instead will alleviate
the problem.

To work around the issue while binding directly to a DataSet do the
following:

1. Remove your DataGridView.SelectionChanged event handler
2. Place the following line of code at the end of the Form.Load event
handler:

((CurrencyManager) this.BindingContext[dataSet1, "Table1"]).ListChanged
+= new ListChangedEventHandler(Form1_ListChanged);

3. Create the following event handler for the ListChanged event of your data
source:

private void Form1_ListChanged(object sender, ListChangedEventArgs e)
{
this.DisplayChangeCount();
}

Using the ListChanged event of the CurrencyManager for the Form will ensure
that the TitleBar is only updated when 'real' changes occur to the DataSet.

HTH

"John J. Hughes II" <no@invalid.com> wrote in message
news:%2***************@TK2MSFTNGP03.phx.gbl...
Dave,

Thank you for your patience.

One line question (don't think it will help):
How do you create a custom user control to be binded to a DataSet so the
DataSet knows when the data used by the control is updated?

************************************************** ***
Reboot... attached find a small project to demo my problem. (VS2005)

When run the main form show a DataGridView which shows the first column of
several records. To the right is two controls, one is a rich text box
and the other is my custom control. At this point the custom control
does not do anything expect display the size, later it will need to modify
the data (another topic).

In the title bar is the number of records that have been changed, at this
point we don't care about saving the data.

Now in my opinion as I move up and down though the rows the title bar
value should always show -0- unless something is edited.

If you comment out the follow line the title bar will always show -0- but
if the line is not commented out then each time the row is changed the
title bar increments by one.

/// Title bar changes count
public Form1()
{
InitializeComponent();
this.userControl11.DataBindings.Add(new
System.Windows.Forms.Binding("MsgData", this.dataSet1, "Table1.Data",
false));
}

/// Title bar does not change count
public Form1()
{
InitializeComponent();
/// this.userControl11.DataBindings.Add(new
System.Windows.Forms.Binding("MsgData", this.dataSet1, "Table1.Data",
false));
}

**************************************************

Note in the project is a second custom user control which uses a string
instead of a byte array. If this is used in place of the rich text
control then the records change each time the row changes. I have
concluded from this that the binding does not compare the value but is
using some other method to determine the value has changed.

Regards,
John

Jun 26 '06 #6

P: n/a
Hi Dave,

Thanks again, comments embedded.

"Dave Sexton" <dave@jwa[remove.this]online.com> wrote in message
news:Og**************@TK2MSFTNGP04.phx.gbl...
Hi John,
How do you create a custom user control to be binded to a DataSet so the
DataSet knows when the data used by the control is updated?
Actually, your binding your control to the current DataRow of a DataTable,
"Table1", in a DataSet, but this question does clarify your problem.

To answer your question:

control.DataBindings.Add("MsgData", this.dataSet1, "Table1.Data");

where MsgData is a property of control and this.dataSet1 contains a table
named, "Table1", which contains a DataColumn named, "Data".

In your example you have done the same thing using a different overload of
the Add method.
Now in my opinion as I move up and down though the rows the title bar
value should always show -0- unless something is edited.


My opinion as well.
Note in the project is a second custom user control which uses a string
instead of a byte array. If this is used in place of the rich text
control then the records change each time the row changes. I have
concluded from this that the binding does not compare the value but is
using some other method to determine the value has changed.


I created a test to see if the RichTextBox control behaved as you
mentioned but I did not see those results. I bound a DataColumn to the
Text property of a RichTextBox and navigated the DataSet using a
DataGridView. It behaved as expected without modifying the RowState of
any DataRows. The DataSet.GetChanges() property always returns null until
I change a DataRow within the DataGrid.


The RichTexBox works as I expect. Unless you edit the data in the
RichTextBox the row does not change. If you edit the data in the
RichTextBox the row updates.

Test:
comment out the binding for MsgData.
Run the application
Select each row, arrow up and down, whatever
(Note the changed records: 0 --- always)
Change the text in the RichTextBox
Leave the row you are currently on
(Note the changed records: 1 --- As expected)

This is what I want my control to do, HOW?

Add the binding for MsgData mucks the whole thing up. Every time you
change rows the change records incerments until the all the records have
been changed.

When and how are you updating the title bar to display the number of
changes? Are you doing anything in that code block that might be changing
a DataRow? Do you have any code anywhere that is modifing any DataRow at
any time?
The title bar is updated via dataGridView1_SelectionChanged. The code gets
the changes, writes the count and returns. Nothing else. The same code is
run if the MsgData is bound or not.

You must be making changes to a DataRow in code without even realizing it.
Simply binding a DataColumn to a RichTextBox, or any Control for that
matter, does not cause the state of a DataRow to be modified unless the
value of a DataColumn with a DataRow is explicitly changed in code or by
the user.
I don't see where the MsgData in control can be modified. there is only the
get / set accessors. The paint function only shows the number of bytes so
I know the row has updated.

- Dave Sexton

Jun 26 '06 #7

P: n/a
Dave,

This does not change anything. My main project does not even have the code
to update the title bar, it only looks for changes when the user presses
update and/or when the form is closed. The main project get the change and
passes them to a SQL data adaptor which then does its thing.

The problem is my control and not the form or the DataSet. I need to
modify the way the control was created or the way it is bound to the data.
I am at a loss for which.

Regards,
John

"Dave Sexton" <dave@jwa[remove.this]online.com> wrote in message
news:OV**************@TK2MSFTNGP04.phx.gbl...
Hi John,

I just had some time to look at the code you attached.

The DataGridView.SelectionChanged method seems to be raised in the middle
of navigating the data source, not after navigation is complete. To be
honest I don't know why this is happening on that particular event but it
seems that the DataGridView does in fact change the state of a DataRow
while navigating the DataSet, however the changes are lost after
navigation is complete. Perhaps binding to a BindingSource object instead
will alleviate the problem.

To work around the issue while binding directly to a DataSet do the
following:

1. Remove your DataGridView.SelectionChanged event handler
2. Place the following line of code at the end of the Form.Load event
handler:

((CurrencyManager) this.BindingContext[dataSet1, "Table1"]).ListChanged
+= new ListChangedEventHandler(Form1_ListChanged);

3. Create the following event handler for the ListChanged event of your
data source:

private void Form1_ListChanged(object sender, ListChangedEventArgs e)
{
this.DisplayChangeCount();
}

Using the ListChanged event of the CurrencyManager for the Form will
ensure that the TitleBar is only updated when 'real' changes occur to the
DataSet.

HTH

"John J. Hughes II" <no@invalid.com> wrote in message
news:%2***************@TK2MSFTNGP03.phx.gbl...
Dave,

Thank you for your patience.

One line question (don't think it will help):
How do you create a custom user control to be binded to a DataSet so the
DataSet knows when the data used by the control is updated?

************************************************** ***
Reboot... attached find a small project to demo my problem. (VS2005)

When run the main form show a DataGridView which shows the first column
of several records. To the right is two controls, one is a rich text
box and the other is my custom control. At this point the custom
control does not do anything expect display the size, later it will need
to modify the data (another topic).

In the title bar is the number of records that have been changed, at this
point we don't care about saving the data.

Now in my opinion as I move up and down though the rows the title bar
value should always show -0- unless something is edited.

If you comment out the follow line the title bar will always show -0- but
if the line is not commented out then each time the row is changed the
title bar increments by one.

/// Title bar changes count
public Form1()
{
InitializeComponent();
this.userControl11.DataBindings.Add(new
System.Windows.Forms.Binding("MsgData", this.dataSet1, "Table1.Data",
false));
}

/// Title bar does not change count
public Form1()
{
InitializeComponent();
/// this.userControl11.DataBindings.Add(new
System.Windows.Forms.Binding("MsgData", this.dataSet1, "Table1.Data",
false));
}

**************************************************

Note in the project is a second custom user control which uses a string
instead of a byte array. If this is used in place of the rich text
control then the records change each time the row changes. I have
concluded from this that the binding does not compare the value but is
using some other method to determine the value has changed.

Regards,
John


Jun 26 '06 #8

P: n/a
Hello again,

Ok the following change seems to mostly fix the problem. Changing rows does
not change the number of rows changed and if the data is changed the DataSet
fetches the data correctly. It does not report the data as change but I
think I am on the correct path.

public partial class UserControl1 : UserControl, INotifyPropertyChanged

Regards,
John

"Dave Sexton" <dave@jwa[remove.this]online.com> wrote in message
news:OV**************@TK2MSFTNGP04.phx.gbl...
Hi John,

I just had some time to look at the code you attached.

The DataGridView.SelectionChanged method seems to be raised in the middle
of navigating the data source, not after navigation is complete. To be
honest I don't know why this is happening on that particular event but it
seems that the DataGridView does in fact change the state of a DataRow
while navigating the DataSet, however the changes are lost after
navigation is complete. Perhaps binding to a BindingSource object instead
will alleviate the problem.

To work around the issue while binding directly to a DataSet do the
following:

1. Remove your DataGridView.SelectionChanged event handler
2. Place the following line of code at the end of the Form.Load event
handler:

((CurrencyManager) this.BindingContext[dataSet1, "Table1"]).ListChanged
+= new ListChangedEventHandler(Form1_ListChanged);

3. Create the following event handler for the ListChanged event of your
data source:

private void Form1_ListChanged(object sender, ListChangedEventArgs e)
{
this.DisplayChangeCount();
}

Using the ListChanged event of the CurrencyManager for the Form will
ensure that the TitleBar is only updated when 'real' changes occur to the
DataSet.

HTH

"John J. Hughes II" <no@invalid.com> wrote in message
news:%2***************@TK2MSFTNGP03.phx.gbl...
Dave,

Thank you for your patience.

One line question (don't think it will help):
How do you create a custom user control to be binded to a DataSet so the
DataSet knows when the data used by the control is updated?

************************************************** ***
Reboot... attached find a small project to demo my problem. (VS2005)

When run the main form show a DataGridView which shows the first column
of several records. To the right is two controls, one is a rich text
box and the other is my custom control. At this point the custom
control does not do anything expect display the size, later it will need
to modify the data (another topic).

In the title bar is the number of records that have been changed, at this
point we don't care about saving the data.

Now in my opinion as I move up and down though the rows the title bar
value should always show -0- unless something is edited.

If you comment out the follow line the title bar will always show -0- but
if the line is not commented out then each time the row is changed the
title bar increments by one.

/// Title bar changes count
public Form1()
{
InitializeComponent();
this.userControl11.DataBindings.Add(new
System.Windows.Forms.Binding("MsgData", this.dataSet1, "Table1.Data",
false));
}

/// Title bar does not change count
public Form1()
{
InitializeComponent();
/// this.userControl11.DataBindings.Add(new
System.Windows.Forms.Binding("MsgData", this.dataSet1, "Table1.Data",
false));
}

**************************************************

Note in the project is a second custom user control which uses a string
instead of a byte array. If this is used in place of the rich text
control then the records change each time the row changes. I have
concluded from this that the binding does not compare the value but is
using some other method to determine the value has changed.

Regards,
John


Jun 26 '06 #9

P: n/a
Thanks for the help,

In fact that works perfectly now.

Regards,
John
Jun 26 '06 #10

P: n/a
Hi John,

I'm glad you resolved your issue. I tried implementing that interface on
the code you gave me and it worked for me as well.

FYI, the problem has nothing to do with a DataGridView, RichTextBox,
DataSet, System.Byte[] Type for a DataColumn or anything else we examined.

It turns out that your Control simply needs to notify the
RelatedPropertyManager that the value has been changed when it expects it to
be changed.

On MSDN:

For change notification to occur in a binding between a bound client and a
data source, your bound type should either:

1. Implement the INotifyPropertyChanged interface (preferred).

2. Provide a change event for each property of the bound type. i.e. public
event EventHandler MsgDataChanged

Do not do both.

Makes perfect sense now!

- Later

"John J. Hughes II" <no@invalid.com> wrote in message
news:ex**************@TK2MSFTNGP03.phx.gbl...
Thanks for the help,

In fact that works perfectly now.

Regards,
John

Jun 26 '06 #11

P: n/a
Dave,

Thanks again... yea make perfect sense when you find the puzzle pieces in
the docs which can in itself be a challenge.

Regards,
John

"Dave Sexton" <dave@jwa[remove.this]online.com> wrote in message
news:%2****************@TK2MSFTNGP03.phx.gbl...
Hi John,

I'm glad you resolved your issue. I tried implementing that interface on
the code you gave me and it worked for me as well.

FYI, the problem has nothing to do with a DataGridView, RichTextBox,
DataSet, System.Byte[] Type for a DataColumn or anything else we examined.

It turns out that your Control simply needs to notify the
RelatedPropertyManager that the value has been changed when it expects it
to be changed.

On MSDN:

For change notification to occur in a binding between a bound client and a
data source, your bound type should either:

1. Implement the INotifyPropertyChanged interface (preferred).

2. Provide a change event for each property of the bound type. i.e.
public event EventHandler MsgDataChanged

Do not do both.

Makes perfect sense now!

- Later

"John J. Hughes II" <no@invalid.com> wrote in message
news:ex**************@TK2MSFTNGP03.phx.gbl...
Thanks for the help,

In fact that works perfectly now.

Regards,
John


Jun 27 '06 #12

This discussion thread is closed

Replies have been disabled for this discussion.