[英]Can i know in the parent Form if an inherited Form has subscribed to the Show event?
我的 winforms 框架中有以下表單
現在應用程序中的每個表單都繼承自上述 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.