Sunday, September 16, 2012

SimpleIoc and the Messenger Service in MVVM Light

,

The SimpleIoc addition in the most recent version of MVVMLight is a great add and really simplified the ViewModelLocator across all of the platforms supported in this framework.

If you are not familiar with MVVM Light or what you types of project platforms it supports please go to http://mvvmlight.codeplex.com or www.galasoft.ch/mvvm to learn more.

However if you are using the Messenger Service in MVVM Light to perform a set of actions to do the following:

  • User takes an action
  • Application changes views
  • Application send message to display or load data

then it is important to note that there are some differences in the way that the ViewModels are loaded in comparison to the previous version of MVVM Light.

Lets look at the ViewModelLocator in the new version:



    public class ViewModelLocator
    {
        static ViewModelLocator()
        {
            ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

            if (ViewModelBase.IsInDesignModeStatic)
            {
                SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
            }
            else
            {
                SimpleIoc.Default.Register<IDataService, DataService>();
            }
            SimpleIoc.Default.Register<MainViewModel>();        
            SimpleIoc.Default.Register<SecondViewModel>();
        }

        /// <summary>
        /// Gets the Main property.
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
        "CA1822:MarkMembersAsStatic",
        Justification = "This non-static member is needed for data binding purposes.")]
        public MainViewModel Main
        {
            get
            {
                return ServiceLocator.Current.GetInstance<MainViewModel>();
            }
        }
   }



Notice that in comparison to what you may have seen in the past version, there is a single property to the ViewModel and a simple line in the constructor here to register the ViewModel with the Ioc Container and that is it.

The property for the ViewModel is Lazy, meaning that it is loaded on demand and is a singleton.  You can create multiple instances by passing in a key upon creation, but for this example I'll keep it simple.

Given the scenario above you will get the result of the secondary view not getting the message sent event though you have registered the message with the Message Service and have an action ready to handle it.  BUT the second time through it's fine and operates as it should.  What has happened?

Very simply, the examples you have seen in the past very rarely ever cover situations in the real world nor do they ever go far enough to look at the overloads in the constructor etc.

What has happened here is that the ViewModel MUST exist first in order to take action on the message. Moreover, the Messenger Service in MVVM Light does not operate like a Service Bus or Message Queue where the messages stay there until they are read.  It is more similar to Events, a fire and forget model.

In order to alleviate said problem, simple pass in "true" to the Register call in the SimpleIoc to create the instance of the ViewModel immediately and go on with your coding.


  SimpleIoc.Default.Register<SecondViewModel>(true);



The previous version of MVVM Light created all of the ViewModels immediately, although not too much of an issue; there are instances where a user may not go to every view in the application and the idea here is to only load what is needed and keep the View and ViewModels loaded in memory when necessary.

If you have questions please comment and/or contact me on twitter @spboyer

2 comments to “SimpleIoc and the Messenger Service in MVVM Light”

  • October 2, 2012 at 10:49 AM
    NioxyBrown says:

    Hi,

    I've one question about the loading of the datas.
    I'm new in C#, windows 8 apps and XAML.
    So I took for start the template in Visual Studio 2012 Grid Apps.
    I want to rewrite it but with the MVVM pattern and with Mvvm Light Toolkit.
    My question is how my MainViewModel will load the sample datas if I want to put the behind code of the page in the viewModel?
    Because in the template I have in the code behind of the MainPage:

    var ProductDataCategories = ProductDataSource.GetCategories((string)navigationParameter);
    this.DefaultViewModel["Categories"] = ProductDataCategories;

    I want to put the work of this two lines in my Load method, but I don't know how to manage it (I have not enough skills in C# :s)


    I'm digging nearby the EventTrigger and the Command.

    XAML:








    MainViewModel:

    private ICommand _loadDataCommand;
    public ICommand LoadDataCommand
    {
    get
    {
    if (_loadDataCommand == null)
    {
    _loadDataCommand = new DelegateCommand(() => LoadData());
    }
    return _loadDataCommand;
    }
    }

    public void LoadData()
    {
    //How I load my data from the SampleDataSource?
    }


    I spent 4 days for find out an answer...

    Thanks you by advance!

    delete
  • October 5, 2012 at 10:52 AM
    NioxyBrown says:

    Hi,

    I solved my problem!

    Thanks!

    delete
Powered by Blogger.
 
Creative Commons License
TattooCoder.com by Shayne Boyer is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.