簡體   English   中英

我可以在父表單中知道繼承的表單是否訂閱了 Show 事件嗎?

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

我的 winforms 框架中有以下表單

  • FormBase(繼承自 Form)
  • FormBaseList(繼承自 FormBase)
  • FormBaseDetail(繼承自 FormBase)

現在應用程序中的每個表單都繼承自上述 3 個表單之一。
例如FormCustomerList將從FormBaseList繼承

現在在FormBaseList存在事件FormBaseList_Shown (通過在 VS 的屬性窗口中雙擊它)

我想在FormBaseList_Show的代碼中知道是否存在事件FormCustomerList_Show (再次通過在屬性窗口中雙擊它)。

這甚至可能嗎?

那我為什么要這個?
因為框架中的某些更改要求表單不再使用Shown事件,而是使用自定義事件。
如果開發人員向表單添加Show事件,我想捕獲並向其顯示警告,如果確實需要,他可以設置一個屬性來隱藏此警告。
這個警告不需要在設計時顯示,在運行時就足夠了。 但如果它可能在設計時,那將是一個獎勵。
那么可以做到這一點嗎,也許有更好的方法來做到這一點?

我希望這個解釋是清楚的

編輯

這個想法是,當開發人員使用 Show 事件時,他必須得到警告(在設計時或運行時)。 如果他覺得他真的需要 Show 方法,他應該能夠為這個特定的表單設置警告

您應該隱藏Shown事件並以這種方式棄用:

[Obsolete("Shown event is deprecated.")]
public new event EventHandler Shown
{
    add { base.Shown += value; }
    remove { base.Shown -= value; }
}

您已將其標記為已過時,並且在構建解決方案時,它將在編譯時在“ 錯誤列表”窗口中顯示警告。

訂閱基本的原始Shown事件,該事件也將按預期運行。

要禁用該警告,請在已訂閱該事件的表單的designer.cs文件頂部添加以下代碼行:

#pragma warning disable CS0618 // Type or member is obsolete

並將此行添加到底部:

#pragma warning restore CS0618 // Type or member is obsolete

注意:在其他文件中,除了designer.cs文件之外,僅用#pragma包圍事件處理程序訂閱就足夠了。 但是對於designer.cs,您不能包圍事件處理程序訂閱,因為通過更改設計器中的任何內容, InitializeComponent的內容和定義成員變量的代碼塊將自動生成,而您在designer.cs中的所有手動更改將被自動生成。丟失。 但是,如果將#pragma放在文件的頂部和底部,則它是安全的,不會從designer.cs中刪除。

要在運行時引發異常或顯示消息框,您可以使用以下選項:

  • 遮蔽Shown事件,並在add部分中引發異常(除非已設置skip標志)。
  • 使用反射查找Shown事件的事件處理程序列表,並檢查是否有附加到該事件的處理程序。

在這兩種解決方案中,都可以使用布爾屬性覆蓋派生形式的行為。

選項1-顯示陰影事件並添加要add的代碼

您可以隱藏Shown事件,並在add訪問器中添加代碼以顯示消息框,或者如果向事件添加了處理程序,則拋出異常。

在下面的示例中,我將ThrowExceptionOnSubscribingShownEvent屬性添加到基本形式,默認情況下為true ,這意味着在訂閱Shown事件時會引發異常。

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

選項2-查找所Shown事件的事件處理程序列表

作為運行時的選項,您可以重寫OnShown方法並使用反射,獲取EVENT_SHOWN字段並使用它,獲取Shown事件的事件處理程序列表。 然后您可以檢查事件處理程序列表是否不為空,引發異常。

在下面的示例中,我將ThrowExceptionOnSubscribingShownEvent屬性添加到基本形式,默認情況下為true ,這意味着在訂閱Shown事件時會引發異常。 您可以在需要時以派生形式將其設置為false

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

使用反射可能是可能的,但是會很混亂。 更好的策略是隱藏Shown事件,如下所示:

        [Obsolete("Don't use this event, use my custom one")]
        public new event EventHandler Shown;

然后,任何嘗試使用此事件的事件都會生成編譯器警告。

除了布萊斯·瓦格納(Bryce Wagner)的答案之外,您還可以在屬性窗口和編輯器中隱藏“顯示的事件”,使其不顯示:

    [Obsolete("Don't use this event, use my custom one")]
    [System.ComponentModel.EditorBrowsable(EditorBrowsableState.Never)] // Hide from editor
    [System.ComponentModel.Browsable(false)] // Hide from properties window
    public new event EventHandler Shown;

EditorBrowsable似乎僅適用於從其他解決方案導入的dll

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM