2008-09-18 23 views
12

我很喜欢自己在这里的一个角落。在C#中继承事件处理程序#

我有一系列的UserControl继承自一个父级,它包含一些方法和事件来简化事情,所以我不必写行和几乎相同的代码行。像你一样做。父级不包含其他控件。

我想要做的只是在父UserControl中有一个事件处理程序,它去做只有父控件才能做的事情(即有条件地调用一个事件,因为事件在父级中定义) 。然后,我会将此事件处理程序连接到我的子控件中的所有输入框,并且子控件将排除解析输入并告知父控件是否抛出该事件的任务。不错,干净,没有重复,复制粘贴代码(对我来说总是会导致错误)。

这是我的问题。 Visual Studio认为我太聪明了一半,并警告说“方法'CheckReadiness'[父项中的事件处理程序]不能成为事件的方法,因为这个类派生出来的类已经定义了该方法。”是的,Visual Studio,这就是要点。我想想要有一个事件处理程序,它只处理子类抛出的事件,它的唯一工作就是使我能够连接子程序而不必编写一行代码。我不需要那些额外的处理程序 - 我需要的所有功能自然就是在儿童处理用户输入时调用的。

我不知道为什么Visual Studio现在开始抱怨这件事(因为它让我这么做),我不知道如何让它消失。最好,我想这样做,而不必定义一个只调用CheckReadiness的方法。是什么引起了这个警告,是什么导致它在不是一个小时之前就出现了,我怎样才能让它消失,而不是在所有的子类中做出小小的处理程序?

回答

7

声明父虚拟方法,在子类覆盖它,并从子类中调用

base.checkReadyness(sender, e); 

(或其derevation)。这允许将来的设计演变,如果你想在调用父事件处理器之前做一些特定的错误检查代码。您可能不需要为每个控件编写数百万个事件处理程序,您只需编写一个事件处理程序,将所有控件挂接到此事件处理程序,然后调用父级的事件处理程序。

我注意到的一件事是,如果所有这些代码都放在dll中,那么您可能会遇到性能问题,试图从dll中调用事件处理程序。

+0

这将解决这个问题,但我希望避免基本上是空的错误处理程序,因此我的问题。 – Merus 2008-09-18 07:11:33

0

如果您的活动已在您的父级中定义,则不需要在您的子级中重新连线。这将导致事件发生两次。

请确认这是否发生了什么。 HTH :)

0

这篇关于MSDN的文章应该是一个很好的出发点:Overriding Event Handlers with Visual Basic .NET。看看如何处理子句可能导致衍生类部分中的问题。

+0

这是一篇Visual Basic文章。他们讨论的问题在C#中不会成为问题。这也许可以解释为什么VS酒吧应该是合法的东西,尽管如此。 – 2012-05-05 14:08:27

0

为什么不在父类中声明该方法为虚拟的,然后可以在派生类中重写它以添加额外的功能?

+0

所以我不必为每个相同的类编写处理程序。这些都是非常小的控制。没有多少额外的功能,我需要。 – Merus 2008-09-18 07:02:02

0

忘记它是一个事件处理程序,只是在子类中做适当的常规方法覆盖。

3

我刚刚遇到过这一个,我同意这感觉就像你正在做的一切正确。宣称虚拟方法最好是解决方法,而不是解决方案。

正在做的事是有效的 - 只存在于派生类中的控件,派生类将事件处理程序附加到该控件的某个事件中。处理事件的方法在基类中定义的方法既不在这里,也不在那里,它在绑定事件的时候可用。这个事件没有被附加到两次或者任何其他愚蠢的事情上,它只是一个处理事件的方法被定义的地方。

绝对不是虚拟方法 - 我不希望方法被派生类重写。非常令人沮丧,在我看来,dev-studio中存在一个bug。

1

我刚刚遇到了Merus第一次提出的确切问题,和其他发布响应的人一样,我完全不清楚为什么VS(我现在使用Visual C#2010 Express)对象具有事件处理函数在基类中定义。我发布响应的原因是,在通过使基类代码成为派生类在其(基本上为空)事件处理程序中简单调用的受保护方法解决问题的过程中,我做了基本的重构重命名并注意到VS设计师停止抱怨。也就是说,它重命名了事件处理程序注册(所以它不再遵循VS设计人员使用ControlName_EventName命名事件处理程序的惯例),并且这似乎满足了它。当我然后试图通过在适当的VS事件中输入名称来注册(现在重命名的)基本事件处理程序与派生类控件,设计师在派生类中创建了一个新的事件处理程序,然后我删除了它,从而保留了派生类控件到基类(事件处理程序)方法。网络,正如你所期望的那样,C#可以找到我们想要做的事情。当您遵循设计器的事件处理程序命名约定时,只有VS设计师不喜欢它。我不认为设计师需要这样工作。任何人,时间继续。

0

这里就是我做得到的基础方法调用几个类似的寻找方式,他们每个人有一些额外的功能,以共同的:

 protected override void OnLoad(EventArgs e) 
    { 
     try 
     { 
      this.SuspendLayout(); 
      base.OnLoad(e); 

      foreach (Control ctrl in Controls) 
      { 
       Button btn = ctrl as Button; 
       if (btn == null) continue; 

       if (string.Equals(btn.Name, "btnAdd", StringComparison.Ordinal)) 
        btn.Click += new EventHandler(btnAdd_Click); 
       else if (string.Equals(btn.Name, "btnEdit", StringComparison.Ordinal)) 
        btn.Click += new EventHandler(btnEdit_Click); 
       else if (string.Equals(btn.Name, "btnDelete", StringComparison.Ordinal)) 
        btn.Click += new EventHandler(btnDelete_Click); 
       else if (string.Equals(btn.Name, "btnPrint", StringComparison.Ordinal)) 
        btn.Click += new EventHandler(btnPrint_Click); 
       else if (string.Equals(btn.Name, "btnExport", StringComparison.Ordinal)) 
        btn.Click += new EventHandler(btnExport_Click); 
      } 

使用正确的固定器脱落的机会按钮名称对我来说看起来是一样的,因为没有手动连接继承的处理程序。

请注意,您可能需要测试this.DesignMode,以便根本跳过VS Designer中的代码,但即使没有检查,它也可以正常工作。

2

我也经历过这个问题,因为在早期版本的VS中,你可以“继承”事件处理程序。所以我找到的解决方案无需重写方法,只需在表单的初始化阶段将事件处理程序分配给某处。就我而言,在构造函数中完成(我敢肯定的OnLoad()会工作以及):

public MyForm() 
    { 
     InitializeComponent(); 
     btnOK.Click += Ok_Click; 
    } 

...在Ok_Click处理程序驻留在基本形式。食物的思想。