在 C# MVP 中处理菜单事件
Handle menu event in C# MVP
我正在学习 C# 和 MVP。我能够处理简单的菜单点击事件。我正在尝试使用 MVP 模式处理菜单单击事件,但无法弄清楚为什么它不起作用。我在互联网上查看了很多代码并提出了以下内容。
interface IMenuBarView
{
event EventHandler AboutMenuItemClicked;
...
}
public partial class MenuBarView : UserControl, IMenuBarView
{
public event EventHandler AboutMenuItemClicked;
private MenuBarPresenter m_menuBarPresenter;
public MenuBarView()
{
this.aboutToolStripMenuItem.Click += AboutMenuItemClicked;
m_menuBarPresenter = new MenuBarPresenter(this);
}
}
class MenuBarPresenter
{
private IMenuBarView m_menuView;
public MenuBarPresenter(IMenuBarView menu)
{
m_menuView = menu;
m_menuView.AboutMenuItemClicked += AboutMenuItemClicked;
}
public void AboutMenuItemClicked(object sender, EventArgs e)
{
MessageBox.Show("Hello");
}
}
我可以在 MenuBarView 中有一个事件处理程序,它又可以调用演示者来执行逻辑。不过我比较感兴趣的是上面那个。这不是正确的做法吗?
我对 C# 真的很陌生,所以不要杀了我。 :)
编辑后:
我很快根据@Enigmativity 评论编造了一些我尝试编译的东西。它运行但从未调用该事件。创建一个窗体,添加一个菜单项并将菜单项名称命名为 item1ToolStripMenuItem。单击菜单时,不会触发该事件。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace testEventHandler
{
public partial class Form1 : Form, IMenuBarView
{
public event EventHandler AboutMenuItemClicked;
private MenuBarPresenter m_menuBarPresenter;
public Form1()
{
InitializeComponent();
this.item1ToolStripMenuItem.Click += AboutMenuItemClicked;
m_menuBarPresenter = new MenuBarPresenter(this);
}
}
interface IMenuBarView
{
event EventHandler AboutMenuItemClicked;
}
class MenuBarPresenter
{
private IMenuBarView m_menuView;
public MenuBarPresenter(IMenuBarView menu)
{
m_menuView = menu;
m_menuView.AboutMenuItemClicked += item1ToolStripMenuItem_Click;
}
private void item1ToolStripMenuItem_Click(object sender, EventArgs e)
{
MessageBox.Show("hello");
}
}
}
您的命令顺序有问题。
当你写这篇文章时:
this.item1ToolStripMenuItem.Click += this.AboutMenuItemClicked;
您是说“任何附加到 this.AboutMenuItemClicked
的处理程序都应该 复制 到 this.item1ToolStripMenuItem.Click
”。当时没有附加的处理程序。您没有复制任何内容。
然后调用 m_menuBarPresenter = new MenuBarPresenter(this);
将 item1ToolStripMenuItem_Click
附加到 this.AboutMenuItemClicked
事件委托。
如果你调换它的顺序:
m_menuBarPresenter = new MenuBarPresenter(this);
this.item1ToolStripMenuItem.Click += this.AboutMenuItemClicked;
但是,这不是附加事件的正确方法。您不需要关心是否有人已附加或处理程序。
this.item1ToolStripMenuItem.Click += (s, e) => this.AboutMenuItemClicked?.Invoke(s, e);
m_menuBarPresenter = new MenuBarPresenter(this);
这是正确的方法。
如果有订阅者,?.Invoke
会调用 .Invoke
,但如果没有订阅者,它什么也不做。
我也玩过你的代码。这更接近我做 MVP 的方式:
public partial class Form1 : Form
{
public event EventHandler AboutMenuItemClicked;
private Presenter _presenter;
public Form1()
{
InitializeComponent();
this.item1ToolStripMenuItem.Click += (s, e) => this.AboutMenuItemClicked?.Invoke(s, e);
_presenter = new Presenter(this);
}
public void ShowMessage(string message)
{
MessageBox.Show(message);
}
}
interface IMenuBarView
{
event EventHandler AboutMenuItemClicked;
}
class Presenter
{
private readonly Form1 _form;
private readonly AlertModel _alertModel;
public Presenter(Form1 form)
{
_form = form;
_form.AboutMenuItemClicked += _form_AboutMenuItemClicked;
_alertModel = new AlertModel();
_alertModel.Message += _alertModel_Message;
}
private void _alertModel_Message(object sender, string e)
{
_form.ShowMessage(e);
}
private void _form_AboutMenuItemClicked(object sender, EventArgs e)
{
_alertModel.UpdateModel("About Menu Item");
}
}
class AlertModel
{
public event EventHandler<string> Message;
public void UpdateModel(string action)
{
this.Message?.Invoke(this, $"User has selected \"{action}\"");
}
}
我正在学习 C# 和 MVP。我能够处理简单的菜单点击事件。我正在尝试使用 MVP 模式处理菜单单击事件,但无法弄清楚为什么它不起作用。我在互联网上查看了很多代码并提出了以下内容。
interface IMenuBarView
{
event EventHandler AboutMenuItemClicked;
...
}
public partial class MenuBarView : UserControl, IMenuBarView
{
public event EventHandler AboutMenuItemClicked;
private MenuBarPresenter m_menuBarPresenter;
public MenuBarView()
{
this.aboutToolStripMenuItem.Click += AboutMenuItemClicked;
m_menuBarPresenter = new MenuBarPresenter(this);
}
}
class MenuBarPresenter
{
private IMenuBarView m_menuView;
public MenuBarPresenter(IMenuBarView menu)
{
m_menuView = menu;
m_menuView.AboutMenuItemClicked += AboutMenuItemClicked;
}
public void AboutMenuItemClicked(object sender, EventArgs e)
{
MessageBox.Show("Hello");
}
}
我可以在 MenuBarView 中有一个事件处理程序,它又可以调用演示者来执行逻辑。不过我比较感兴趣的是上面那个。这不是正确的做法吗? 我对 C# 真的很陌生,所以不要杀了我。 :)
编辑后: 我很快根据@Enigmativity 评论编造了一些我尝试编译的东西。它运行但从未调用该事件。创建一个窗体,添加一个菜单项并将菜单项名称命名为 item1ToolStripMenuItem。单击菜单时,不会触发该事件。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace testEventHandler
{
public partial class Form1 : Form, IMenuBarView
{
public event EventHandler AboutMenuItemClicked;
private MenuBarPresenter m_menuBarPresenter;
public Form1()
{
InitializeComponent();
this.item1ToolStripMenuItem.Click += AboutMenuItemClicked;
m_menuBarPresenter = new MenuBarPresenter(this);
}
}
interface IMenuBarView
{
event EventHandler AboutMenuItemClicked;
}
class MenuBarPresenter
{
private IMenuBarView m_menuView;
public MenuBarPresenter(IMenuBarView menu)
{
m_menuView = menu;
m_menuView.AboutMenuItemClicked += item1ToolStripMenuItem_Click;
}
private void item1ToolStripMenuItem_Click(object sender, EventArgs e)
{
MessageBox.Show("hello");
}
}
}
您的命令顺序有问题。
当你写这篇文章时:
this.item1ToolStripMenuItem.Click += this.AboutMenuItemClicked;
您是说“任何附加到 this.AboutMenuItemClicked
的处理程序都应该 复制 到 this.item1ToolStripMenuItem.Click
”。当时没有附加的处理程序。您没有复制任何内容。
然后调用 m_menuBarPresenter = new MenuBarPresenter(this);
将 item1ToolStripMenuItem_Click
附加到 this.AboutMenuItemClicked
事件委托。
如果你调换它的顺序:
m_menuBarPresenter = new MenuBarPresenter(this);
this.item1ToolStripMenuItem.Click += this.AboutMenuItemClicked;
但是,这不是附加事件的正确方法。您不需要关心是否有人已附加或处理程序。
this.item1ToolStripMenuItem.Click += (s, e) => this.AboutMenuItemClicked?.Invoke(s, e);
m_menuBarPresenter = new MenuBarPresenter(this);
这是正确的方法。
如果有订阅者,?.Invoke
会调用 .Invoke
,但如果没有订阅者,它什么也不做。
我也玩过你的代码。这更接近我做 MVP 的方式:
public partial class Form1 : Form
{
public event EventHandler AboutMenuItemClicked;
private Presenter _presenter;
public Form1()
{
InitializeComponent();
this.item1ToolStripMenuItem.Click += (s, e) => this.AboutMenuItemClicked?.Invoke(s, e);
_presenter = new Presenter(this);
}
public void ShowMessage(string message)
{
MessageBox.Show(message);
}
}
interface IMenuBarView
{
event EventHandler AboutMenuItemClicked;
}
class Presenter
{
private readonly Form1 _form;
private readonly AlertModel _alertModel;
public Presenter(Form1 form)
{
_form = form;
_form.AboutMenuItemClicked += _form_AboutMenuItemClicked;
_alertModel = new AlertModel();
_alertModel.Message += _alertModel_Message;
}
private void _alertModel_Message(object sender, string e)
{
_form.ShowMessage(e);
}
private void _form_AboutMenuItemClicked(object sender, EventArgs e)
{
_alertModel.UpdateModel("About Menu Item");
}
}
class AlertModel
{
public event EventHandler<string> Message;
public void UpdateModel(string action)
{
this.Message?.Invoke(this, $"User has selected \"{action}\"");
}
}