Prism and MVVM Light Toolkit

2.5k views Asked by At

I'm trying to put Prism (just for CompositeUI) and MVVM Light Toolkit (for MVVM architecture =D) working together, but I'm getting some troubles with the Light ViewModelLocator. When we use the locator into a "simple" WPF application, we can use an application resource on App.xaml, like this:

<Application.Resources>
    <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
</Application.Resources>

But when we are using Prism, our business code is inside the Module project, and it doesn't have an App.xaml, then I tried to put that resource inside the View resources:

<Window.Resources>
    <ResourceDictionary>
        <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
    </ResourceDictionary>
</Window.Resources>

It just turned off my Design mode (and also runtime) errors, but the View doesn't appear in the region assigned to it.

Somebody already tried to do something like this? Is it possible to put Prism and MVVM Light working together?

This is my "full" code:

(ViewLight.xaml)

<Window x:Class="TryERP2.Financeiro.View.ViewLight"
    ... a lot of NS ...
    mc:Ignorable="d"
    xmlns:vm="clr-namespace:TryERP2.Financeiro.ViewModel"
    d:DesignHeight="150" d:DesignWidth="245" SizeToContent="WidthAndHeight">
    <Window.Resources>
        <ResourceDictionary>
            <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
        </ResourceDictionary>
    </Window.Resources>

    <Grid DataContext="{Binding Light, Source={StaticResource Locator}}">
        <Button Content="{Binding MyButtonText}" HorizontalAlignment="Stretch" Name="button1" VerticalAlignment="Stretch" />
    </Grid>
</Window>

ViewLightModel.cs:

public class ViewLightModel : ViewModelBase
{
    public ViewLightModel()
    { }

    public const string MyButtonTextPropertyName = "MyButtonText";
    private string _myButtonText = "Button Text";

    public string MyButtonText
    {
        get
        { return _myButtonText; }

        set
        {
            if (_myButtonText == value)
            { return; }

            _myButtonText = value;
            RaisePropertyChanged(MyButtonTextPropertyName);
        }
    }
}

Financeiro.cs (The module initializer class ... Partially shown ... Just where I register and "invoke" the views):

        var container = ServiceLocator.Current.GetInstance<IUnityContainer>();
        container.RegisterType<Object, ViewLight>("ViewLight");

        var regionManager = ServiceLocator.Current.GetInstance<IRegionManager>();
        var main = new Uri("ViewLight", UriKind.Relative);
        regionManager.RequestNavigate("Desktop", main);

A "normal" MVVM Light Application has an App.xaml file, that (I think) isn't used in Prism modules Views. That file has this structure:

<Application x:Class="TryERP2.Financeiro.App"
         ... a lot of NS ...
         xmlns:vm="clr-namespace:TryERP2.Financeiro.ViewModel"
         StartupUri="MainWindow.xaml"
         mc:Ignorable="d">

    <Application.Resources>
        <vm:ViewModelLocator x:Key="Locator"
                             d:IsDataSource="True" />
    </Application.Resources>

</Application>

That's what happen when I execute my application. The View that was on the module should be loaded into this blank space, showing its Button, but nothing happened:

http://imageshack.us/photo/my-images/818/capturarwy.png

When I try to change this view and put in its place a "simple view" (not using MVVMLight) it works perfectly, like shown in the picture below:

http://imageshack.us/photo/my-images/513/capturar1a.png

2

There are 2 answers

0
Diego Stiehl On BEST ANSWER

I'm sorry. I made a big mistake. As you may have noticed, I'm building a Ribbon Application, and I'm trying to show the controls under a blank Region. The items that can be displayed there are Controls. It wasn't working because I was trying to display a Window:

<Window x:Class="TryERP2.Financeiro.View.ViewLight"
... a lot of NS ...
mc:Ignorable="d"
xmlns:vm="clr-namespace:TryERP2.Financeiro.ViewModel"
d:DesignHeight="150" d:DesignWidth="245" SizeToContent="WidthAndHeight">
... etc

I fixed it by changing it to an User Control instead a Window, and it worked perfectly.

My new ViewLight.xaml:

<UserControl x:Class="TryERP2.Financeiro.View.ViewLight"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        xmlns:vm="clr-namespace:TryERP2.Financeiro.ViewModel"

        d:DesignHeight="150" d:DesignWidth="245">
    <UserControl.Resources>
        <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
    </UserControl.Resources>

    <Grid DataContext="{Binding Light, Source={StaticResource Locator}}">
        <Button Content="{Binding MyButtonText}" HorizontalAlignment="Stretch" Name="button1" VerticalAlignment="Stretch" />
    </Grid>
</UserControl>

My new ViewLight.xaml.cs (Code-behind):

public partial class ViewLight : UserControl
{
    public ViewLight()
    {
        InitializeComponent();
    }
}

And the ViewModel is still the same.

8
Peter Porfy On

In ViewLight.xaml you should change

<Window.Resources>
    <ResourceDictionary>
        <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
    </ResourceDictionary>
</Window.Resources>

to

<Window.Resources>
        <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
</Window.Resources>

Because Window.Resources is already a ResourceDictionary, and you create an another in it. You cannot access Locator resource here:

<Grid DataContext="{Binding Light, Source={StaticResource Locator}}">

Another option is to use MergedDictionary.