c# - Pass data across viewmodels -


i can't figure out. try describe problem best can.

i building application using mvvm pattern. have user control aaaview viewmodel aaaviewmodel used fill data class cdataclass. have main window mainview , viewmodel mainviewmodel. next have window dialogview dialogviewmodel.

so mainviewmodel (that has own user control) creates dialogviewmodel (with instance of user control). how can transfer data in cdataclass between these 2 user controls? tried create property in aaaviewmodel hold instance of mainviewmodel or dialogviewmodel can pass data stuck because couldn't make dependency property.

image representation of problem

my goal make user control can used in different views can have different data in underlaying cdataclass.

just clarify... using user control <views:generalinfoview grid.row="0" /> , don't know how share data between 2 different instances of same user control in different views. point pattern or method appreciate.

thank help.

i don't think it's ideal you've got application architecture diagrammed relationships among views; think better way think set of relationships among viewmodels, views hanging off tree needed. when think way, "how data passed" gets lot simpler. view conduit between viewmodel , user. don't design house set of windows , telephones , try figure out floor plan that. start house , how people live in it.

so easy:

some viewmodels have aaviewmodel property. there may kinds of simple or complicated views on viewmodels; if view wants let user edit viewmodel's aaviewmodel stuff, includes aaview bound appropriately viewmodel's aaviewmodel. mainviewmodel , dialogviewmodel both big complicated interactive views want let edit vm's aaviewmodel stuff.

if mainviewmodel dialogviewmodel's parent, or created temporary instance of dialogviewmodel put in modal dialog, mainviewmodel show dialog, , have @ dialogvm.aavm.cdata.isdirty decide it. or maybe gives dialogvm.aavm new cdataclass instance before showing dialog (maybe clone of own instance), , if showmodel() returns true, dialogvm.aavm.cdata.

the point once viewmodels driving everything, becomes relatively simple them communicate each other. parent-child easy: parent gives stuff child , looks @ child brings back. viewmodel can subscribe viewmodel's propertychanged event; parent viewmodel can monitor children; when happens on child, parent can decide whether update sibling. in general, children should not know @ parents; makes easier reuse child viewmodels in disparate contexts. it's parents decide information.

all aaviewmodel knows handed him copy of cdataclass; updates public properties accordingly. else (probably aaview, doesn't know) hands him changes setting properties; updates cdataclass instance accordingly. after while, unknown him, 1 viewmodel or comes , looks @ cdataclass.

and communication between views , viewmodels happens via bindings.

update

it turns out you're creating viewmodels in views, , result have no idea how parent can them. , know why it's not idea create child view viewmodels way.

here's how child view/viewmodels in viewmodel-centric design described above:

first, rid of whatever you're doing create child viewmodels inside view.

second, create datatemplate child viewmodel type. should go in resource dictionary merged resources in app.xaml, it's simple won't kill if lazy , paste resources of 2 different views it's used.

i don't know namespace declarations like. i'm going assume views in called xmlns:view="...", , viewmodels in called xmlns:vm="...".

<datatemplate datatype="{x:type vm:aaaviewmodel}">     <view:aaaview /> </datatemplate> 

now, can assign aaaviewmodel contentproperty of control inherits contentcontrol (and that's of them), , template instantiated. means xaml create aaaview , assign instance of aaaviewmodel datacontext property of aaaview created.

so let's create child aaaviewmodel next, , we'll show in ui.

public class dialogviewmodel  {      //  can create in dialogviewmodel's constructor if need      //  give parameters won't known until then.      private aaaviewmodel _aaavm = new aaaviewmodel();     public aaaviewmodel aaavm     {         { return _aaavm; }         protected set {             _aaavm = value;             onpropertychanged(nameof(aaavm));         }     } 

and can display aaavm in dialogview:

<grid>     <grid.rowdefinitions>         <rowdefinition height="auto" />         <rowdefinition height="*" />     </grid.rowdefinitions>      <contentcontrol          content="{binding aaavm}"          grid.row="0"         />      <stackpanel orientation="vertical" grid.row="1">         <!-- other stuff -->     </stackpanel> </grid> 

now how mainviewmodel in touch dialogviewmodel? in case of dialogs, since have finite lifespan, it's not big deal let them create own viewmodels. can either way. lean towards having create own in second example below.

not quite same, close. first, once again, rid of whatever you're doing dialog creates own viewmodel.

mainviewmodel.cs

public cdataclass cdc { /* know drill */ }  public void showdialog() {     var dvm = new dialogviewmodel();      //  maybe isn't want; don't know cdataclass does.      //  i'm assuming has copy constructor.      dvm.aaavm.cdc = new cdataclass(this.cdc);      if (dialogview.showdialog(dvm).getvalueordefault())     {         cdc = dvm.cdc;     } } 

note next 1 view codebehind, not viewmodel.

dialogview.xaml.cs

public static bool? showdialog(dialogviewmodel dvm) {     var vw = new dialogview() { datacontext = dvm };      return vw.showdialog(); } 

now, could let dialog continue creating own viewmodel; in case give public property this:

public dialogviewmodel viewmodel => (dialogviewmodel)datacontext; 

and showdialog method this:

dialogview.xaml.cs

public static bool? showdialog(cdataclass cdc) {     var dlg = new dialogview();      dlg.viewmodel.aaavvm.cdc = cdc;      return dlg.showdialog(); } 

and parent interact instead:

mainviewmodel.cs

public void showdialog() {     var cdcclone = new cdataclass(this.cdc);      if (dialogview.showdialog(cdcclone).getvalueordefault())     {         cdc = cdcclone;     } } 

nice , tidy.

if dialog isn't modal, make dialog viewmodel private member of mainviewmodel, , have mainviewmodel subscribe events on dialog viewmodel keep abreast of dialog doing. whenever user updates dialog's copy of cdataclass, dialog raise dataclassupdated, , mainviewmodel have handler event sniffs @ _dialogviewmodel.aaavm.cdc, , decides it. can example code if necessary.

so can see mean building in terms of parent/child viewmodels, , stuffing them views when , appropriate.


Comments