(一)、引言
之前在园中anderslly的博客看到两篇文章:写的很好。
Windows Forms中通过自定义组件实现统一的数据验证(一)
Windows Forms中通过自定义组件实现统一的数据验证(二)
小菜在其基础上修改了代码就成了小菜在TaskVision中使用的自定义数据验证控件了。
(二)、完成效果
点击登录,文本框为空的地方会显示错误提示信息。
代码下载:https://files.cnblogs.com/a-peng/SmartClient_Chapter04.rar
(三)、分析
1、不使用自定义数据验证控件,直接使用ErrorProvider
public partial class LoginForm : Form
{
public LoginForm()
{
InitializeComponent();
}
private void LoginForm_Load(object sender, EventArgs e)
{
lblVersion.Text = "Version " + Application.ProductVersion;
}
private void btnOk_Click(object sender, EventArgs e)
{
if (txtUserName.Text.Trim() != string.Empty && txtPassword.Text.Trim() != string.Empty)
{
MessageBox.Show("通过验证");
}
else
{
MessageBox.Show("未通过验证");
}
}
private void btnCancel_Click(object sender, EventArgs e)
{
this.Close();
}
private void txtUserName_Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
if (txtUserName.Text.Trim() == string.Empty)
{
errorProvider.SetError(txtUserName, "请您输入帐号后登录");
}
else
{
errorProvider.SetError(txtUserName, null);
}
}
private void txtPassword_Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
if (txtPassword.Text.Trim() == string.Empty)
{
errorProvider.SetError(txtPassword, "请您输入密码后登录");
}
else
{
errorProvider.SetError(txtPassword, null);
}
}
}运行:
弹出未通过验证,不过效果不太理想,界面中只有帐号文本框旁边显示了错误信息。
这是由于,ErrorProvider只验证获得焦点的控件,密码文本框还未获得焦点,所以不会提示错误。
我们可以修改btnOk_Click代码
注意下面是错误的代码:
private void btnOk_Click(object sender, System.EventArgs e)
{
bool isValidate = true;
Control[] controls = new Control[] { txtUserName, txtPassword };
foreach (Control control in controls)
{
control.Focus();
if (!this.Validate())
{
isValidate = false;
}
}
if (isValidate)
{
MessageBox.Show("通过验证");
}
else
{
MessageBox.Show("未通过验证");
}
}运行:
噢,我的天呐,竟然弹出通过验证!!!为什么呢?this.Validate()永远是true。不知道这是为何!!!不知道是不是bug
所以小菜妥协修改为下面的代码:
private void btnOk_Click(object sender, System.EventArgs e)
{
Control[] controls = new Control[] { txtUserName, txtPassword };
foreach (Control control in controls)
{
control.Focus();
this.Validate();
}
if (txtUserName.Text.Trim() != string.Empty && txtPassword.Text.Trim() != string.Empty)
{
MessageBox.Show("通过验证");
}
else
{
MessageBox.Show("未通过验证");
}
}运行:
现在基本满意了。不过在LoginForm代码中出现了很多与验证相关的代码,txtUserName_Validating中,txtPassword_Validating中,包括btnOk_Click中也存在与验证相关的代码。
在WinForm中,我们很经常面对如下需求,添加数据,提交,如果文本框的数量很多,那xxxx_Validating就会很多,我们完全可以将其封装成控件使用。
2、自定义数据验证控件
三个控件,一个类
BaseValidator数据验证基控件
RequiredFieldValidator验证非空控件继承BaseValidator
FormValidator窗体验证控件
ValidatorManager验证控件集合管理类,可以将验证控件与指定的窗体关联。
我们先来使用一下:
往LoginForm窗体中拉入两个自定义RequiredFieldValidator控件。
rfvUserName指定属性ControlToValidate为txtUserName,ErrorMessage为“请您输入帐号后登录”
rfvPassword指定属性ControlToValidate为txtPassword,ErrorMessage为“请您输入密码后登录”
往LoginForm窗体中拉入FormValidator控件名称fvLoginForm
在LoginForm.design.cs的相关代码如下:
//
// rfvUserName
//
this.rfvUserName.ControlToValidate = this.txtUserName;
this.rfvUserName.ErrorMessage = "请您输入帐号后登录";
this.rfvUserName.IsValid = false;
//
// rfvPassword
//
this.rfvPassword.ControlToValidate = this.txtPassword;
this.rfvPassword.ErrorMessage = "请您输入密码后登录";
this.rfvPassword.IsValid = false;
//
// fvLoginForm
//
this.fvLoginForm.HostingForm = this;
这样我们的LoginForm代码如下:
public partial class LoginForm : Form
{
public LoginForm()
{
InitializeComponent();
}
private void LoginForm_Load(object sender, EventArgs e)
{
lblVersion.Text = "Version " + Application.ProductVersion;
}
private void btnOk_Click(object sender, System.EventArgs e)
{
if (fvLoginForm.IsValid)
{
MessageBox.Show("通过验证");
}
else
{
MessageBox.Show("未通过验证");
}
}
private void btnCancel_Click(object sender, EventArgs e)
{
this.Close();
}
}
BaseValidator控件,数据验证基控件。
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
namespace TaskVision
{
public abstract class BaseValidator : Component, ISupportInitialize
{
private Control m_controlToValidate; // 需要验证的控件
private ErrorProvider m_errorProvider = new ErrorProvider();
private string m_errorMessage; //错误信息
private bool m_isValid = false; //是否通过验证
public Control ControlToValidate
{
get { return m_controlToValidate; }
set { m_controlToValidate = value; }
}
public string ErrorMessage
{
get { return m_errorMessage; }
set { m_errorMessage = value; }
}
public bool IsValid
{
get { return m_isValid; }
set { m_isValid = value; }
}
public void Validate()
{
// 验证控件。
m_isValid = EvaluateIsValid();
if (!m_isValid)
{
m_errorProvider.BlinkStyle = ErrorBlinkStyle.NeverBlink; // 不闪烁
m_errorProvider.SetError(m_controlToValidate, m_errorMessage);
}
else
{
m_errorProvider.SetError(m_controlToValidate, null);
}
}
//交由具体验证控件实现
protected abstract bool EvaluateIsValid(); 
初始化
}
}
RequiredFieldValidator控件判断不为空,继承BaseValidator控件。
using System;
namespace TaskVision
{
public class RequiredFieldValidator : BaseValidator
{
protected override bool EvaluateIsValid()
{
if (ControlToValidate.Text.Trim() == string.Empty)
return false;
else
return true;
}
}
}
验证控件集合:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace TaskVision
{
public class ValidatorManager
{
private static Dictionary<Form, List<BaseValidator>> m_validators; //需要验证的控件集合
public static List<BaseValidator> GetValidators(Form form)
{
return m_validators[form];
}
public static void AddValidator(Form form, BaseValidator validator)
{
if (m_validators == null)
{
m_validators = new Dictionary<Form, List<BaseValidator>>();
}
if (!m_validators.ContainsKey(form))
{
m_validators.Add(form, new List<BaseValidator>());
}
m_validators[form].Add(validator);
}
public static void RemoveValidator(Form form, BaseValidator validator)
{
m_validators[form].Remove(validator);
if (m_validators[form].Count == 0)
{
m_validators.Remove(form);
}
}
}
}
FormValidator控件,窗体验证控件。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Windows.Forms;
namespace TaskVision
{
public class FormValidator : Component
{
private Form m_hostForm;
[Browsable(false)]
[DefaultValue(null)]
public Form HostingForm
{
get
{
if ((m_hostForm == null) && this.DesignMode)
{
IDesignerHost designer = this.GetService(typeof(IDesignerHost)) as IDesignerHost;
if (designer != null) // 获取用作当前设计的根组件的基类的实例
m_hostForm = designer.RootComponent as Form;
}
return m_hostForm;
}
set
{
if (!this.DesignMode && (m_hostForm == null))
{
m_hostForm = value;
}
}
}
public bool IsValid
{
get
{
List<BaseValidator> validators = ValidatorManager.GetValidators(m_hostForm);
bool isValid = true;
foreach (BaseValidator validator in validators)
{
validator.Validate();
if (validator.IsValid == false)
isValid = false;
}
return isValid;
}
}
}
}
作者:a-peng
出处:http://a-peng.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出
原文连接,否则保留追究法律责任的权利。
*************************************************************************


浙公网安备 33010602011771号