Passing Parameters to ViewModel Constructors

Apr 1, 2010 at 8:29 AM

Is there any way to pass parameters to ViewModel constructors? I've heard there's something using the Locator, but I've not seen any way described to actually implement it.

Coordinator
Apr 1, 2010 at 9:41 PM

Hi,

Yes, please check my MIX10 session at http://live.visitmix.com/MIX10/Sessions/EX14 and the source code at http://blog.galasoft.ch/archive/2010/03/16/sample-code-for-my-mix10-talk-online.aspx (check the one named MVVM Demo 2 (final))

This sample is injecting a DataService into the MainViewModel constructor.

Happy coding,

Laurent

Apr 3, 2010 at 2:27 PM

Thanks Laurent.

That worked perfectly, had to hack at the sample a bit to make it play with EF, but it seems fairly happy, just need to find a way to inform the ViewModels that are consuming the DataService that the data has changed and they need to refresh.

Regards

Richard

 

Jun 10, 2010 at 7:45 AM
Edited Jun 10, 2010 at 7:47 AM

Hi laurent,

how do i pass a parameter to viewmodel constructor in viewmodellocator if i am using Entity Framework (ria service) .. this is the error i m getting

        public static IUnityContainer Container { get; private set; }

        private static MainViewModel _main;

        public ViewModelLocator()
        {
            Container = new UnityContainer();

            if (ViewModelBase.IsInDesignModeStatic)
            {
                // Create design time view models
            }
            else
            {
                // Create run time view models
                Container.RegisterType<IFilesCategory, FilesCategory>();
//This line is giving me error:

//Error 1 The type 'ScannedFiles.Web.Model.FilesCategory' cannot be used as type parameter
// 'TTo' in the generic type or method 'Microsoft.Practices.Unity.IUnityContainer.RegisterType<TFrom,TTo>
//(params Microsoft.Practices.Unity.InjectionMember[])'. There is no implicit reference conversion 
//from 'ScannedFiles.Web.Model.FilesCategory' to 'ScannedFiles.Model.IFilesCategory'.	
//C:\Users\BabAs\Documents\Visual Studio 2010\Projects\Silverlight\BusinessApp\New folder\startAfresh\ScannedFiles\
//ScannedFiles\ViewModel\ViewModelLocator.cs

            }

            CreateMain();
        }

 Files Category contains the following fields:

1: Id, 2: Name, 3: Description, 4: Remarks

plus the partial class contains:

namespace ScannedFiles.Web.Model
{
    public partial class FilesCategory
    {
        public bool IsModified
        {
            get
            {
                return EntityState == EntityState.Modified;
            }
        }

        public bool IsNew
        {
            get
            {
                return (EntityState == EntityState.New) ||
                       (EntityState == EntityState.Detached);
            }
        }

        protected override void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);

            if (String.CompareOrdinal(e.PropertyName, "EntityState") == 0)
            {
                RaisePropertyChanged("IsNew");
                RaisePropertyChanged("IsModified");
            }
        }

    }
}

My interface for FilesCategory is like this:

using System.ComponentModel;

namespace ScannedFiles.Model
{
    public interface IFilesCategory
    {
        protected override void OnPropertyChanged(PropertyChangedEventArgs e);
    }
}

Where am i doing something wrong. Pls help me...

regards

ashutosh (just started programming :)  )


Coordinator
Jun 10, 2010 at 1:58 PM

Hi,

FilesCategory does not implement IFilesCategory in your sample, so Unity cannot create the desired instance.

Since this question is really not related to MVVM Light, I would recommend you to post it on StackOverflow.com. There, people with more time on their hand will hopefully be able to guide you. Maybe find a Unity tutorial too, to understand how this works.

Cheers,

Laurent

Dec 1, 2010 at 5:14 PM

And how do you guys are passing parameters like ids?

Ex:

 

public class UserViewModel {
  public UserViewModel(IFooService fooSerivce, int userId) {
    ...
  }
}

 

Dec 22, 2010 at 8:57 PM

There is a thought around using MvvmLight and view models overall in the question though.  I use spring.net. If there are any data daos that need to be passed in, they are all configured in the container as described above.

For parameters that may be dependent on what's active in the UI at the time, I may have the fooService already injected in the container but have the userId a property.

If you have to have it in the constructor, you may also want to consider arranging your view models hierarchically and setup a parent link between them. The parent view model could keep the user id (or the selection or whatever) and child objects can access it. Think of the resource dictionary in WPF controls. You can do the same thing with hierarchical DI containers that you get your view model from a DI container and just stick a placeholder for the id in the container at the parent level and pick it up at the child container level.

There are a number of ways. I use the hierarchy of view models alot when I have a view composed of dependent views that are complex so that the selection and other info (like my domain object session state) can propagate downward without effort. Think of it as adding a little of the dependency object + resource dictionary capabilities to view models. The entire eclipse stack in the java world has moved to this model in the new e4 platform.

The Locator pattern is a really, really simple version of the container but more statically configured. XAML can have constructor args so you can play with combinations of locator and direct instantiation but a DI container may be more useful in the long run.