事件处理中的MVP模式

本文关键字:模式 MVP 事件处理 | 更新日期: 2023-09-27 17:58:27

我刚开始使用C#和MVP设计模式。当涉及到事件处理时,我对具体的实现表示怀疑。我知道,视图不应该知道演示者,演示者应该通过视图界面控制视图。

假设我有两个文本框,希望检查是否有错误。如果发生错误,我想更改文本框文本属性。创建一个EventHandler并使用sender对象来验证用户当前使用的文本框是否错误?

类似于:

IView:

interface IMainView
{
    event KeyPressEventHandler KeyPressed;
}

视图:

public partial class MainView : Form, IMainView
{
    public frmInterakcija()
    {
        InitializeComponent();
        this.textBox1.Name = "textBox1";
        this.textBox2.Name = "textBox2";
        new MainPresenter();
        Bind();
    }
    private void Bind()
    {
       this.textBox1.KeyPress += KeyPressed;
       this.textBox2.KeyPress += KeyPressed;
    }
}

演示者:

class MainPresenter
{
    private IMainView _view;
    public MainPresenter(IMainView view) 
    {
        _view = view;
        this.initialize();
    }
    public void initialize()
    {
        _view.KeyPressed += _view_textBoxKeyPressed;
    }
    public void _view_textBoxKeyPressed(object sender, EventArgs e)
    {
        if (sender.GetType() == typeof(TextBox))
        {
            TextBox textBox = (TextBox)sender;
            if (textBox.Name.Equals("textbox1") 
                {...} // Do validation/changes on textbox1
            else ...
        }
    }
 }

或者,我应该为我拥有的每个文本框创建事件处理程序,并通过属性更新/处理错误?(我想这会使我的代码变得多余)

什么是正确的方法?

事件处理中的MVP模式

IMHO presenter应该不知道视图特定的对象(代码中的示例textbox)。这种逻辑不应该出现在演示者中。演示者一定不知道UI中控件的ID,这更糟糕。记住,这样做的好处之一应该是,您可以通过模拟视图来测试演示者,如果您有特定于UI的代码,则无法对演示者进行单元测试。

对我来说,这确实像是两个不同的events,因为你在做不同的逻辑。我会提出两个不同的events,一个进行验证,另一个进行自己的逻辑。演示者不必检查发件人是textbox还是textbox的id。此外,如果您有另一个文本框,那么在当前实现中需要另一个if条件。

此外,在视图中,它应该是new MainPresenter(this);

演示者绝对不应该有视图特定的类型(例如控件、事件等),因为在测试演示者的逻辑时,这些类型很难伪造。相反,你应该有如下的东西。

IView:

interface IMainView
{
    // give these better names based on what they actually represent (e.g. FirstName and LastName)
    // you could also add setters if you needed to modify their values from the presenter
    string Text1 { get; } 
    string Text2 { get; }
    // provide a way to bubble up validation errors to the UI
    string ErrorMessage { get; set; }
}

演示者:

class MainPresenter
{
    private IMainView _view;
    public MainPresenter(IMainView view) 
    {
        _view = view;
    }
    public void ValidateText1()
    {
        if (/* some validation is false */)
        {
            _view.ErrorMessage = "Text1 isn't valid";
        }
    }
    public void ValidateText2()
    {
        if (/* some validation is false */)
        {
            _view.ErrorMessage = "Text2 isn't valid";
        }
    }
 }

视图:

public partial class MainView : Form, IMainView
{
    var readonly MainPresenter _presenter;
    public frmInterakcija()
    {
        InitializeComponent();
        _presenter = new MainPresenter(this);
    }
    private void textBox1_KeyPress(object sender, KeyPressEventArgs eventArgs)
    {
        _presenter.ValidateText1();
    }
    private void textBox2_KeyPress(object sender, KeyPressEventArgs eventArgs)
    {
        _presenter.ValidateText2();
    }
    #region Implementation of IMainView
    public string Text1
    {
        get { return textBox1.Text; }
    }
    public string Text2
    {
        get { return textBox2.Text; }
    }
    public string ErrorMessage
    {
        get { return labelErrorMessage.Text; }
        set { labelErrorMessage.Text = value; }
    }
    #endregion
}