c# - How to display complex data in MVP Passive View -
i've been looking in mvp pattern while, , managed create simple mvp-compliant applications.
i trying apply pattern more complex application, , have doubts on best way of doing that.
my application has single winform, 2 buttons loading 2 different kinds of data. view interface looks following:
interface iview_mainform { // load input // event eventhandler<inputloadeventargs> loadinput_01; event eventhandler<inputloadeventargs> loadinput_02; bool input01_loaded { get; set; } bool input02_loaded { get; set; } }
the iview referenced in presenter via constructor injection:
public presenter_mainform(iview_mainform view) { this.view = view; this.view.loadinput_01 += new eventhandler<inputloadeventargs>(onloadinput_01); this.view.loadinput_02 += new eventhandler<inputloadeventargs>(onloadinput_02); }
so far, good. when user clicks of 2 buttons loading data, loadinput_## event raised, presenter handling it, checks input errors , structures according data model.
my next step displaying processed data in view.
i'm striving keep view passive , "dumb" possible, assuming knows nothing of presenter (it doesn't subscribe events, presenter sends data view calling iview methods instead), let alone of model.
how supposed populate control treeview, if view has no idea of data model looks like?
also, getting whole mvp thing right, or there have missed?
there nothing wrong having complex type
properties in view
. let's have complextype
.
class complextype { public string parentnode {get;set;} public list<string> childnodes {get;set;} // other properties }
let's assume complextype
data model treeview
. fine mvp
pattern have properties on view
have complextype
. having fine
interface iview_mainform { // load input // event eventhandler<inputloadeventargs> loadinput_01; event eventhandler<inputloadeventargs> loadinput_02; bool input01_loaded { get; set; } bool input02_loaded { get; set; } complextype input01data {get;set;} // might have code in get/set setters complextype input02data {get;set;} // might have code in get/set setters public void setinput01data(complextype input01data) { input01data = input01data; // other stuff } }
and since model
view
has 2 inputs, model this
public interface imodel { public complextype input01data {get;set;} public complextype input02data {get;set;} }
now in presenter
handle event fired view
, populate model
, set properties on view
class presenter { private imodel _mymodel... private irepository _repository; public presenter(iview_mainform view, irepository repository) { _repository = repository; this.view = view; this.view.loadinput_01 += new eventhandler<inputloadeventargs>(onloadinput_01); this.view.loadinput_02 += new eventhandler<inputloadeventargs>(onloadinput_02); } public void onloadinput_01(object sender, inputloadeventargs e) { // data based on passed arguments (e.someproperty) // construct imodel mymodel = _repository.getdata(e.someproperty); // pass data iview_mainform view.setinput01data(mymodel.input01data); } }
and regarding concern
i'm striving keep view passive , "dumb" possible, assuming knows nothing of presenter (it doesn't subscribe events, presenter sends data view calling iview methods instead), let alone of model.
your view
still doesn't know presenter
nor model
. fires events, data presenter
, binds controls. , have testability
in place (please note unit test pseudo code, since don't know how retrieve data, input required in button click event etc...) .
[test] public void shouldloadinput01dataonbuttonclick() { // arrange imodel data = // create dummy data mock<iview_mainform> clientsviewmock = new mock<iview_mainform>(); mock<irepository> clientsrepositorymock = new mock<irepository>(); clientsrepositorymock.setup(repository => repository.getdata(something)).returns(data.input01data); var presenter = new presenter(clientsviewmock.object, clientsrepositorymock .object); // act clientsviewmock.raise(view => view.loadinput01 += null, new inputloadeventargs()); // assert clientsviewmock.verify(view => view.setinput01data(data.input01data), "input01 data expected set on button click."); }
Comments
Post a Comment