Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVVM Light ViewModelLocator

I am using MVVM Light in my application, with multiple assemblies in the solution. How can I have a ViewModelLocator in each assembly without defining in App.xaml resources?

Typically ViewModelLocator is defined like this:

<Application.Resources>
  <ResourceDictionary>
   <ResourceDictionary.MergedDictionaries>
     <ResourceDictionary Source="/Sol1;component/GlobalResources.xaml" />
   </ResourceDictionary.MergedDictionaries>
   <viewModels:ViewModelLocator xmlns:main="clr-namespace:MainModule.ViewModel;assembly=MainModule" x:Key="Locator" d:IsDataSource="True"/> 
</ResourceDictionary>

I created a Resources.xaml in a class library within my solution like this:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:ModuleX="clr-namespace:ModuleX">
<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="/Common;component/CommonResources.xaml" />
</ResourceDictionary.MergedDictionaries>
<ModuleX:ViewMoldelLocator x:Key="ModuleXLocator" />
</ResourceDictionary>

However, ModuleXLocator is not found:

<phone:PhoneApplicationPage
       ...
       DataContext="{Binding Main, Source={StaticResource ModuleXLocator}}">
like image 375
rdon Avatar asked Jul 08 '14 20:07

rdon


1 Answers

I'm not 100% if I'm answering your question but I'll answer a similar problem I had and its the solution. Hopefully its what you're looking for.

Problem:

You've designed a wonderful little MVVMLight application (LittleApp) and now you want to use it as a UserControl/Page/Window in another project (BigApp). The problem is LittleApp has its ViewModelLocator defined in its corresponding App.xaml which is not used for BigApp. The result is LittleApp looks for its ViewModelLocator in "BigApp's App.xaml" and fails.

You also want to keep LittleApp working as a stand alone project and so don't want to mess with its design.

Gives Possible Exceptions:

XMLParseException: The ViewModelLocator defined in LittleApp's root node can't be found (because its defined in an unused App.xaml)

WPFError 40: You've used the MVVMLight tool to create both apps and thus both Apps have an App.xaml with a ViewModelLocator called 'Locator' pointing to a ViewModel called 'Main'. LittleApp will be able to resolve this but it will point to the wrong MainViewModel and thus have property conflicts.

Solution:

You need to define LittleApp's ViewModelLocator as a resource in the root node of LittleApp's MainView. So if your MainView is a UserControl called LittleApp/View/MainView.xaml it will look something like this.

<UserControl x:Class="LittleApp.View.MainView"
         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:vm="clr-namespace:LittleApp.ViewModel"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">

    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="../Skins/MainSkin.xaml" />
            </ResourceDictionary.MergedDictionaries>
            <vm:ViewModelLocator x:Key="Locator"/>
        </ResourceDictionary>
    </UserControl.Resources>

    <UserControl.DataContext>
        <Binding Source="{StaticResource Locator}"/>
    </UserControl.DataContext>

    <Grid>
       .
       .  Your Control Design
       .
       .
       .
    </Grid>
</UserControl>

Now BigApp just needs to reference LittleApps assembly and add it as a namespace in the root node of the control you want to add it to. Something like this.

<Page x:Class="BigApp.View.Page1"
      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:LittleView="clr-namespace:LittleApp.View;assembly=LittleApp"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300">

    <Grid>
        <LittleView:MainView/>
    </Grid>
</Page>
like image 80
Josh C Avatar answered Sep 22 '22 15:09

Josh C