locked
AutoWireViewModel Exception

    Question

  • I'm using Prism and Unity in my Universal app. I am getting an exception when the view's code behind calls InitializeComponent();

    My ViewModel inherits from BindableBase, and my View inherits from VisualStateAwarePage. In the views XAML, I am setting the page up like this:

    <prism:VisualStateAwarePage
        x:Class="MyApp.Hub.Views.LoginPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:MyApp.Hub.Views"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:vm="using:MyApp.Hub.ViewModels"
        xmlns:prism="using:Microsoft.Practices.Prism.StoreApps"
        xmlns:prismmvvm="using:Microsoft.Practices.Prism.Mvvm"
        prismmvvm:ViewModelLocator.AutoWireViewModel="True"
        mc:Ignorable="d"
        d:DataContext="{d:DesignInstance vm:LoginPageViewModel, IsDesignTimeCreatable=True}">

    The error I'm getting is when the view is initialized, and the exception is:

    Failed to assign to property 'Microsoft.Practices.Prism.Mvvm.ViewModelLocator.AutoWireViewModel'

    and the line number is pointing to prismmvvm:ViewModelLocator.AutoWireViewModel="True" above

    Saturday, September 06, 2014 8:51 AM

Answers

  • Found the problem - in my View I was setting the design time view model and using the following:

    IsDesignTimeCreatable=True

    Removing this, and using

    d:DataContext="{d:DesignInstance vm:MyViewModel}" only, seems to work

    Saturday, September 13, 2014 9:55 AM

All replies

  • OK - I have found out what is causing the error, but breaks what I'm trying to achieve. The error was because I have parameters in my viewmodel's contructor. As soon as I removed these parameters, it fired up.

    However, because I'm using Unity and have things like my EventAggregator, NavigationService and ViewModels registered in my container, I need the parameters being passed into the viewmodel.

    Saturday, September 06, 2014 10:26 AM
  • You need to register the types that the view model is injected with in the OnInitialize method of your App.xaml.cs:

    App.xaml.cs:

        sealed partial class App : MvvmAppBase
        {
            ...
            private readonly IUnityContainer _container = UnityServiceHelper.UnityContainer;
    
            protected override void OnInitialize(IActivatedEventArgs args)
            {
                _container.RegisterInstance<IMyService>(new MyService());
                _container.RegisterType<IEventAggregator, EventAggregator>(new ContainerControlledLifetimeManager());
            }
    
            protected override object Resolve(Type type)
            {
                return _container.Resolve(type);
            }
        }
    


    LoginPageViewModel:

    public LoginPageViewModel(IMyService service)
    {
     ...
    }


    Please refer to the following link for more information about how set up Prism and Unity for a Windows Store App: http://blog.thomaslebrun.net/2014/02/windows-8-1-introduction-to-prism-for-the-windows-runtime/#.VArkeHkcSM8

    Saturday, September 06, 2014 10:52 AM
  • No luck there Magnus, still the same issue. Below is a cut down version of what I have setup:

    //app.xaml
    <prism:MvvmAppBase
        x:Class="MyApp.Hub.App"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="using:Microsoft.Practices.Prism.Mvvm">

        <Application.Resources>
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="/Styles/BaseStyles.xaml"/>
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
        </Application.Resources>
    </prism:MvvmAppBase>

    //app.cs
    namespace MyApp.Hub
    {

     public sealed partial class App : MvvmAppBase
     {


            private IUnityContainer _container;

            protected override Task OnLaunchApplication(LaunchActivatedEventArgs args)
            {

               // Navigate to the login page.
               NavigationService.Navigate("Login", null);

                Window.Current.Activate();
                return Task.FromResult<object>(null);
            }


            protected override Task OnInitialize(IActivatedEventArgs args)
            {
                //create the container and it's objects
                CreateUnityContainer();

                //set the default viewmodel - IT IS EHRE THE ERROR OCCURS
                ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver((viewType) =>
                  {
                      var viewModelTypeName = string.Format(CultureInfo.InvariantCulture, "MyApp.Hub.ViewModels.{0}ViewModel, MyApp.Hub", viewType.Name);
                      var viewModelType = Type.GetType(viewModelTypeName);

                      if (viewModelType == null)
                      {
                          if (Debugger.IsAttached)
                              Debugger.Break();
                      }

                      return viewModelType;
                  });

                ViewModelLocationProvider.SetDefaultViewModelFactory((type) => _container.Resolve(type));

                return base.OnInitialize(args);
            }

     private void CreateUnityContainer()
            {
                //create a container to store the objects
                if (_container == null)
                {
                    _container = new UnityContainer();      
                }
            
                _container.RegisterInstance<IEventAggregator>(new EventAggregator());

            }

            protected override object Resolve(Type type)
            {
                return _container.Resolve(type);
            }

     }
    }

    //viewmodel - in MyApp.Hub.Shared project, in a ViewModels folder
    namespace MyApp.Hub.ViewModels
    {
        public class LoginPageViewModel : ViewModel, ILoginPageViewModel
        {

            private readonly IEventAggregator _eventaggregator;


            public LoginPageViewModel(IEventAggregator eventAggregator)
            {

                _eventaggregator = eventAggregator;

            }

        }
    }

    //view - in MyApp.Hub.Shared project, in a Views folder
    <prism:VisualStateAwarePage
        x:Class="MyApp.Hub.Views.LoginPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:MyApp.Hub.Views"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:vm="using:MyApp.Hub.ViewModels"
        xmlns:prism="using:Microsoft.Practices.Prism.StoreApps"
        xmlns:prismmvvm="using:Microsoft.Practices.Prism.Mvvm"
        prismmvvm:ViewModelLocator.AutoWireViewModel="True"
        mc:Ignorable="d"
        d:DataContext="{d:DesignInstance vm:LoginPageViewModel}">

    </prism:VisualStateAwarePage>

    Tuesday, September 09, 2014 7:43 AM
  • Found the problem - in my View I was setting the design time view model and using the following:

    IsDesignTimeCreatable=True

    Removing this, and using

    d:DataContext="{d:DesignInstance vm:MyViewModel}" only, seems to work

    Saturday, September 13, 2014 9:55 AM
  • IsDesignTimeCreatable=False will prevent you from viewing data in the designer.I had the same error you get and the reason was that i had forgotten to override Resolve method in App.xaml.cs.

    So that the ViewModel wasn't able to be correctly instanciated.

    PS: I was using Unity and dependency injection


    "Find a job you love and you’ll never have to work a day in your life" Confucius

    Sunday, October 05, 2014 4:37 PM
  • Hi,

    There is many reason for the error, if you have view models in different assembly then you need to override the  resolve methods.

    protected override Task OnInitializeAsync(IActivatedEventArgs args)
            {         
              
                _container.RegisterInstance<INavigationService>(NavigationService);         
          
                ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver((viewType) =>
                {
                    var viewModelTypeName = string.Format(CultureInfo.InvariantCulture, "ABC.XYZ.MetroApp.UI.Models.ViewModels.{0}ViewModel, ABC.XYZ.MetroApp.UI.Models", viewType.Name);
                    var viewModelType = Type.GetType(viewModelTypeName);

                    return viewModelType;
                });
            
              

                return Task.FromResult<object>(null);
            }

            protected override object Resolve(Type type)
            {        
                return _container.Resolve(type);
            }

    Hope it will solve this issue.

    Monday, May 18, 2015 12:17 PM