By default, simple binding updates a bound data source property
value as part of Control validation. Control validation occurs when a Control
loses focus which occurs when a user Tabs or Clicks off a Control (see Controlling
the Binding Operation for more information). If an error occurs as part of
the validation process, Windows Forms will cancel the validation and focus will
not move to the next Control. For example, assume you bind a TextBox "Text"
property to an integer property on a data source. When s user Tabs off the
TextBox, validation occurs and the data binding engine (Binding type) will
attempt to update the data source property with the bound Control value
(TextBox.Text). If an error (exception) occurs as part of the data source
update, the default behavior of the binding engine is to fail validation which
prevents focus from leaving the TextBox.
It is important to note that if an error occurs then the
binding engine must assume that the value displayed to the user (TextBox.Text)
is inconsistent with the value in the data source property. In this scenario
it is important to neither make it appear as if the binding was successful
(silently fail) or display an intrusive dialog. For this reason, the default
behavior is to "trap" the user on the Control until they enter a successful
value.
Sample: Using an ErrorProvider
and ToolTip to show error status (VS 2005) (VS Project: SimpleBindingTabIssue)
In VS 2005 there are two ways you
can provide feedback to a user when a binding error occurs. The easiest way is
to add an ErrorProvider to the Form and set ErrorProvider.DataSource to the
same data source used by the Binding. In addition, you can also add a handler
to the BindingComplete event for the Binding and write your own customer error
handling logic. In the sample below, the custom logic shows a ToolTip:
/*******************************************************************
* Setup (using the Visual Studio Form designer):
*
* Add 1 TextBox to the Form (textBox1)
* Add 2 CheckBoxes to the Form (showErrorToolTipCB
* and showErrorProviderCB)
*
* Add the following public property to the Form class:
*
* private int _intValue;
*
* public int IntegerValue
* {
* get { return _intValue; }
* set { _intValue = value; }
* }
*
* Add the following code to the Form.Load event:
******************************************************************/
ToolTip errorTT = new ToolTip();
ErrorProvider ep = new ErrorProvider(this);
Binding tbBinding = new Binding("Text", this, "IntegerValue", true);
/* Add binding */
this.textBox1.DataBindings.Add(tbBinding);
/* Hook BindingComplete to allow navigation */
tbBinding.BindingComplete += delegate(object bind, BindingCompleteEventArgs args)
{
if ((this.showErrorToolTipCB.Checked) && !String.IsNullOrEmpty(args.ErrorText))
{
/* Show ToolTip */
errorTT.Show(args.ErrorText, this.textBox1, 2000);
}
};
this.showErrorProviderCB.CheckedChanged += delegate
{
ep.DataSource = (this.showErrorProviderCB.Checked ? this : null);
};
/* Initialize ToolTip */
errorTT.IsBalloon = true;
errorTT.ToolTipTitle = "Binding Error:";
/* Initialize ErrorProvider */
ep.BlinkStyle = ErrorBlinkStyle.NeverBlink;
}
Sample: Allowing a user to Tab
off a Control when a binding error occurs (VS 2005) (VS Project: SimpleBindingTabIssue)
Control validation occurs when a
Control loses focus (see Controlling the Binding Operation for more
information). When the user Tabs off the TextBox, validation occurs and the
data binding engine (Binding type) will attempt and update the data source
property with the bound Control value (TextBox.Text). If an exception occurs,
validation will fail and the focus will not leave the bound Control. To allow
focus to leave, you can add a BindingComplete event handler and set e.Cancel to
false:
/*******************************************************************
* Setup (using the Visual Studio Form designer):
*
* Add 1 TextBox to the Form (textBox1)
*
* Add the following public property to the Form class:
*
* private int _intValue;
*
* public int IntegerValue
* {
* get { return _intValue; }
* set { _intValue = value; }
* }
*
* Add the following code to the Form.Load event:
******************************************************************/
Binding tbBinding = new Binding("Text", this, "IntegerValue", true);
/* Add binding */
this.textBox1.DataBindings.Add(tbBinding);
/* Hook BindingComplete to allow navigation */
tbBinding.BindingComplete += delegate(object bind, BindingCompleteEventArgs args)
{
/* Allow user to Tab off */
args.Cancel = false;
};
}