The code below illustrates some unexpected (for me!) behaviour when combining data binding and validation in winforms. Can anyone tell me how I can prevent the datasource from being updated when validation fails?
Many thanks.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace ValidationBug
{
/// <summary>
/// This illustrates some unexpected behaviour with winforms validation and binding
///
/// To reproduce: Run the program, enter a value into the textbox, click the X to close the form.
///
/// Expected behaviour: validation of textbox fails so data source is not updated.
///
/// Observed behaviour: data source is updated.
/// </summary>
public class Form1 : Form
{
private class Data
{
private string _field;
public string Field
{
get { return _field; }
set
{
// this should never be called, but it is.
_field = value;
}
}
}
private System.ComponentModel.IContainer components = null;
public Form1()
{
this.Load += new System.EventHandler(this.Form1_Load);
}
private void Form1_Load(object sender, EventArgs e)
{
AutoValidate = System.Windows.Forms.AutoValidate.EnablePreventFocu开发者_如何学JAVAsChange;
var txt = new TextBox();
// validation always fails.
txt.Validating += new CancelEventHandler((s, ev) => ev.Cancel = true);
Controls.Add(txt);
var data = new Data();
this.components = new System.ComponentModel.Container();
BindingSource bs = new BindingSource(this.components);
bs.DataSource = typeof(Data);
// only update datasource on succesful validation.
txt.DataBindings.Add(new Binding("Text", data, "Field", false, DataSourceUpdateMode.OnValidation));
}
}
}
I tend to "brute force" my code - could you set an initial value to your private string _field
, perhaps in a constructor?
Also, are you sure that setting your CancelEventHandler
's Cancel property to TRUE marks your data as invalid?
You may even want to add a private bool _valid
field to your Data class that only returns values if it is valid.
private class Data
{
private bool _valid;
private string _field;
public Data()
{
_field = null;
_valid = false;
}
public string Field
{
get
{
if (_valid)
{
return _field;
} else {
return null;
}
set
{
// this should never be called, but it is.
_field = value;
_valid = !String.IsNullOrEmpty(_field);
}
}
}
Just some ideas to look into.
精彩评论