wpfunity-container

Setting UserControl ViewModel Property


All -

I am using Unity in my WPF application for DI (without prism). I have my MainWindow.xaml and MainWindowViewModel.cs. I have a usercontrol in my Mainwindow.xaml. The user control has its own uc1.xaml and uc1viewmodel.cs. The UC1 ViewModel is currently exposed as a property on MainWindowViewModel so I can set the datacontext on the usercontrol (as recommended by many ppl here).

The question I have is how/where can I set this property - will it be in app.xaml.cs or will it be in the constructor of mainwindowviewmodel. Code Snippets:

App.xaml.cs

protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        //Step 1 - One Time - Creating an instance of the container
        UnityContainer unity = new UnityContainer();

        //Step 2 - Registering your MainWindowViewModel
        unity.RegisterType<IViewModel, UserControl1ViewModel>();

        //Step 3 - Creating an Instance
        UserControl1ViewModel uc1_mwvm = unity.Resolve<UserControl1ViewModel>();  <-- doesnt help
        MainWindowViewModel mwvm = unity.Resolve<MainWindowViewModel>();

        MainWindow mw = unity.Resolve<MainWindow>();

        mw.Show();
    }

MainWindowViewModel.cs

public class MainWindowViewModel
{
    public IViewModel IVM { get; set; }

    public MainWindowViewModel()
    {
        //IVM = new UserControl1ViewModel(); <-- All I really want is an equivalent but letting Unity do the work. 
    }
}

MainWindow.xaml

<Window x:Class="_05_ViewFist_UC_Unity_Working.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:uc1="clr-namespace:_05_ViewFist_UC_Unity_Working"
     xmlns:uc2="clr-namespace:_05_ViewFist_UC_Unity_Working"
    Title="MainWindow" Height="350" Width="525">
<StackPanel Orientation="Vertical">
    <TextBlock Text="{Binding NNN}" />
    <uc1:UC1 DataContext="{Binding UC1VM}" />
    <uc2:UC2 DataContext="{Binding UC2VM}" />
</StackPanel>
</Window>

UC1

<UserControl x:Class="_05_ViewFist_UC_Unity_Working.UC1"
         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" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300" >
<StackPanel Orientation="Horizontal" Background="Red">
    <TextBlock Text="UC1 "  />
    <TextBlock Text="{Binding FirstName}"  />
</StackPanel>
</UserControl>

As you see from the code - Instance of UC1 is created in xaml (MainWindow.xaml) and hence when MainWindow instance is created in app.xaml.cs - it still doesnt create an instance of UserControl1ViewModel.

Question again is : Dont think its a good practice for me to call the Unity Resolve statement in the constructor of MainwindowViewModel. Is that correct??

Can somebody share a code snippet of how/where I can do this?

Thanks


Solution

  • I downloaded your solution from github and tried to solve your problem.

    You did a great job just you forgot few details such as property attributes.

    This is how your App.cs file shall look alike:

        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
    
            //Step 1 - One Time - Creating an instance of the container
            UnityContainer unity = new UnityContainer();
    
            //Step 2 - Registeration
            unity.RegisterType<IMainWindowViewModel, MainWindowViewModel>();
            unity.RegisterType<IUC1ViewModel, UC1ViewModel>();
            unity.RegisterType<IUC2ViewModel, UC2ViewModel>();
    
    
            //// Instance of MainWindowViewModel will be created once you call Resolve MainWindow.
    
    
            MainWindow mw = unity.Resolve<MainWindow>();
    
            mw.Show();
        }
    

    Here is what I changed:

    public class MainWindowViewModel : IMainWindowViewModel
    {
        #region Public Properties
    
        [Dependency]
        public IUC1ViewModel UC1VM { get; set; }
    
        [Dependency]
        public IUC2ViewModel UC2VM { get; set; }
    
        public string NNN { get; set; }
    
        #endregion
    
        public MainWindowViewModel()
        {
            NNN = "This value coming from MainWindowViewModel";
        }
    }
    

    [Dependency] is a property attibute that tells Unity where to inject values.

    I could merge my code to your repo in github if you wish so.