用户控件中未调用重写事件

时间:2019-02-10 03:23:29

标签: c# .net winforms events user-controls

我有一个带有TextBox的用户控件:

public partial class MyControl : UserControl
{
    public new event CancelEventHandler Validating
    {
        add
        {
            txt.Validating += value;
        }
        remove
        {
            txt.Validating -= value;
        }
    }

    public new string Text
    {
        get => txt.Text;
        set => txt.Text = value;
    }
}

我将控件和ErrorProvider放在表单上,​​然后执行以下操作:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        SetErrorEvents(myControl1);
    }

    private void SetErrorEvents(object control)
    {
        (control as Control).Validating += ValidationEvent;
    }

    private void ValidationEvent(object sender, CancelEventArgs e)
    {
        var control = (Control)sender;

        if (string.IsNullOrWhiteSpace(control.Text))
            errorProvider1.SetError(control, "error");
        else
            errorProvider1.SetError(control, string.Empty);
    }
}

在为我的控件的Validating事件设置委托时,它是为UserControl本身设置委托,并且不会被覆盖,因此将设置TextBox的事件。 / p>

以上工作不是应该的吗?我想念什么?

2 个答案:

答案 0 :(得分:2)

它未被覆盖,已被new关键字遮盖或隐藏。您尚未订阅新事件,您已经订阅了基类事件。基本上就是polymorphism的工作方式。

  • 如果要在验证子控件时引发用户控件的Validating事件,请处理该子控件的Validating事件并调用该控件的OnValidating方法用户控制。

  • 如果您要覆盖Validating事件覆盖OnValidating方法。

  • 如果要更改Validating事件的发送者,则需要更改Validating事件的调用方式。为此,您需要使用反射并找到事件,然后直接自己调用它。

示例-子控件验证时引发UserControl的验证事件

如果您希望在验证子文本框时引发控件的Validating事件,请处理子控件的Validating事件并调用``

public MyControl()
{
    InitializeComponent();
    txt.Validating += (obj, args) => OnValidating(args);
}

示例-覆盖验证事件

protected override void OnValidating(CancelEventArgs e)
{       
    // Add custom code here.       
    base.OnValidating(e);
}

示例-手动引发Validating事件而无需调用base.OnValidating

如果由于某种原因您不想调用base.OnValidating,而它的职责基本上是引发Validating事件,则可以找到该事件并直接调用它:

protected override void OnValidating(CancelEventArgs e)
{  
    var f = typeof(Control).GetField("EventValidating",
            System.Reflection.BindingFlags.NonPublic |
            System.Reflection.BindingFlags.Static);
    var validating = (CancelEventHandler)Events[f.GetValue(this)];
    validating?.Invoke(this, e); 
}

例如,您可以设置另一个发件人,例如子控件,而不是this

答案 1 :(得分:1)

定义此接口:

public interface IMyControl
{
    event CancelEventHandler Validating;
}

将界面应用于自定义控件:

public partial class MyControl : UserControl, IMyControl
{
    ...
}

在您的Form类中,更新SetErrorEvents(),以便将其强制转换为IMyControl

...
private void SetErrorEvents(object control)
{
    (control as IMyControl).Validating += ValidationEvent;
}
...