Ivan
Ivan

Reputation: 1171

How to connect multiple ViewModels to a single View with Prism's viewlocator?

I use Prism's viewlocator to connect View and ViewModel, and I follow the convention by placing the View inside the view folder and ViewModel inside the viewmodel folder, and also adding suffix viewmodel to the name of the viewmodel class. It all works fine. I was just wondering how to connect multiple viewmodels to a single view?

For example, I have:

View: CustomerView and in XAML I simply use: prism:ViewModelLocator.AutoWireViewModel="True"

ViewVodel: CustomerViewModel

now I want to add CustomerViewModel2, but it is not going to work, because it doesn't match the view's name

Upvotes: 0

Views: 2393

Answers (3)

Kobie Williams
Kobie Williams

Reputation: 460

Setup your viewmodels as partial classes.

Upvotes: 0

dymanoid
dymanoid

Reputation: 15197

As I mentioned in my comment, there's no such possibility to directly connect a single view with multiple (same-level) view models.

You have to split up your view into a master and (several) child views (either logically in XAML or physically by moving child views into separate UserControls).

Here are my suggestions.

  1. Use PRISM regions.

Define a master view that will contain the regions:

<Window>
    <StackPanel Orientation="Vertical">
        <ContentControl prism:RegionManager.RegionName="Region1"/>
        <ContentControl prism:RegionManager.RegionName="Region2"/>
    </StackPanel>
</Window>

Create child views that will be "inserted" (in PRISM's terminology - injected) into your main view:

<UserControl x:Class="UserControl1">
    <Grid/>
</UserControl>

<UserControl x:Class="UserControl2">
    <Grid/>
</UserControl>

And finally you have to register in PRISM your views so they can be instantiated:

// Obtain the region manager over DI
IRegionManager regionManager;
regionManager.RegisterViewWithRegion("Region1", typeof(UserControl1));
regionManager.RegisterViewWithRegion("Region2", typeof(UserControl2));

Each of these child views will have its own view model. You can use the PRISM's view model locator to auto-wire them.

  1. Use data templating.

Your master view:

<Window>
<Window.Resources>
    <DataTemplate DataType="vm:ViewModel1">
        <v:UserControl1/>
    </DataTemplate>
    <DataTemplate DataType="vm:ViewModel2">
        <v:UserControl2/>
    </DataTemplate>
</Window.Resources>
    <ItemsControl ItemsSource="{Binding Items}"/>
</Window>

Add the child view models into the Items collection of your master view model, and WPF will create the views and auto-wire the view models with them for you.

class MasterViewModel : BindableBase
{
    public IEnumerable<BindableBase> Items
    {
        get { return new[] { new ViewModel1(), new ViewModel2() }
    }
}

Of course, you can use DI for instantiating your view models.

  1. Use "stacked" view model.

Something like this:

class MainViewModel : BindableBase
{
    public ViewModel1 ViewModel1 { get; private set; }
    public ViewModel2 ViewModel2 { get; private set; }
}

In your main view, you will have to set up your bindings accordingly.

<Window>
    <StackPanel>
        <TextBlock Text="{Binding ViewModel1.SomeValue}"/>
        <TextBox Text="{Binding ViewModel2.SomeValue}"/>
    </StackPanel>
</Window>

Upvotes: 2

Filip Skakun
Filip Skakun

Reputation: 31724

You could expose child view models as properties of the main view model for the page, then prefix the paths to the child view model in your bindings with the property name.

Upvotes: 1

Related Questions