如何在没有访问权限的情况下覆盖继承的控件的事件?

时间:2019-11-28 08:09:29

标签: c# .net winforms event-handling

我正在一个项目中,我实际上正在使用具有某些自动行为的继承控件,因此不需要重新做所有工作。这些控件是从DevExpress控件继承而来的,我可以访问这些继承的控件。

我到达了一个引发事件的地方,订阅我自己的方法没有显示任何结果,因为继承的控件执行了自己的代码。

继承的控件:

private void BinaryGridView_InvalidRowException(object sender, InvalidRowExceptionEventArgs e)
{
    e.ExceptionMode = DevExpress.XtraEditors.Controls.ExceptionMode.NoAction;
    DevExpress.XtraEditors.XtraMessageBox.Show(e.ErrorText, "Atención", MessageBoxButtons.OK, MessageBoxIcon.Error);
}

我自己的表单中的方法:

grwWhatever.InvalidRowException += (s, e) => { e.ExceptionMode = ExceptionMode.NoAction; };

根据documentation,我试图隐藏任何消息框,当然,正如我继承的控制源所说,它正在显示该消息框。

因此,达到这一点我想有两种选择:

1.-从继承的控件继承,将private更改为protected virtual并覆盖该行为。这不是一个选择,因为出于某种原因,我无法在此处解释我必须唯一地使用那些继承的控件

2.--将private更改为public,以便随后可以取消订阅并再次订阅:

grwWhatever.InvalidRowException -= grwWhatever.BinaryGridView_InvalidRowException;
grwWhatever.InvalidRowException += (s, e) => { e.ExceptionMode = ExceptionMode.NoAction; };

这个第二个选项实际上工作正常,但是...让我们猜测它们都不可行。更改继承控件事件的内容是不可能的。留下继承控件的用法设计的一部分... 哪种方法是最好的进行方法?可以使用Reflection完成吗?

1 个答案:

答案 0 :(得分:1)

正确的解决方案应该是更改基类中的代码。但是,由于您已经提到您无权更改基类的代码,并且使用反射的解决方案也是可以接受的,因此在这里,我将分享一个使用反射的示例,用于学习目的

从基类中删除私有事件处理程序订阅

我假设我有一个名为MyBaseForm的基类,并且您已经在基类中使用Load私有方法处理了MyBaseForm_Load事件。

在此示例中,在派生自基类的派生类MyDerivedForm中,我使用一些反射代码删除了MyBaseForm_Load事件订阅,而是使用了一个新的处理程序来处理事件派生类MyDerivedForm_Load

预期行为:

  • 在删除事件处理程序之前,您将看到两个消息框
  • 使用eventInfo.RemoveEventHandler删除事件处理程序后,您将仅从派生类事件处理程序中看到一个消息框。

代码如下:

public class MyBaseForm : Form
{
    public MyBaseForm()
    {
        this.Load += MyBaseForm_Load;
    }
    private void MyBaseForm_Load(object sender, EventArgs e)
    {
        MessageBox.Show("MyBaseForm_Load");
    }
}

public class MyDerivedForm : MyBaseForm
{
    public MyDerivedForm()
    {
        var eventInfo = this.GetType().GetEvent("Load",
            System.Reflection.BindingFlags.Public |
            System.Reflection.BindingFlags.Instance);
        var delegateType = eventInfo.EventHandlerType;
        eventInfo.RemoveEventHandler(this, 
            Delegate.CreateDelegate(delegateType, this, "MyBaseForm_Load", false, true));

        this.Load += MyDerivedForm_Load;
    }

    private void MyDerivedForm_Load(object sender, EventArgs e)
    {
        MessageBox.Show("MyDerivedForm_Load");
    }
}