2
votes

Im trying to use MVVM on a PRISM Module. I have a ViewModel in my module with a parameterized constructor which accepts an IOutputService object which will be injected using Ninject.

namespace HelloWorld.ViewModels
{
    public class HelloWorldViewModel : ViewModelBase
    {
        private IOutputService outputService;

        public HelloWorldViewModel(IOutputService outputService)
        {
            this.outputService = outputService;
        }
    }
}

In the HelloWorldModule.cs file, I register IOutputService with a class that implements it.

public class HelloWorldModule : IModule
{
    private IKernel kernel;
    private IRegionManager regionManager;

    public HelloWorldModule(IKernel kernel, IRegionManager regionManager)
    {
        this.kernel = kernel;
        this.regionManager = regionManager;
    }

    public void Initialize()
    {
        kernel.Bind<IOutputService>().To<MessageBoxOutputService>();
        regionManager.RegisterViewWithRegion("Region1", typeof(HelloWorldView));
    }
}

You can also notice that I am registering the HelloWorldView to Region1. HelloWorldView uses HelloWorldViewModel. The problem now is I can't initialize the HelloWorldViewModel in XAML of View because my ViewModel doesn't have a parameterless constructor.

<UserControl x:Class="HelloWorld.Views.HelloWorldView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:vm="clr-namespace:HelloWorld.ViewModels"
             mc:Ignorable="d">
    <UserControl.DataContext>
        <vm:HelloWorldViewModel />
    </UserControl.DataContext>
    <Grid>

    </Grid>
</UserControl>

When I run this, the InitializeComponent() method of the View throws an NullReferenceException. Any proper way to make this work? Thanks.

3

3 Answers

0
votes

In the codebehind of the view, inject the viewmodel in the constructor.

public partial class HelloWorldView : UserControl
{
    public HelloWorldView(HelloWorldViewModel vm)
    {
        InitializeComponent();
        DataContext = vm;
    }
 }
0
votes

Well You don't have to set View's DataContext in xaml. It can be simply done in CodeBehind. Add following property to HelloWorldView.xaml.cs

    /// <summary>
    /// Gets or sets ViewModel.
    /// </summary>
    [Inject]
    public HelloWorldViewModel ViewModel
    {
        get { return this.DataContext as HelloWorldViewModel; }
        set { this.DataContext = value; }
    }

When you call RegisterViewWithRegion an instance of that view will be resolved and thanks to InjectAttribute Ninject will provide that View with DataContext. So you don't need to worry about that. Constructor injection should work as well.

-1
votes

Try using ObjectDataProvider.

Example (From MSDN):

<ObjectDataProvider x:Key="myDataSource" ObjectType="{x:Type src:Person}">
  <ObjectDataProvider.ConstructorParameters>
    <system:String>Joe</system:String>
  </ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>

Here is a good example by Bea Stollnitz:

Why should I use ObjectDataProvider?