Gonzo345
Gonzo345

Reputation: 1333

How to override an inherited control's event without having access to it?

I'm working on a project where I'm actually using inherited controls with some automated behaviour so I don't need to re-do all the job. The controls are being inherited from DevExpress controls and I've got access to the inherited controls.

I reached a point where an event was being raised and subscribing to my own method was showing no results because the inherited control executed its own code.

Inherited control:

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);
}

Own method in my form:

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

According to the documentation, I was trying to hide any message box and of course, as my inherited control source says, it was showing that message box.

So, reaching that point I guess had two options:

1.- Inheriting from that inherited control, changing the private to protected virtual and overriding that behaviour. This wasn't a choice since, for reasons I couldn't explain here I must use uniquely those inherited controls.

2.- Changing the private to public, so I could unsubscribe and subscribe again, afterwards:

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

This 2nd option is actually working fine but... let's guess none of them are doable. Changing the content of the inherited control's event is not a possibility. Leaving a part the inherited control's usage design... Which would be the best way to proceed? Could it be done using Reflection?

Upvotes: 1

Views: 539

Answers (1)

Reza Aghaei
Reza Aghaei

Reputation: 125197

The right solution should be changing the code in the base class. But since you have mentioned you don't have access to change the code of base class, and a solution using reflection is also acceptable, here I will share an example using reflection, for learning purpose.

Remove private event handler subscription from base class

I assume I have a base class called MyBaseForm and you have handled Load event using MyBaseForm_Load private method in the base class.

In this example, in a derived class MyDerivedForm which is derived from base class, I use some reflection code to remove the MyBaseForm_Load event subscription and instead, I handle the event using a new handler in the derived class MyDerivedForm_Load.

The expected behavior:

  • Before removing the event handler, you will see two message boxes
  • After removing the event handler using eventInfo.RemoveEventHandler, you will see just a single message box, from the derived class event handler.

Here is the code:

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");
    }
}

Upvotes: 1

Related Questions