问题
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 i.e DataGridView can publish current row data?
回答1:
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);
回答2:
The View may have knowledge of Model as long as the interaction is limited to data binding only. i.e. 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.
回答3:
Is it OK to get DataSource in Presenter and there set its DataSource ? e.g. 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.
来源:https://stackoverflow.com/questions/13015999/mvp-view-knows-model