c# - How do I update the parent viewmodel when child viewmodel is updated -
in first view model (renamed mainviewmodel) have list of actionviewmodels. in xaml have listbox bound list, in listbox have template binds properties actionviewmodel.
so far , works. when selecting 1 of listitems navigate actionviewmodel , pass id it. actionviewmodel retrieves information static list in memory mainviewmodel retrieved information create list of actionviewmodels.
so far still good, can edit properties, bindings work fine , i'm happy. clicking save button information gathered , stored in static list. when hit button go list, unfortunately values showing there still same, there way send command reload items in list? pass complete viewmodel reference new actionviewmodel? or property tells parent 'this viewmodel in list has been updated'?
i sure above text bit confusing, here code clarify bit (hopefully)
mainviewmodel.cs
private list<actionviewmodel> _actionviewmodels; public list<actionviewmodel> actionviewmodels { { return _actionviewmodels; } set { _actionviewmodels = value; raisepropertychanged(() => actionviewmodels); } } private cirrious.mvvmcross.viewmodels.mvxcommand<int> _navigatetoaction; public system.windows.input.icommand navigatetoaction { { _navigatetoaction = _navigatetoaction ?? new cirrious.mvvmcross.viewmodels.mvxcommand<int>((action) => navigatetothedesiredaction(action)); return _navigatetoaction; } } private void navigatetothedesiredaction(int action) { showviewmodel<actionviewmodel>(new { id = action }); } // dtos server or cache , fill list of actionviewmodels public async task load() { actionservice actionservice = new actionservice(); list<actionviewmodel> actionviewmodels = new list<actionviewmodel>(); myactions = await actionservice.getmyactions(); foreach (actiondto action in myactions) { actionviewmodel actionviewmodel = new actionviewmodel(); await actionviewmodel.load(action.id); actionviewmodels.add(actionviewmodel); } actionviewmodels = actionviewmodels; }
actionviewmodel.cs
public int id { { return theaction.id; } set { theaction.id = value; raisepropertychanged(() => id); } } public string title { { return theaction.title; } set { theaction.title = value; raisepropertychanged(() => title); } } public async task load(int actionid) { actiondto theaction = await actionservice.getaction(actionid); this.id = theaction.id; this.title = theaction.title; } private cirrious.mvvmcross.viewmodels.mvxcommand _save; public system.windows.input.icommand save { { _save = _save ?? new cirrious.mvvmcross.viewmodels.mvxcommand(presavemodel); return _save; } } private void presavemodel() { savemodel(); } private async task savemodel() { validationdto result = await actionservice.saveaction(theaction); }
actionservice.cs
public static list<actiondto> allactions = new list<actiondto>(); public async task<actiondto> getaction(int actionid) { actiondto action = allactions.firstordefault(a => a.id == actionid); if (action == null) { int tempactionid = await loadaction(actionid); if (tempactionid > 0) return await getaction(actionid); else return new actiondto() { error = new validationdto(false, "failed load action id " + actionid, errorcode.invalidactionid) }; } return action; } private async task<int> loadaction(int actionid) { actiondto action = await webservice.getaction(actionid); allactions.add(action); return action.id; } public async task<validationdto> saveaction(actiondto action) { list<actiondto> currentlist = allactions; actiondto removeactionfromlist = currentlist.firstordefault(a => a.id == action.id); if (removeactionfromlist != null) currentlist.remove(removeactionfromlist); currentlist.add(action); allactions = currentlist; return await webservice.saveaction(action); }
there 3 ways can think of allow this.
the
actionservice
send out sort of notification when data changes. 1 easy way use mvvmcross messenger plugin. way collectabull service works in collectionservice.cs in n+1 days of mvvmcross videos (for more info watch n=13 in http://mvvmcross.wordpress.com)this approach use. has low overhead, uses
weakreference
s (so doesn't leak memory), extensible (any object can listen changes), , encourages loose coupling of viewmodel , model objectsyou implement kind of
refresh
api on list viewmodel , call appropriate view events (e.g.viewdidappear
,onnavigatedto
,onresume
).i don't use approach refreshing known data, have used enabling/disabling resource intensive objects - e.g. timers
for shape of model data (and how changes), can imagine scenarios approach might more efficient messenger approach.
you extend use of
inotifypropertychanged
,inotifycollectionchanged
model layer.i've done few times , it's worked me.
if choose approach, careful ensure views subscribe change events using
weakreference
subscriptions such used in mvvmcross binding - see weaksubscription. if didn't this, possible model cause views persist in memory after ui has removed them.
Comments
Post a Comment