我有点把自己逼到了一个角落里。

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

我想要做的只是在父 UserControl 中拥有一个事件处理程序,该处理程序执行只有父控件才能执行的操作(即有条件地调用事件,因为事件在父控件中定义)。然后,我将此事件处理程序连接到子控件中的所有输入框,子控件将完成解析输入并告诉父控件是否引发该事件的任务。漂亮干净,没有重复的复制粘贴代码(对我来说 总是 导致错误)。

这是我的问题。Visual Studio认为我太聪明了一半,并警告我说“方法'checkReveriness'(父母中的事件处理程序)不能是事件的方法,因为该类别从该类派生的类中定义了该方法。”是的,视觉工作室, 这才是重点. 。我 有一个仅处理子类抛出的事件的事件处理程序,它唯一的工作是使我能够连接子类,而无需编写一行代码。我不需要那些额外的处理程序 - 当孩子们处理用户输入时,我需要的所有功能都会自然地被调用。

我不知道为什么 Visual Studio 现在开始抱怨这个问题(因为它以前允许我这样做),而且我不知道如何让它消失。最好,我希望无需定义仅调用 CheckReadiness 的方法即可完成此操作。是什么导致了这个警告,是什么导致它在一小时前还没有出现,而现在却出现了,以及我怎样才能让它消失而不需要在所有子类中使用小处理程序?

有帮助吗?

解决方案

将父方法声明为virtual,在子类中重写它并调用

base.checkReadyness(sender, e);

(或其派生)来自子类内部。这允许未来的设计演变,例如您是否想在调用父事件处理程序之前执行一些特定的错误检查代码。您可能不需要为每个控件编写数百万个这样的事件处理程序,您只需编写一个,将所有控件挂接到该事件处理程序,该事件处理程序又调用父级的事件处理程序。

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

其他提示

我也刚刚遇到过这个,我同意感觉你做的一切都是正确的。将方法声明为 virtual 充其量只是一种解决方法,而不是解决方案。

所做的事情是有效的 - 一个控件仅存在于派生类中,并且派生类将事件处理程序附加到该控件的事件之一。事实上,处理事件的方法是在基类中定义的,这一点不存在,它在绑定到事件时可用。事件不会被附加到两次或任何类似的愚蠢的事情,这只是处理事件的方法定义在哪里的问题。

最肯定的是它不是虚拟方法 - 我不希望该方法被派生类覆盖。非常令人沮丧,在我看来,这是 dev-studio 中的一个错误。

我也遇到过这个问题,因为在早期版本的 VS 中,您可以“继承”事件处理程序。因此,我找到的无需重写方法的解决方案只是在表单初始化阶段的某个位置分配事件处理程序。就我而言,在构造函数中完成(我确信 OnLoad() 也可以工作):

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

...Ok_Click 处理程序驻留在基本表单中。值得深思。

我刚刚遇到了 Merus 首次提出的确切问题,并且像其他发布响应的人一样,我完全不清楚为什么 VS(我现在使用 Visual C# 2010 Express)反对在基础中定义事件处理程序班级。我发布响应的原因是,在通过使基类代码成为派生类在其(基本上是空的)事件处理程序中简单调用的受保护方法来解决问题的过程中,我对基类进行了重构重命名类方法并注意到 VS 设计者不再抱怨了。也就是说,它重命名了事件处理程序注册(因此它不再遵循 VS 设计者使用 ControlName_EventName 命名事件处理程序的约定),这似乎满足了它的要求。然后,当我尝试通过在相应的 VS 事件中输入名称来针对派生类控件注册(现已重命名)基本事件处理程序时,设计人员在派生类中创建了一个新的事件处理程序,然后我将其删除,从而使派生类控件保持注册状态到基类(事件处理程序)方法。Net,正如您所期望的,C# 找到了我们想做的合法事情。当您遵循设计器的事件处理程序命名约定时,只有 VS 设计器不喜欢它。我认为设计师没有必要以这种方式工作。无论如何,是时候继续了。

如果您的事件已在父类中定义,则无需在子类中再次重新连接它。这将导致事件触发两次。

请确认是否发生了这种情况。哈:)

MSDN 上的这篇文章应该是一个很好的起点: 使用 Visual Basic .NET 重写事件处理程序. 。看看 Handles 子句如何导致派生类出现问题 部分。

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

忘记它是一个事件处理程序,只需在子类中进行适当的常规方法重写即可。

以下是我为了以几种类似的形式调用基本方法所做的事情,每种形式都比常见的形式有一些额外的功能:

        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 中的代码,但即使没有检查,它对我来说也能正常工作。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top