我的winforms框架中有以下表单
现在,应用程序中的每个表单都继承自上述3种表单之一。
例如FormCustomerList
将继承自FormBaseList
现在FormBaseList
中存在事件FormBaseList_Shown
(通过在VS的属性窗口中双击该事件)
我想在FormBaseList_Show
的代码中知道是否存在事件FormCustomerList_Show
(再次在属性窗口中双击该事件)。
那有可能吗?
那我为什么要这个?
因为框架中的某些更改要求表单不再使用Shown
事件,而是使用自定义事件。
如果开发人员在表单中添加了Show
事件,我想捕获并向其显示警告,如果确实需要,他可以设置一个属性来隐藏此警告。
在设计时不需要显示此警告,在运行时就足够了。但是,如果在设计时可行,那将是一个好处。
那么可以做到这一点,也许有更好的方法吗?
我希望这个解释清楚
编辑
这个想法是,当开发人员使用Show事件时,他必须得到警告(在设计时或运行时)。如果他认为他确实需要Show方法,那么他应该能够对此特定表格设置警告
答案 0 :(得分:1)
您应该隐藏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
的内容和定义成员变量的代码块将自动生成,并且您在设计器中的所有手动更改.cs将丢失。但是,如果将#pragma
放在文件的顶部和底部,则它是安全的,不会从designer.cs中删除。
答案 1 :(得分:1)
要在运行时引发异常或显示消息框,您可以使用以下选项:
Shown
事件,并在add
部分中引发异常(除非已设置跳过标志)。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);
}
}
答案 2 :(得分:0)
使用反射可能是可能的,但是会很混乱。更好的策略是隐藏Shown事件,如下所示:
[Obsolete("Don't use this event, use my custom one")]
public new event EventHandler Shown;
然后,任何尝试使用此事件的事件都会生成编译器警告。
答案 3 :(得分:0)
除了布莱斯·瓦格纳(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