博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

TaskVision自定义数据验证控件

Posted on 2008-10-07 20:55  a-peng  阅读(831)  评论(0)    收藏  举报

(一)、引言
之前在园中anderslly的博客看到两篇文章:写的很好。
Windows Forms中通过自定义组件实现统一的数据验证(一)
Windows Forms中通过自定义组件实现统一的数据验证(二)

小菜在其基础上修改了代码就成了小菜在TaskVision中使用的自定义数据验证控件了。

(二)、完成效果
image
点击登录,文本框为空的地方会显示错误提示信息。

代码下载: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);
        }

    }

}

运行:
 image
弹出未通过验证,不过效果不太理想,界面中只有帐号文本框旁边显示了错误信息。
这是由于,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(
"未通过验证");
    }
   
}

运行:
image
噢,我的天呐,竟然弹出通过验证!!!为什么呢?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(
"未通过验证");
    }

}

运行:
image
现在基本满意了。不过在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
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出
原文连接,否则保留追究法律责任的权利。
*************************************************************************