C# 使用事件通过窗体类实现接口

C# 使用事件通过窗体类实现接口,c#,.net,function,events,interface,C#,.net,Function,Events,Interface,我目前正致力于将一些Visual Basic.NET代码移植到c#.NET,我移植的库中有一个特定部分似乎无法使用。下面是它的布局: 首先,我有一个定义如下的接口: public interface IMyInterface { void EnableSave(object sender, EventArgs e); } this.EnableFormSave += new frmIMyInterface.EnableFormSaveEventHandler(this.Enable

我目前正致力于将一些Visual Basic.NET代码移植到c#.NET,我移植的库中有一个特定部分似乎无法使用。下面是它的布局:

首先,我有一个定义如下的接口:

public interface IMyInterface
{
      void EnableSave(object sender, EventArgs e);
}
this.EnableFormSave += new frmIMyInterface.EnableFormSaveEventHandler(this.EnableSave);
接下来,我有一个实现上述接口的可继承表单:

public partial class frmIMyInterface : Form, Globals.IMyInterface
{
      public delegate void EnableFormSaveEventHandler(object sender, EventArgs e);
      public event EnableFormSaveEventHandler EnableFormSave;

      public void EnableSave(object sender, EventArgs e)
      {
            EnableFormSave.Invoke(sender, e);
      }
}
到目前为止还不错。然后,我创建了一个实现frmIMyInterface的表单:

public partial class frmMyNewForm : frmIMyInterface
{
...
public virtual void OnEnableSave(EventArgs e)
  {
        //EnableFormSave.Invoke(sender, e);

        // This is the usual way to invoke an event in c#
        var handler = EnableFormSave;
        if (handler != null) handler(this, e);
  }
在这种形式下,我定义了一个方法来处理事件:

private void EnableSave(object sender, EventArgs e)
{
    this.cmdSave.Enabled = true;
}
然后,在表单的设计器代码中,处理程序委托定义如下:

public interface IMyInterface
{
      void EnableSave(object sender, EventArgs e);
}
this.EnableFormSave += new frmIMyInterface.EnableFormSaveEventHandler(this.EnableSave);
我的项目正常构建,但是,当我尝试使用表单设计器打开
frmMyNewForm
时,我会看到一个启动屏幕,上面显示,为防止加载设计器之前可能的数据丢失,必须解决以下错误:“EnableSave”方法不能是事件的方法,因为该类派生的类已定义了该方法

我移植的VisualBasic.NET代码的所有定义都与我定义的完全一致,但运行良好。我看不出有任何问题,而且似乎.NET应该知道引发事件的基类中的方法定义与在派生表单中定义并设置为事件处理程序的处理程序之间的区别


提前感谢您!

您必须重命名事件处理程序或事件。否则调用不明确

所以这是可行的:

this.EnableFormSave += new frmIBGInterface.EnableFormSaveEventHandler(this.OnEnableSave);

private void OnEnableSave(object sender, EventArgs e)
{
    this.cmdSave.Enabled = true;
}
c#中的常见模式是命名调用事件OnEnableSave的方法,并将其设置为虚拟,以便派生类可以重写行为,而不必附加到自己的事件。因此,在frmIMyInterface中:

public partial class frmMyNewForm : frmIMyInterface
{
...
public virtual void OnEnableSave(EventArgs e)
  {
        //EnableFormSave.Invoke(sender, e);

        // This is the usual way to invoke an event in c#
        var handler = EnableFormSave;
        if (handler != null) handler(this, e);
  }
然后在frmMyNewForm中

public override void OnEnableSave(EventArgs e)
{
    base.OnEnableSave(e);
    this.cmdSave.Enabled = true;
}

也就是说,将调用事件的方法公开是非常奇怪的。我可能会将接口方法命名为EnableSave(),然后从该方法调用OnEnableSave(),并将其命名为OnEnableSave()受保护。

谢谢。所以…我猜VisualBasic.NET根本不在乎,并且没有错误地解决了它?而且…事件名为
EnableFormSave
…因此它是不同的。不确定为什么,我认为它也不应该在那里工作。当我尝试进行此更改时,只要我更改代码分配del的方法的名称,就可以如果将方法添加到事件处理程序中,则会出现以下错误:“OnEnableSave的重载与委托frmIMyInterface.EnableFormSaveEventHandler的重载不匹配“我不明白为什么。更改名称与签名无关。你能确认你两行都改了吗?啊。。。我已经删除了参数。把它们放回去,现在就可以了!非常感谢。您的frmMyNewForm有两个EnableSave()方法。它从基类继承的一个和另一个私有类。你也得到了一个警告,如果你想这样做,建议使用新的关键字。你不想这么做,没有意义。您还在frmIMyInterface.EnableSave()方法中犯了一个错误,当没有事件处理程序订阅该事件时,它将崩溃并烧毁。它也不遵循事件引发模式,它应该是一个名为OnEnableSave()的受保护虚拟方法。请记住,C#与VB.NET不同。您能详细介绍一下您认为应该如何正确实现这一点吗?我不反对改变它的运作方式。。。记住,这是一个端口。我宁愿做得很好,也不愿做得很差,因为VB就是这样做的。:)目标是让一个事件被继承,并在数据更改时激发,并强制派生表单在该事件激发时实现一个方法来执行某些操作(如启用保存按钮)。那么,您的应用程序当前是如何构造的?检测数据更改并调用IMyInterface.EnableSave()的代码在哪里?抱歉,这里仍在学习如何工作。。。其思想是,它是一个库,有一个类可以将表单传递给它,它可以旋转表单上的所有控件,并根据控件类型将eventhandler添加到相应的“…更改”事件中私有frmimy接口frmFoo;if(_ctrl是TextBox){u ctrl.TextChanged+=neweventhandler(frmFoo.EnableSave);}如果因此,在表单构建时,它应该将事件添加到每个控件中,当控件数据更改时,事件应该触发并允许启用“保存”按钮。我以前从未听说过这样的事情!在IMO中,您应该让表单附加到其控件的更改事件,并设置其保存按钮的启用状态,或者选择一种经过尝试和测试的模式,例如MVC,当控制器上的CanSave属性设置为true时,表单将启用save按钮。如果您想按自己的方式执行,那么我认为不需要事件。只需在IMyInterface上定义void EnableSave(),并在frmIMyInterface上用抽象方法实现它。这将强制frmMyNewForm覆盖EnableSave(),在这里它可以启用save按钮。