简体   繁体   中英

Mvp View knows Model

I'm trying to use MVP and I notice that my View must know Model that should not happen in MVP I presume.

here is example:

public partial class TestForm : Form, ITestView
{
    public void LoadList(IEnumerable<AppSignature> data)
    {
        testPresenterBindingSource.DataSource = data;
    }
}

public interface ITestView
{
    event EventHandler<EventArgs> Load;
    void LoadList(IEnumerable<AppSignature> data);
}

public class TestPresenter
{
   private ITestView view;

   public TestPresenter(ITestView view)
   {  
       this.view = view;
       view.Load += View_Load;
   } 

   private void View_Load(object sender, EventArgs e)
   {
       var data = // get from model
       view.LoadList(data);
   }
}

and the problem is that in TestForm I need reference to AppSignature. In all tutorials I saw, there are some simple examples like public void LoadList(IEnumerable<String> data) where there is no need reference to model. But how ie DataGridView can publish current row data?

Your form is a View, it is not a Presenter. Thus it should implement interface ITestView :

public interface ITestView
{
    event EventHandler Load;
    void LoadList(IEnumerable<AppSignatureDto> data);
}

And your Presenter is someone, who subscribes to view's events and uses view properties to read and update view:

public class TestPresenter
{
   private ITestView view;

   public TestPresenter(ITestView view)
   {  
       this.view = view;
       view.Load += View_Load;
   } 

   private void View_Load(object sender, EventArgs e)
   {
       List<AppSignature> signatures = // get from model
       List<AppSignatureDto> signatureDtos = // map domain class to dto
       view.LoadList(signatureDtos);
   }
}

And you form, as I already said, is a view, it does not know anything about presenter and model:

public partial class TestForm : Form, ITestView
{
    public event EventHandler Load;    

    private void ButtonLoad_Click(object sender, EventArgs e)
    {
        if (Load != null)
            Load(this, EventArgs.Empty);
    }

    public void LoadList(IEnumerable<AppSignatureDto> data)
    {
        // populate grid view here
    }
} 

How to deal with reference to domain classes? Usually I provide to view only simple data (strings, integers, dates, etc), or I create data transfer objects, which are passed to view (you can name them FooView, FooDto, etc). You can easily map them with something like AtoMapper :

List<AppSignatureDto> signatureDtos = 
      Mapper.Map<List<AppSignature>, List<AppSignatureDto>>(signatures);

The View may have knowledge of Model as long as the interaction is limited to data binding only. ie View should not try to manipulate Model directly. View will always redirect user input to Presenter and Presenter will take care of further actions. If any action performed by Presenter results in a change in state of Model, Model will notify View via data binding. Model will be completely unaware of existence of View.

Is it OK to get DataSource in Presenter and there set its DataSource ? eg Presenter code:

Public void LoadData()
{
    _view.Data.DataSource = Business.GetData().ToList();
}

Form code:

Public BindingSource Data
{
    get
    {
        return this.bsData;
    }
}

Thanks to that I dont need to add any references to the View, but I didn't see that solution in any other sources.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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