c# - MVVM pattern: an intermediate View between Command binding and ViewModel execute -
scenario date loaded program (e.g., evaluation of students in class each student distinct entity his/her evaluation data) , summary of them shown on datagrid. user selects selects of students, , performs analysis on evaluation. analysis process requires parameters, therefore before analysis window pops-up , lets user specify preferred parameters; analysis process executes.
implementation summary datagrid defined following , binded viewmodel:
<datagrid x:name="cachedsamplesdg" itemssource="{binding cacheddatasummary}"> <datagrid.columns> <datagridtextcolumn header="name" binding="{binding name}"/> <datagridtextcolumn header="score" binding="{binding score}"/> </datagrid.columns> </datagrid>
the button starts process defined following:
<button x:name="analysisbt" content="analyze" command="{binding analyzecommand}" commandparameter="{binding elementname=cachedsamplesdg, path=selecteditems}"/>
the viewmodel pretty basic , summarized following:
internal class cacheddatasummaryviewmodel { public cacheddatasummaryviewmodel() { _cacheddatasummary = new observablecollection<cacheddatasummary>(); analyzecommand = new samplesanalyzecommand(this); } private observablecollection<cacheddatasummary> _cacheddatasummary; public observablecollection<cacheddatasummary> cacheddatasummary { { return _cacheddatasummary; } } public icommand analyzecommand { get; private set; } }
and here definition of analysis command:
internal class samplesanalyzecommand : icommand { public samplesanalyzecommand(cacheddatasummaryviewmodel viewmodel) { _viewmodel = viewmodel; } private cacheddatasummaryviewmodel _viewmodel; public event eventhandler canexecutechanged { add { commandmanager.requerysuggested += value; } remove { commandmanager.requerysuggested -= value; } } public bool canexecute(object parameter) { // canexecute logic } public void execute(object parameter) { // process mess ... // here need selected rows of datagird, "parameter" delegates them. // need other parameters analysis user can set through view } }
an diagram of current process , next
question when button clicked
- apply ui changes on mainwindow
- pop-up processoptionswindow
- get set parameters processoptionswindow
- pass selected datagrid rows , user specified parameters
samplesanalyzecommand
what best way achieve requirement ?
you can define model , viewmodel process options, , in samplesanalyzecommand, display processoptionsview. when user done processoptionsview, main viewmodel gets notified (e.g event handler) , completes process.
something this:
internal class samplesanalyzecommand : icommand { ... public void execute(object parameter) { this._viewmodel.showprocessoptions(parameter); } } internal class cacheddatasummaryviewmodel { public string status { { return this.status; } set { if (!string.equals(this.status, value)) { this.status = value; // notify property change ui } } } ... internal void showprocessoptions(object paramter) { // model var processoptions = new processoptionsmodel() { otherinfo = parameter }; // view-model var processoptionsviewmodel = new processoptionsviewmodel(); processoptionsviewmodel.model = processoptions; // view var processoptionsview = new processoptionsview( processoptionsviewmodel ); // edit2: update status this.status = "selecting process options..."; // can use event handler or dialog result processoptionsviewmodel.ok += this.performprocess; processoptionsview.showdialog(); } private void performprocess(object sender, eventargs e) { var processoptionsview = sender processoptionsview; var processoptionsmodel = processoptionsview.model; var processoptions = processoptionsmodel.model; // edit2: update status this.status = "performing process..."; // use processoptions.otherinfo initial info // use processoptions.* process options info // , perform process here // edit2: update status this.status = "process done."; } ... } class processoptionsmodel { public object otherinfo { get; set; public int parameter1 { get; set; } public ilist<processitem> selecteditems { get; set; } ... } class processoptionsviewmodel { public event eventhandler ok; private samplesanalyzecommand model; private icommand okcommand; public processoptionsviewmodel() { this.okcommand = new okcommand(this.onok); } public samplesanalyzecommand model { { return model; } set { this.model = value; // property changed stuff here } } private void onok(object parameter) { if (this.ok != null) { this.ok = value; } } } class processoptionsview { // interacts it's view-model , performs ok command if // user pressed ok or }
hope helps.
edit (1):
as blindmeis suggested, may use dialog service make connection between views.
edit (2):
immidiate ui changes after button click can done in showprocessoptions method of showprocessoptions. don't think want reflect ui changes of options window while user works it, main window. ui changes after user closes options window can done in performprocess.
if want make abstraction options selection (e.g reading file) mentioned in comment below, may define ioptionsprovider interface, , put processoptionsview , view-model behind still use same model.
interface ioptionsprovider { processoptionsmodel getprocessoptions(); } class processoptionsview : ioptionsprovider { public processoptionsmodel getprocessoptions() { if (this.showdialog()) { return this.modelview.model; } return null; } } class processoptionsfromfile : ioptionsprovider { public processoptionsmodel getprocessoptions() { // create instance of processoptionsmodel file }
}
note in case removed ok event since getprocessoptions supposed block until user closes main window. if want responsive approach in fromfile case, may need work on async stuff, maybe define getprocessoptionsasync instead.
in case things may little bit complicated guess achievable in way.
Comments
Post a Comment