c# - Bindings not working for views first time MvvmLight -


i have been using approach mvvm navigation create datatempalte viewmodel view inside. main window setup this

<window x:class="vaultprez.mainwindow"     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"     xmlns:ignore="http://www.ignore.com"     xmlns:v="clr-namespace:vaultprez.views"     xmlns:vm="clr-namespace:vaultprez.viewmodel"     mc:ignorable="d ignore"     height="720"     width="1280"     title="mvvm light application"     datacontext="{binding main, source={staticresource locator}}">  <window.resources>     <resourcedictionary>         <resourcedictionary.mergeddictionaries>             <resourcedictionary source="skins/mainskin.xaml" />         </resourcedictionary.mergeddictionaries>         <datatemplate datatype="{x:type vm:mainmenuviewmodel}">             <v:mainmenu />         </datatemplate>         <datatemplate datatype="{x:type vm:headerviewmodel}">             <v:header />         </datatemplate>         <datatemplate datatype="{x:type vm:mediaviewmodel}">             <v:mediaviewer />         </datatemplate>     </resourcedictionary> </window.resources>  <grid x:name="layoutroot">     <grid.rowdefinitions>         <rowdefinition height="50"></rowdefinition>         <rowdefinition height="*"></rowdefinition>     </grid.rowdefinitions>     <contentpresenter grid.row="0" content="{binding header}" />     <contentpresenter grid.row="1" content="{binding currentview}" /> </grid> 

the name space v references actual views , vm viewmodels. main view model view

public class mainviewmodel : viewmodelbase {     private readonly dataaccessservice dataservice;      private viewmodelbase currentview;      private viewmodelbase header; ...      public dictionary<string, viewmodelbase> views { get; set; }      public viewmodelbase currentview     {         { return currentview; }         set         {             if (currentview == null)                 currentview = value;             else if (currentview != value)             {                 viewstates.push(currentview);                 currentview = value;                 raisepropertychanged("currentview");             }         }     }      public viewmodelbase header     {         { return header; }         set         {             header = value;             raisepropertychanged("header");         }     }      /// <summary>     /// initializes new instance of mainviewmodel class.     /// </summary>     public mainviewmodel(idataaccessservice dataservice)     {         this.dataservice = dataservice dataaccessservice;         views = new dictionary<string, viewmodelbase>();          viewstates = new observablestack<viewmodelbase>();          viewstates.collectionchanged += viewstates_collectionchanged;         views.add("mainmenu", new mainmenuviewmodel(dataservice));         views.add("mediaviewer", new mediaviewmodel(dataservice));         currentview = views["mainmenu"];         header = new headerviewmodel(dataservice);          registermessages();     }      private void registermessages()     {         messengerinstance.register<backmessage>(this, (message) =>         {             onback();         });         messengerinstance.register<changeviewmessage>(this, (message) =>         {             currentview = views[message.view];         });         messengerinstance.register<cancelbackmessage>(this, (message) =>         {             cancelback = true;             waiting = false;         });         messengerinstance.register<savemediamessage>(this, (message) =>         {             if (message.media != null)                 dataservice.savemedia();             waiting = false;         });     }      void viewstates_collectionchanged(object sender, system.collections.specialized.notifycollectionchangedeventargs e)     {         if (((observablestack<viewmodelbase>)sender).count < 1)             messengerinstance.send<setbackvisibilitymessage>(new setbackvisibilitymessage() { visibility = visibility.hidden });         else             messengerinstance.send<setbackvisibilitymessage>(new setbackvisibilitymessage() { visibility = visibility.visible });     }      private void onback()     {         //messagebox.show("back");         if (currentview == views["mediaviewer"])         {             waiting = true;             messengerinstance.send<asksavemediamessage>(new asksavemediamessage());             task t = task.factory.startnew(() =>             {                 while (waiting)                     if (!waiting) break;             });             t.wait();         }         if(!cancelback)         {             currentview = viewstates.pop();             raisepropertychanged("currentview");         }         cancelback = false;     } 

but part relevant viewmodels stored in dictionary , when main view receives message change view moves specified 1

messengerinstance.register<changeviewmessage>(this, (message) => {     currentview = views[message.view]; }); 

in theory when binding currentview has view type of mainmenuviewmodel mainmenu shows etc. works on other views when change them doesn't work first time, bindings empty on view when go main menu try second time fine bound properly.

the viewmodel has data too, nothing null on first try.

if 3 or 4 view program i'd iterate through every view during load plan on having around 20 views , time consuming.

am doing fundamentally wrong?

edit: here viewmodellocator.cs

public class viewmodellocator {     static viewmodellocator()     {         servicelocator.setlocatorprovider(() => simpleioc.default);          if (viewmodelbase.isindesignmodestatic)         {         }         else         {             simpleioc.default.register<idataaccessservice, dataaccessservice>();         }          simpleioc.default.register<mainviewmodel>();         simpleioc.default.register<mainmenuviewmodel>();         simpleioc.default.register<headerviewmodel>();         simpleioc.default.register<mediaviewmodel>();     }      /// <summary>     /// gets main property.     /// </summary>     [system.diagnostics.codeanalysis.suppressmessage("microsoft.performance",         "ca1822:markmembersasstatic",         justification = "this non-static member needed data binding purposes.")]     public mainviewmodel main     {         { return servicelocator.current.getinstance<mainviewmodel>(); }     }      public mainmenuviewmodel menu     {         { return servicelocator.current.getinstance<mainmenuviewmodel>(); }     }      public headerviewmodel header     {         { return servicelocator.current.getinstance<headerviewmodel>(); }     }      public mediaviewmodel media      {         { return servicelocator.current.getinstance<mediaviewmodel>(); }     }     /// <summary>     /// cleans resources.     /// </summary>     public static void cleanup()     {     } } 

your view is, far can make out, absolutely fine. use same mechanism no issues. think problem may lie in viewmodel here: 'views.add("mainmenu", new mainmenuviewmodel(dataservice));' . newing instances of viewmodels doesn't work way expect to. add (true) end of simpleioc registrations - simpleioc.default.register(true);. viewmodels lazy loaded singletons default. passing true parameter simpleioc registration turns off lazy loading.


Comments

Popular posts from this blog

css - SVG using textPath a symbol not rendering in Firefox -

Java 8 + Maven Javadoc plugin: Error fetching URL -

node.js - How to abort query on demand using Neo4j drivers -