Windows Develop Bookmark and Share   
 index > Windows Forms Data Controls and Databinding > change not reflected in the underlying data object
 

change not reflected in the underlying data object

This is a basic question.  Maybe there is a simple solution, but I just cannot find it.

I have a TextBox which is bound to a data object's property.  This data object implements IEditableObject interface.  So this is a two-way binding.  The data can be shown in the GUI control and the changes made through the GUI control will be reflected in the underlying data object.  The code to bind is shown below.


nameTextBox.DataBindings.Add("Text", myObject, "Name");
 


But the trouble is that I have to press Tab key to leave the TextBox before the changes can be reflected in the data object.  If I just change the text from "Name" to "Name 2", and then press the Save button without pressing the Tab key, the data object's property is still "Name".

Is there any trick to reflect the changes made in the TextBox in the data object without pressing the Tab key?

Thanks!

blackpuppy  Friday, June 24, 2005 4:40 AM

By default, a Binding will only push values to the data source on "Validation" - which occurs when a Control loses focus.  Some controls, such as menu items, don't cause the source control to lose focus and therefore don't cause validation to occur (and the value is never pushed to the data source).  You can cause the Control to push values to the DataSource when it's value changes (rather than on Validation) by changing your binding to the following:


nameTextBox.DataBindings.Add("Text", myObject, "Name", true, DataSourceUpdateMode.OnPropertyChanged);
 


In addition, you can set the "CausesValidation" flag on a Control to indicate if the act of focusing (or clicking) on the control will cause validation.  It's possibly that your "Button" has "CausesValidation" set to false (but the above solution will solve this problem as well).

You indicated you're using IEditableObject and this may cause additional issues (possibly your asking how to auto-call EndEdit() on validation).  If you're looking to auto call EndEdit() let me know and I'll post some sample code that demonstrates that.

Joe Stegman
The Windows Forms Team
Microsoft Corp.

This posting is provided "AS IS" with no warranties, and confers no rights.

Joe Stegman  Friday, June 24, 2005 2:49 PM
Hi,


Could you post the code in your save button? Maybe the problem lies there...







cheers,

Paul June A. Domag
Paul Domag  Friday, June 24, 2005 6:44 AM
In the save button's click event handler, I just assume the data object has already been updated from the GUI and then save it to the database as follows.


Trace.WriteLine("nameTextBox.Text=" + nameTextBox.Text);  // = "Name 2"
Trace.WriteLine("myObject.Name=" + myObject.Name);  // = "Name"

myObject.Save();  // do what I want to do

 


It's from these two trace statements that I see myObject.Name is not updated to "Name 2" if I do not press the Tab key to leave the TextBox.  But the TextBox's Text has already been changed to "Name 2".

In fact, here the data object should be changed and then I can save it to the database.  Do I have to manually update myObject.Name from the GUI, as shown below?


myObject.Name = nameTextBox.Text; // before saving to database
 


But the problem is if I do press Tab key, then I do not need the above line of code.
blackpuppy  Friday, June 24, 2005 7:24 AM

By default, a Binding will only push values to the data source on "Validation" - which occurs when a Control loses focus.  Some controls, such as menu items, don't cause the source control to lose focus and therefore don't cause validation to occur (and the value is never pushed to the data source).  You can cause the Control to push values to the DataSource when it's value changes (rather than on Validation) by changing your binding to the following:


nameTextBox.DataBindings.Add("Text", myObject, "Name", true, DataSourceUpdateMode.OnPropertyChanged);
 


In addition, you can set the "CausesValidation" flag on a Control to indicate if the act of focusing (or clicking) on the control will cause validation.  It's possibly that your "Button" has "CausesValidation" set to false (but the above solution will solve this problem as well).

You indicated you're using IEditableObject and this may cause additional issues (possibly your asking how to auto-call EndEdit() on validation).  If you're looking to auto call EndEdit() let me know and I'll post some sample code that demonstrates that.

Joe Stegman
The Windows Forms Team
Microsoft Corp.

This posting is provided "AS IS" with no warranties, and confers no rights.

Joe Stegman  Friday, June 24, 2005 2:49 PM
Thanks, Joe Stegman!  DataSourceUpdateMode.OnPropertyChanged does solve the problem.  You post clearly explains the ins and outs.

By default, the "CauseValidation" property of a control is True and I haven't changed that.  One thing is that my buttons are all ToolStripButton controls inside a Toolstrip control.  So these buttons including the save button does not have a "CauseValidation" property.

I'm using Rockford Lhotka's CSLA.NET framework.  The BusinessBase class implements IEditableObject.  All my data objects derive from BusinessBase.  Could you explan the additional issues associated with IEditableObject?

Thank you very much!

blackpuppy  Monday, June 27, 2005 3:24 AM

By changing the update mode to OnPropertyChanged, the Control will update the business object every time the Control value changes (rather than on Tab).  If you have another control such as a DataGridView bound to the same data, even though the data in the data source has been updated the other control will not reflect this change (even on Tab).  The reason is because controls update bound values in response to change notification (they have to receive an event that tells them the bound value has been updated).  Without IEditableObject, the business object (or business object collection) will typically fire change notification when it's value is updated - so it would work like this;

TextBox.Text changed
TextBox.TextChanged fired
Data binding see TextChanged event
Data binding pushes Text value to the Business Object
The business object property changes
The business object (or business object list) fires change notification for the changed property
Data binding sees this change notification
Data binding updates other controls that may be bound to this  property

With IEditableObject, the change notification is not fired until EndEdit is called so other controls will not update:

TextBox.Text changed
TextBox.TextChanged fired
Data binding see TextChanged event
Data binding pushes Text value to the Business Object
The business object property changes but does not fire change notification

[...]
Some other UI gesture such as a position change in a grid causes EndEdit to occur
The business object fires change notifcation
Data binding sees this change notification
Data binding updates other controls that may be bound to this  property


Joe Stegman
The Windows Forms Team
Microsoft Corp.

This posting is provided "AS IS" with no warranties, and confers no rights.



Joe Stegman  Monday, June 27, 2005 2:40 PM

I have a similar scenario where I have a bindingsource whose datasource is a collection object (List which implements csla.net) and I set the Datagridview datasource to the bindingsource. Whenever I change the value of textbox in the datagrid and click the tool strip button the property change event does not fire

BindingSource bsRelInfo = new BindingSource();

bsRelInfo.DataSource = iimWebManagement.RelInfo; //it is a list collection implementing CSLA.Net

grdRels.DataSource = bsRelInfo.List;

grdRels.DataBindings.DefaultDataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged; //Should this be done in a different way

grdRels.DataBind();

How do I force the event to fire so that the change is pushed to the underlying business object?

Sathish Calangi

Joe Stegman wrote:

By changing the update mode to OnPropertyChanged, the Control will update the business object every time the Control value changes (rather than on Tab). If you have another control such as a DataGridView bound to the same data, even though the data in the data source has been updated the other control will not reflect this change (even on Tab). The reason is because controls update bound values in response to change notification (they have to receive an event that tells them the bound value has been updated). Without IEditableObject, the business object (or business object collection) will typically fire change notification when it's value is updated - so it would work like this;

TextBox.Text changed
TextBox.TextChanged fired
Data binding see TextChanged event
Data binding pushes Text value to the Business Object
The business object property changes
The business object (or business object list) fires change notification for the changed property
Data binding sees this change notification
Data binding updates other controls that may be bound to this property

With IEditableObject, the change notification is not fired until EndEdit is called so other controls will not update:

TextBox.Text changed
TextBox.TextChanged fired
Data binding see TextChanged event
Data binding pushes Text value to the Business Object
The business object property changes but does not fire change notification

[...]
Some other UI gesture such as a position change in a grid causes EndEdit to occur
The business object fires change notifcation
Data binding sees this change notification
Data binding updates other controls that may be bound to this property


Joe Stegman
The Windows Forms Team
Microsoft Corp.

This posting is provided "AS IS" with no warranties, and confers no rights.

CCSathish  Thursday, October 05, 2006 9:27 PM

Hi, I'm looking for the auto call EndEdit() sample, how can I implement this?

Thank you!

Dominic Morin  Friday, November 17, 2006 6:40 PM

Hi,

The original postercould use a BindingSource instead of binding directly to the object's properties, andsimply call EndEdit() on the BindingSource BEFORE calling Update() on the TableAdapter. But still, if he wishes to bind directly without using a BinbingSource, he can call EndCurrentEdit() on the Binding's BindingManagerBase before the call to Update().

This way you don't need to set the Binding's DataSourceUpdateMode to "OnPropertyChanged", as this might generate a lot of trafic (the data is updated for every character entered in the TextBox by the user).

Luc

Luc Morin  Friday, November 17, 2006 7:28 PM
Did I enter the wrong place? my DataBindings.Add didn't accept more than 3 parameters.
I'm using Visutal studio 2003.
Another VB.Net Programmer  Tuesday, February 20, 2007 9:37 PM

Hi all,

This post is an old post but the subject still exists.

I think I found a pretty nice and good solution for this problem.
I also think asLuc that using"OnPropertyChanged" it's not always a good idea. from the other hand writing each time code to update the data source or end the current edit, for each button on the ToolStrip is a pain.
There for I am using a (derived) inherited ToolStrip that according to my tests solves this issue. The following is the code, I have commented the lines that are specific to my project.


using System.Windows.Forms;

using System.Drawing;

using System.ComponentModel;

namespace Client.UIControls

{

/// <summary>

///

/// </summary>

/// <remarks>Efy Teicher</remarks>

[ToolboxBitmap(typeof(ToolStrip))]

public partial class UCToolStrip : ToolStrip

{

public UCToolStrip()

{

InitializeComponent();

//this.BackgroundImage = global::Ness.Client.UIControls.Properties.Resources.SilverStyile;

//this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;

//this.Dock = System.Windows.Forms.DockStyle.Bottom;

//this.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));

//this.GripStyle = ToolStripGripStyle.Hidden;

//this.RightToLeft = RightToLeft.Yes;

this.CausesValidation = true;

}

// Let user change this property in desigen time

[Browsable(true)]

[DefaultValue(true)]

public new bool CausesValidation

{

get { return base.CausesValidation; }

set

{

base.CausesValidation=value;

}

}

/// <summary>

/// Handle any button click in order to validate focused object,

/// the object focused on the form will validate and still kip focus.

///<remarks>

///We want to make sure that controls on the containing container or even the containing form are validated, because we need them to update there Binding sources.

///</remarks>

/// </summary>

/// <param name="e"></param>

protected override void OnItemClicked(ToolStripItemClickedEventArgs e)

{

base.OnItemClicked(e);

if (base.CausesValidation)

{

var form = this.FindForm();

if (form != null)

{

form.Validate();

}

}

}

}

}

(Please leave the credit remark commentfor this part of code if using the code or copying to a different site for benefit of the community).

Now, I am happy that in the first place I have used in our project derived and wrapped objects.

This works also on TextBoxes and GridView’s that are placed on user controls and child panels.

Pay tension to the methods we used: CausesValidation (as described here: http://msdn.microsoft.com/en-us/library/system.windows.forms.toolstrip.causesvalidation.aspx) is by default ‘false�and it’s not browsble at runtime, also worser even changing the value of ToolStrip.CausesValidation at runtime did not bring the expected result and did not Cause the expected validation (as described here: http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_22967093.html ), this is why I needed to override OnItemClicked methode.

The solusion was based on this part in the ToolStrip course http://www.scribd.com/doc/7336829/Windows-Forms-ToolStrip-Course look in page 6:

Focus/Validation

Forthemostpart,whenactivatedbythemenukey(ALT),theMenuStrip/ToolStripwilltrynottotakefocusawayfromthecontrolthatiscurrentlyfocus.

IfthereisacontrolhostedwithintheMenuStriporadropdownoftheMenuStrip,theControlwillgainfocuswhentabbedto.Ingeneral,the

GotFocus/LostFocus/Enter/LeaveeventsonMenuStripmaynotfirewhenkeyboardactivated.Insuchcases,theMenuStrip.

MenuActivate,MenuStrip.MenuDeactivateeventscanbeusedinstead.

BydefaultToolStrip.CausesValidationisFalse.ValidationcanbeperformedbymanuallycallingValidate()ontheForm.

Any feedback is appreciated.

Efy

Efy T  Thursday, August 13, 2009 6:24 PM

You can use google to search for other answers

Custom Search

More Threads

• DataGridView drawing problem Application Hang
• Help me! I want when I edit value in my datagrid, press Enter...
• GridView with Radio Button
• mask in DataGridView
• Graphs in .NET
• VB2005 Check cells of DataGridView for content
• Help: DataGridView.AutoSizeRows
• stupid question
• DatagridViewTextboxCell wrap problem
• Formatting Rows in Datagrid based on data in the coresponding row of datatable