Hi, I somehow don't get it and hopefully somebody can explain this to me and/or a solution.
I got a "smart" data source class which implements INotifyPropertyChange and IDataErrorInfo. Just for this test I have two values in this class, an int and an int?.
I validate these values, they cannot be 0 and also not null in the latter case.
So i got several questions now:
1.
- If I do not enable formatting on the DataBinding to the nullable field, I cannot enter any data. The value is reset to null when I leave the field and it should be written back to the underlying data object.
- If I disable formatting on the DataBinding, I can enter data, but cannot leave the control without entering anything.
Why is that behavior like that? I kind of would like to have a mixture of both as the user should be able to leave the control if he does not wish to enter any data, but if he enters something it should be written to the data object.
2. The validation on the UserControl is not triggered when formatting is on. Which would mean I would have to chose right now that either the user cannot enter any data, but I can use the validation to set an error message, or the user can enter data, but validation is not triggered. What am I doing wrong here?
What I want to achieve is simply to bind the nullable int to the TextBox and allow the user to enter data (if he wants) and to be able to validate it at some point in my application to show him with an ErrorProvider what he did wrong at which field - like it works with the non nullable int.
Below is the source code of this example:
Create a form with a dummy TextBox on top which will have the focus on startup. Otherwise you won't be able to press the button to trigger validation, because none of the controls will allow you to leave it without entering data (part of the questions above). One TextBox and one of the UserControl described below.
The little data source class:
public class Test : System.ComponentModel.INotifyPropertyChanged, System.ComponentModel.IDataErrorInfo
{
private int val1 = 0;
private int? val2 = null;
public int Val1
{
get { return this.val1; }
set { this.val1 = value; }
}
public int? Val2
{
get { return this.val2; }
set { this.val2 = value; }
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
#region IDataErrorInfo Members
public string Error
{
get { return String.Empty; }
}
public string this[string columnName]
{
get
{
if ((columnName == "Val1") && (val1 == 0))
return "Val1 cannot be 0";
if ((columnName == "Val2") && ( (val2 == null) || (val2 == 0) ))
return "Val1 cannot be null or 0";
return String.Empty;
}
}
#endregion
}
The user control just contains a TextBox and an ErrorProvider:
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
this.errorProvider1.SetIconAlignment(this.textBox1, ErrorIconAlignment.MiddleRight);
this.errorProvider1.SetIconPadding(this.textBox1, 2);
this.errorProvider1.BlinkStyle = System.Windows.Forms.ErrorBlinkStyle.BlinkIfDifferentError;
}
public string Value
{
get { return this.textBox1.Text; }
set { this.textBox1.Text = value; }
}
protected override void OnValidated(EventArgs e)
{
MessageBox.Show("!");
IDataErrorInfo dataErrorInfo = (this.DataBindings["Value"].DataSource as IDataErrorInfo);
this.errorProvider1.SetError(this.textBox1, dataErrorInfo[this.DataBindings["Value"].BindingMemberInfo.BindingField]);
// base.OnValidated(e);
}
The Form, as described, one dummy TextBox, one TextBox and one UserControl plus one Button to test Validation by triggering it manually:
public partial class Form1 : Form
{
private Test test = new Test();
public Form1()
{
InitializeComponent();
this.userControl11.DataBindings.Add("Value", test, "Val2", true);
this.errorProvider1.SetIconAlignment(this.textBox1, ErrorIconAlignment.MiddleRight);
this.errorProvider1.SetIconPadding(this.textBox1, 2);
this.errorProvider1.BlinkStyle = System.Windows.Forms.ErrorBlinkStyle.BlinkIfDifferentError;
this.textBox1.DataBindings.Add("Text", test, "Val2", true);
this.textBox1.Validated += new EventHandler(textBox1_Validated);
}
void textBox1_Validated(object sender, EventArgs e)
{
IDataErrorInfo dataErrorInfo = (this.textBox1.DataBindings["Text"].DataSource as IDataErrorInfo);
this.errorProvider1.SetError(this.textBox1, dataErrorInfo[this.textBox1.DataBindings["Text"].BindingMemberInfo.BindingField]);
}
private void button1_Click(object sender, EventArgs e)
{
this.ValidateChildren(ValidationConstraints.Visible);
MessageBox.Show("Val1: " + test.Val1 + " Val2: " + test.Val2);
}
}