在自定义TextBox控件的构造函数中添加验证事件处理程序

本文关键字:添加 验证 事件处理 程序 构造函数 自定义 TextBox 控件 | 更新日期: 2023-09-27 18:16:26

我创建了一个继承自TextBox的自定义控件。

我有一个ValidateTextBoxEntry方法,由验证事件调用。

通常,我会使用可视化编辑器中的属性编辑器将ValidateTextBoxEntry添加到每个自定义控件实例的验证事件中。

相反,我宁愿在自定义控件的构造函数中自动向所有事件处理程序添加一行,类似于:
    public CustomTextBox()
    {
        InitializeComponent();
        this.Validating += 
        new System.ComponentModel.CancelEventHandler(ValidateTextBoxEntry);
   }
向自定义控件的所有实例添加验证事件处理程序的优雅方法是什么?

在自定义TextBox控件的构造函数中添加验证事件处理程序

    this.Validating += 
    new System.ComponentModel.CancelEventHandler(ValidateTextBoxEntry);

这是不优雅的。. net中的事件是观察者模式的一种实现。您将它们公开,以便其他代码可以订阅事件,并在本例中自定义验证。听你自己的事件是没有意义的。

为了适应,每个Xxxx事件都有一个OnXxxx()方法。您可以自己调用此方法以引发validation事件。或者,在这种情况下更常见的是,让Winforms为您调用它。一个示例实现如下所示:

    protected override void OnValidating(CancelEventArgs e) {
        if (this.Text.Length == 0) e.Cancel = true;
        else base.OnValidating(e);
        DisplayWarning(e.Cancel);
    }

注意这里的事件处理是如何定制的。它实现了永远不能在文本框中有一个空字符串的规则。此时就没有理由再调用base. onvalidate()了,您不希望事件处理程序覆盖该规则。并进一步扩展,自动处理显示提示给用户,他的数据输入需要处理。

这样做可以让你控制代码运行的顺序,这是非常重要的。

我同意elgonzo在评论中的观点,这可能不是正确的方法,但我认为你可以用interface实现它。

如果您定义了一个包含处理程序定义的接口,并使每个表单实现该接口,那么如果您可以找到正确的表单,则可以从控件中连接处理程序。你可以继续迭代Parent属性直到它为空。但我真的觉得不值得这么做:

//the interface
public interface IShouldntDoThis
{
    void MyTextBox_Validating(object sender, CancelEventArgs e);
}
//the control
public class MyTextBox : TextBox
{
    public MyTextBox()
    {
    }
    protected override void InitLayout()
    {
        base.InitLayout();
        Control parent = this.Parent;
        while (parent.Parent != null)
        {
            parent = parent.Parent;
        }
        //parent should now be the Form
        IShouldntDoThis test = parent as IShouldntDoThis;
        if (test != null)
        {
            this.Validating += test.MyTextBox_Validating;
        }
    }
}
//the form
public partial class MainForm : Form, IShouldntDoThis
{
    public Form1()
    {
        InitializeComponent();
    }
    public void MyTextBox_Validating(object sender, CancelEventArgs e)
    {
        throw new NotImplementedException();
    }
}

嗯,事实证明,在构造函数中添加一行(如我在问题中所示),正确的方法(如elgonzo所述-谢谢)。

关键是要使事件处理程序成为类本身的一个方法。