【问题标题】:Method doesn't bind to event handler方法未绑定到事件处理程序
【发布时间】:2021-12-30 21:45:25
【问题描述】:

我尝试在 winforms 中使用 MVC 模式,但是当我尝试调用事件时,它始终为空。我将 GameView 表单传递给 Game 类,我将 CityButtonPressed 方法绑定到事件,但是当我运行它时,似乎没有任何绑定。

class Game
{
    private readonly IGameView _gameView;

    public Game(IGameView view)
    {
        _gameView = view;
        _gameView.CityButtonPressed += CityButtonPressed;
    }

    public void CityButtonPressed(object sender,EventArgs e)
    {
          //do something
    }
}

public interface IGameView
{
   event EventHandler CityButtonPressed;
}

public partial class GameView : Form,IGameView
{
    public event EventHandler CityButtonPressed;

    public GameView()
    {
        InitializeComponent();
    }

    protected virtual void OnButtonPressed(EventArgs e)
    {
        CityButtonPressed?.Invoke(this, e);
    }

    private void button1_Click(object sender, EventArgs e)
    {
        OnButtonPressed(EventArgs.Empty);
    }
}

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        var gameView = new GameView();
        var game = new Game(gameView);
        Application.Run(new GameView());
    }
}

我做错了什么?

【问题讨论】:

  • @HaraldCoppoolse 在GameView 中的CityButtonPressed 事件处理程序
  • 这对我来说看起来不太 MVC。您的 Game 类看起来像模型和控制器的组合。而且,无论哪种方式,它都不应该知道关于按钮按下的任何事情。
  • 您发布的代码没有任何内容表明它不起作用。你能发一个minimal reproducible example吗?
  • 您的代码看起来正确。也许GameView 是在事件注册后重新创建的?
  • GameView的构造函数中下断点,检查是否被多次调用。

标签: c# winforms model-view-controller


【解决方案1】:

这是您的代码的精简版表明它可以工作

void Main()
{
    var view = new GameView();
    var game = new Game(view);
    view.OnButtonPressed();
}

public interface IGameView
{
    event EventHandler CityButtonPressed;
}

class Game
{
    private readonly IGameView _gameView;


    public Game(IGameView view)
    {
        _gameView = view;
        _gameView.CityButtonPressed += CityButtonPressed;
    }

    public void CityButtonPressed(object sender, EventArgs e)
    {
        Console.WriteLine("Pressed");
    }
}

public partial class GameView : IGameView
{
    public event EventHandler CityButtonPressed;

    public void OnButtonPressed()
    {
        if (CityButtonPressed == null) 
            Console.WriteLine("null");
        CityButtonPressed?.Invoke(this, new EventArgs());
    }
}

当我运行它时,我会在控制台上看到Pressed。我所做的只是重构您的代码,使其降至运行所需的最低数量。

您似乎没有正确接线,或者您没有向我们展示所需的实际最少代码量。


更新

您正在创建两个 GameView 实例。有你的问题。

    var gameView = new GameView();
    var game = new Game(gameView);
    Application.Run(new GameView());

试试这个:

    var gameView = new GameView();
    var game = new Game(gameView);
    Application.Run(gameView);

【讨论】:

  • 我发现当我像你一样在 main 方法中运行 OnButtonPressed 方法时,它工作正常,但是当它在按下实际按钮后运行时显示空异常。我更新了主帖,现在应该可以复制了。
  • @AdamKotvas - 问题已解决。我已经更新了我的答案。
【解决方案2】:

在调用 CityButtonPressed 之前,请确保使用 GameView 实例实例化 Game 类。例如:

private Game game;
    protected virtual void OnButtonPressed(EventArgs e)
    {
      game=  new Game(this);
        if (CityButtonPressed == null)   
            MessageBox.Show("null");  
        CityButtonPressed?.Invoke(this, e);
    }

这对您来说不是一个好的解决方案,因为您将在某处需要 Game 实例,但 CityButtonPressed 不应再为空。

【讨论】:

    猜你喜欢
    • 2016-12-10
    • 1970-01-01
    • 2016-05-26
    • 2013-11-20
    • 2013-02-02
    • 1970-01-01
    • 2014-10-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多