c# - WPF Mvvm navigation with parameters -
following this tutorial (among others) , reading questions asked here i've constructed navigation mechanism allow me pass parameters between viewmodels
:
object base - every view model inherits it:
public abstract class objectbase : inotifypropertychanged { //inotifypropertychanged members ... //navigation handling public abstract objectbase backlocation { get; } public abstract event action<objectbase> navigateto; public abstract string viewheader { get; } }
mainviewmodel - in charge of navigation:
public class mainviewmodel : objectbase { private objectbase _selectedview; private commandbase _backcommand; public mainviewmodel() { selectedview = new firstviewmodel(); } public objectbase selectedview { { return _selectedview; } set { setproperty(ref _selectedview, value); //register navigation event of new view selectedview.navigateto += (target)=> { selectedview = target; }; } } //this command bound button on main view public commandbase backcommand { { return _backcommand ?? (_backcommand = new commandbase(back)); } } private void back(object obj) { if (selectedview.backlocation != null) { selectedview = selectedview.backlocation; } else { application.current.shutdown(); } } }
and main view:
<window ... <window.datacontext> <vm:mainviewmodel/> </window.datacontext> <window.resources> <datatemplate datatype="{x:type vm:firstviewmodel}"> <views:firstview/> </datatemplate> <datatemplate datatype="{x:type vm:secondviewmodel}"> <views:secondview/> </datatemplate> </window.resources> <contentpresenter content="{binding selectedview}"/> </window>
my problem is: if set datatemplates
in main view above makes each view aware of it's datacontext
if want add datacontext
explicitly view in order use intellisense this:
<usercontrol x:class="wpf_navigationtest.views.firstview" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:viewmodels="clr-namespace:wpf_navigationtest.viewmodels"> <!--this causes view model's constructor called again--> <usercontrol.datacontext> <viewmodels:firstviewmodel/> </usercontrol.datacontext> <grid> <textblock text="user control 1" fontsize="40"/> </grid>
the view model's
constructor called twice, losing parameters passed navigate
event.
the problem here setting datacontext
inside usercontrol
, , in main view model.
<usercontrol.datacontext> <viewmodels:firstviewmodel/> </usercontrol.datacontext>
the code above instantiating new firstviewmodel
every time usercontrol
created. therefore when control gets created contentcontrol
(based on datatemplate
), goes ahead , creates new firstviewmodel
.
so, solution here remove usercontrol.datacontext
declaration in usercontrol
, , can instead set datacontext
of contentcontrol
of selectedview
.
<contentpresenter content="{binding selectedview}" datacontext="{binding selectedview}"/>
in order use multiple view models single view, can add datatemplate
:
<datatemplate datatype="{x:type vm:thirdviewmodel}"> <views:secondview/> </datatemplate>
for design-time data (to intellisense), can make use of d:datacontext
explained in this article.
this require set view models static resources, recommend creating them in separate resourcedictionary
.
Comments
Post a Comment