1

想象一个简单的用户控件,它有一个文本框(客户名称)和两个按钮(保存/取消)。

此 UserControl 位于带有另外两个按钮的父控件中(PreviousCustomer/NextCustomer)

问题是我不知道在哪里将模型传递给演示者。我是否通过视图构造函数?如果模型发生变化(点击了 PreviousCustomer/NextCustomer)怎么办?我每次都创建一个新视图吗?如果 UserControl 与许多孩子很复杂,这似乎很浪费。我可以在视图和演示者中实现 UpdateModel 方法,还是不正确?

这是我的代码:

public interface IModel
{
    string CustomerName { get; set; }
}

public class Presenter
{
    private IView _view;
    private IModel _model;

    public Presenter(IView view, IModel model)
    {
        _view = view;
        _model = model;
        _view.CustomerName = _model.CustomerName;
    }

    public void Save()
    {
        _model.CustomerName = _view.CustomerName;
    }

    public void Cancel()
    {
        _view.CustomerName = _model.CustomerName;
    }

    public void UpdateModel(IModel newModel)
    {
        _model = newModel;
        _view.CustomerName = _model.CustomerName;
    }
}

public interface IView
{
    string CustomerName { get; set; }
}

public class View : UserControl, IView
{
    private Presenter _presenter;

    public string CustomerName
    {
        get { return CustomerNameEditBox.Text; }
        set { CustomerNameEditBox.Text = value; }
    }

    //Is this the right place to pass in the model?
    public View(IModel model)
    {
        _presenter = new Presenter(this, model);
    }

    private void SaveButton_Click(object sender, EventArgs e)
    {
        _presenter.Save();
    }

    private void CancelButton_Click(object sender, EventArgs e)
    {
        _presenter.Cancel();
    }

    public void UpdateModel(IModel newModel)
    {
        _presenter.UpdateModel(newModel);
    }
}

编辑:正如下面评论中所述,我认为最好让视图完全愚蠢并且对演示者或模型一无所知。这是我修改后的代码。

模型:

public interface IModel
{
    string CustomerName { get; set; }
}

public class Model : IModel
{
    public string CustomerName { get; set; }

    public Model(string name)
    {
        CustomerName = name;
    }
}

看法:

public interface IView
{
    event EventHandler SaveClick;
    event EventHandler CancelClick;
    string CustomerName { get; set; }
}

public class View : UserControl, IView
{
    public event EventHandler SaveClick
    {
        add { SaveButton.Click += value; }
        remove { SaveButton.Click -= value; }
    }

    public event EventHandler CancelClick
    {
        add { CancelButton.Click += value; }
        remove { CancelButton.Click -= value; }
    }

    public string CustomerName
    {
        get { return CustomerNameEditBox.Text; }
        set { CustomerNameEditBox.Text = value; }
    }
}

主持人:

public class Presenter
{
    private IView _view;
    private IModel _model;

    public Control View
    {
        get { return (Control)_view; } 
    }

    public Presenter(IView view, IModel model)
    {
        _view = view;
        _view.SaveClick += new EventHandler(_view_SaveClick);
        _view.CancelClick += new EventHandler(_view_CancelClick);
        _model = model;
        _view.CustomerName = _model.CustomerName;
    }

    void _view_SaveClick(object sender, EventArgs e)
    {
        _model.CustomerName = _view.CustomerName;
    }

    void _view_CancelClick(object sender, EventArgs e)
    {
        _view.CustomerName = _model.CustomerName;
    }

    public void ChangeModel(IModel newModel)
    {
        _model = newModel;
        _view.CustomerName = _model.CustomerName;
    }
}

用法:

public class MainProgram : Form
{
    public void ArbitraryMethod()
    {
        //Create a new model object
        IModel model1 = new Model("test1");

        //Create the presenter with the model and any view implementing IView
        Presenter presenter = new Presenter(new View(), model1);

        //Add the view to a panel control in this form
        mainPanel.Controls.Add(presenter.View);

        //Change the model
        IModel model2 = new Model("test2");
        presenter.ChangeModel(model2);
    }
}
4

1 回答 1

0

如果您的设计是 MVP(模型视图演示器),您应该在演示器中创建模型。这就是这种模式背后的想法。视图与演示者通信,演示者向他提供他需要的所有方法、属性和事件。在您的示例中,您也决定创建一个模型。你可以这样做,但请从视图中隐藏它。与您的示例相关,删除构造函数中的 IModel 参数并在代码中创建一个新参数。

考虑通过方法 (_view.SetName("me") 设置视图更改。这可以让您以后的生活更轻松。

无需创建新的 winforms 表单。也许,我不明白你的意思。

更新:

看看下面的例子。您有视图、演示者和模型的接口(基于您的代码)。我刚刚将 IModel 重命名为 ICustomer 以明确我的观点。演示者创建一个模型来做一些 I/O 工作,并获得一个视图界面来更新窗口或界面后面的任何东西。

public interface IView
{
    public string CustomerName { get; set; }
}

public interface ICustomer
{
    string CustomerName { get; set; }
}

public interface IModel
{
    void Save(ICustomer entity);
    void Update(ICustomer entity);
    ICustomer Create();
}


public class Customer : ICustomer
{
    public string CustomerName {get;set;}

}

public class MyModel : IModel
{

    public void Save(ICustomer entity)
    {
        //Do something here..
    }

    public void Update(ICustomer entity)
    {
        //Do something here..
    }

    public ICustomer Create()
    {
        return new Customer();
    }
}

public class Presenter
{
    private IView _view;
    private ICustomer _entity;
    private IModel _model = new MyModel();

    public Presenter(IView view)
    {
        _view = view;
        _model = new MyModel();
        _entity = _model.Create();

        _view.CustomerName = _entity.CustomerName;
    }

    public void Save()
    {
        _model.Save(_entity);
    }

    public void Cancel()
    {
        _entity = _model.Create();
    }

    public void UpdateModel(ICustomer customer)
    {
        _model.Update(customer);
        _view.CustomerName = customer.CustomerName;
    }
}
于 2013-08-16T12:26:09.367 回答