Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何覆盖继承的控件';在没有访问权限的情况下发生的事件?_C#_.net_Winforms_Event Handling - Fatal编程技术网

C# 如何覆盖继承的控件';在没有访问权限的情况下发生的事件?

C# 如何覆盖继承的控件';在没有访问权限的情况下发生的事件?,c#,.net,winforms,event-handling,C#,.net,Winforms,Event Handling,我正在做一个项目,在这个项目中,我实际上使用了一些自动行为的继承控件,所以我不需要重新做所有的工作。这些控件是从DevExpress控件继承的,我可以访问继承的控件 我到达了一个触发事件的点,订阅我自己的方法没有显示任何结果,因为继承的控件执行它自己的代码 继承控制: private void BinaryGridView_InvalidRowException(object sender, InvalidRowExceptionEventArgs e) { e.ExceptionMod

我正在做一个项目,在这个项目中,我实际上使用了一些自动行为的继承控件,所以我不需要重新做所有的工作。这些控件是从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; };
根据,我试图隐藏任何消息框,当然,正如我继承的控制源所说,它正在显示该消息框

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

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

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

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

第二个选项实际上运行良好,但是。。。让我们猜猜它们都不可行。无法更改继承控件事件的内容。将部分保留为继承控件的使用设计哪种方法是最好的继续进行?是否可以使用
反射

正确的解决方案应该是更改基类中的代码。但是,既然您已经提到,您无法更改基类的代码,而且使用反射的解决方案也是可以接受的,那么为了学习的目的,我将在这里分享一个使用反射的示例

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

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

在本例中,在从基类派生的派生类
MyDerivedForm
中,我使用一些反射代码删除
MyBaseForm\u Load
事件订阅,而是使用派生类
MyDerivedForm\u 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");
    }
}

BinaryGridView\u InvalidRowException
是唯一订阅的事件,然后您可以将
grwWhatever.InvalidRowException
分配给
null
。在这种情况下,无需将访问器类型更改为
public
。如果
ExceptionMode
NoAction
值,因为您总是意味着不显示消息框,那么只需转到继承的控件并在消息框之前添加if语句:
if(e.ExceptionMode==ExceptionMode.NoAction)
。在继承的控件中,如果可能,最好将
OnInvalidRoweException
重写为扩展,而不是使用事件处理程序。如果
BinaryGridView\u InvalidRoweException
是订阅到继承控件中的事件的事件处理程序,则无法更改继承的控件代码,然后你不能阻止它工作。是的,有一个解决方案是使用反射。我将发布一个使用
Form
类及其
Load
事件的示例。就是这样!我可以选择在继承的控件中更改代码,因为我有源代码,但我很好奇在一个不可能的场景中如何做到这一点。这太棒了。如果您可以更改基类代码,那么最好按照我在问题下面发布的注释进行操作:)