Search code examples
c#winformsinheritancevisual-inheritance

Can i know in the parent Form if an inherited Form has subscribed to the Show event?


I have the following forms in my winforms framework

  • FormBase (inherited from Form)
  • FormBaseList (inherited from FormBase)
  • FormBaseDetail (inherited from FormBase)

Now every form in the application inherits from on one of the 3 above.
For example FormCustomerList will be inherited from FormBaseList

Now in FormBaseList the event FormBaseList_Shown is present (by doubleclicking on it in the properties window in VS)

What I would like to know in the code from FormBaseList_Show is if there is an event FormCustomerList_Show present (again by doubleclick on it in the properties window).

Is that even possible ?

So why do I want this ?
Because some changes in the framework require the forms to not use the Shown event anymore but a custom event.
I would like to catch and show a warning to the developer if he adds a Show event to a form, and if it is really needed he can set a property that will hide this warning.
This warning does not needs to be shown at designtime, at runtime would be enough. But if its possible at designtime that would be a bonus.
So can this be done and is there maybe a better way to do this ?

I hope this explanation is clear

EDIT

The idea is that when a developer makes use of a Show event he must get a warning (either at designtime or runtime). If he feels that he really needs the Show method he should be able to set the warning off for this particular form


Solution

  • To throw exception or show a message box at run-time you have the following options:

    • Shadow the Shown event and in the add part, throw an exception (unless the skip flag has been set).
    • Using reflection find the event handler list for Shown event and check if there is a handler attached to the event.

    In both solutions, a boolean property can be used to override the behavior in derived forms.

    Option 1 - Shadowing Shown event and add the code to add

    You can shadow the Shown event and in the add accessor, add a code to show a message box or throw exception if a handler added to the event.

    In the following example, I've added ThrowExceptionOnSubscribingShownEvent property to the base form which is true by default which means it throws the exception on subscribing the Shown event.

    public bool ThorwExceptionOnSubscribingShownEvent { get; set; } = true;
    
    public new event EventHandler Shown
    {
        add
        {
            if (ThorwExceptionOnSubscribingShownEvent)
                throw new InvalidOperationException("Shown event is deprecated.");
    
            base.Shown += value;
        }
        remove
        {
            base.Shown -= value;
        }
    }
    

    Option 2 - Finding event handler list for Shown event

    As an option for run-time, you can override OnShown method and using reflection, get EVENT_SHOWN field and using it, get the event handler list of Shown event. Then you can check if the event handler list is not empty, throw an exception.

    In the following example, I've added ThrowExceptionOnSubscribingShownEvent property to the base form which is true by default which means it throws the exception on subscribing the Shown event. You can set it to false when needed in derived forms:

    public partial class BaseForm : Form
    {
        public BaseForm()
        {
            InitializeComponent();
        }
    
        public bool ThrowExceptionOnSubscribingShownEvent { get; set; } = true;
        protected override void OnShown(EventArgs e)
        {
            if (!DesignMode)
            {
                var EVENT_SHOWN = typeof(Form).GetField("EVENT_SHOWN",
                    BindingFlags.NonPublic | BindingFlags.Static)
                    .GetValue(null);
                var handlers = Events[EVENT_SHOWN]?.GetInvocationList();
                if (ThrowExceptionOnSubscribingShownEvent && handlers?.Length > 0)
                    throw new InvalidOperationException("Shown event is deprecated.");
            }
            base.OnShown(e);
        }
    }