简体   繁体   English

Winforms中的MVP模式-处理事件

[英]MVP pattern in winforms - Handling events

I just started with C# and MVP design pattern. 我刚开始使用C#和MVP设计模式。 I'm in doubt about concrete implementation when it comes to event handling. 对于事件处理,我不确定具体的实现。 I'm aware of that, view shouldn't know about presenter and presenter should control a view through view interface. 我知道,视图不应该知道演示者,演示者应该通过视图界面控制视图。

Let's say I have 2 text boxes and would like to check for errors. 假设我有2个文本框,想要检查错误。 If an error occurs I want to change text box Text property. 如果发生错误,我想更改文本框的Text属性。 Is it wrong approach to create one EventHandler and use sender object to verify witch text box is user currently using? 创建一个EventHandler并使用发送者对象来验证用户当前正在使用的文本框是错误的方法吗?

Something like: 就像是:

IView: IView:

interface IMainView
{
    event KeyPressEventHandler KeyPressed;
}

View: 视图:

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;
    }
}

Presenter: 主持人:

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 ...

        }
    }
 }

Or instead of this above I should create event handler for every textbox I have and update/handle errors through properties? 还是代替上述方法,我应该为我拥有的每个文本框创建事件处理程序,并通过属性更新/处理错误? (this will make my code redundant I guess) (我猜这会使我的代码变得多余)

What would be right approach? 什么是正确的方法?

IMHO the presenter should be unaware of view specific objects (example textbox in your code). 恕我直言, presenter应该不了解特定于视图的对象(代码中的示例textbox )。 That kind of logic should not be in presenter. 这种逻辑不应该出现在主持人中。 And presenter must not know about the Ids of controls in the UI, that's even worse. 演示者一定不能不知道UI中的控件ID,这更糟。 Remember one of the benefits of this should be that you can test the presenter by mocking the view, if you have UI specific code you won't be able to unit test the presenter. 请记住,这样做的好处之一是您可以通过模拟视图来测试演示者,如果您具有特定于UI的代码,则无法对演示者进行单元测试。

It does seem like two different events to me since you are doing different logic. 在我看来,这确实是两个不同的events ,因为您执行的逻辑不同。 I'd raise two different events and one would do validation, the other would do its own logic. 我将提出两个不同的events ,一个将进行验证,另一个将执行其自己的逻辑。 The presenter won't have to check if the sender is textbox or the id of the textbox . 主持人不会有检查,如果发件人是textbox或的id textbox Also what if you have another textbox, you'll need another if condition in this current implementation. 另外,如果您有另一个文本框,在当前实施中还需要另一个if条件。

Also, in the view, it should be new MainPresenter(this); 另外,在视图中,它应该是new MainPresenter(this);

Your presenter should absolutely not have view-specific types in it (eg controls, events, etc.) since these are hard to fake when it comes time to test the presenter's logic. 您的演示者绝对不应在其中包含特定于视图的类型(例如控件,事件等),因为在测试演示者的逻辑时很难伪造这些类型。 Instead, you should have something like the following. 相反,您应该具有如下所示的内容。

IView: 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; }
}

Presenter: 主持人:

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";
        }
    }
 }

View: 视图:

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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM