简体   繁体   中英

MVVM Light - Multiple ViewModels (and connecting them up)

I am trying to learn the MVVM pattern (C#), having come from a Windows Forms background. I am using the MVVM Light toolkit, and so far I think it is brilliant. I have made several small applications, however one thing I am struggling with is introducing a second view.

I want to (for example), have a button on my MainViewModel, which via a RelayCommand, opens up a new Window - let's say an "About" window. I have done hours of research on the web for this however it seems I can't get my AboutViewModel to communicate with/show my AboutView.

I have placed a receiving messenger in the code-behind constructor of the AboutView.xaml - however I can't get it to receive any messages from the AboutViewModel, and thus can't make it 'Show()'.

If anyone has an example of an Mvvm Light WPF app using multiple views that would be great :)

There are two ways I can think to do this easily

The first would be to use a Popup instead of a new Window . For example, I often put properties in my ViewModel for PopupContent and IsPopupVisible , and set those values anytime I want to display my Popup control. For example, a ShowAboutPopup relay command might run something like this:

void ShowAboutPopup()
{
    PopupContent = new AboutViewModel();
    IsPopupVisible = true;
}

You can display it using a Popup object, or a custom UserControl . I prefer to use my own custom Popup UserControl , which will usually end up looking like this:

<Window>
    <Canvas x:Name="RootPanel">
        <SomePanel>
            <!-- Regular content goes here -->
        </SomePanel>

        <local:PopupPanel Content="{Binding PopupContent}"
            local:PopupPanel.IsPopupVisible="{Binding IsPopupVisible}"
            local:PopupPanel.PopupParent="{Binding ElementName=RootPanel}" />
    </Canvas>
</Window>

The PopupContent property is a ViewModel (such as an AboutViewModel ), and DataTemplates are used to tell WPF to draw specific ViewModels with specific Views

<Window.Resources>
    <DataTemplate DataType="{x:Type local:AboutViewModel}">
        <local:AboutView />
    </DataTemplate>
</Window.Resources>

The other method is to have some kind of ApplicationViewModel that runs on startup, and is responsible for the overall application state, which includes which window(s) are open.

Typically I prefer to have a single ApplicationView that contains a ContentControl to display the current page

<Window>
    <ContentControl Content="{Binding CurrentViewModel}" />
</Window>

however it can also be used to manage multiple windows. If you do use it to manage multiple Window objects, be warned that this will not be a pure ViewModel because it will need to access some View-specific objects, and referencing UI objects it not something a ViewModel should do. For example, it may subscribe to receive ShowWindow messages, and upon receiving those messages it would create the specified View and show it, and possibly hide the current window as well.

Personally, I try to avoid multiple windows as much as possible. My usual method is to have a single View that contains consistent application objects for any page, and a ContentControl containing dynamic content that changes. I have an example using this navigation style on my blog if you're interested

As i can see you want a navigation in your MVVM app?

Word goes to the creator of MVVM Light - Laurent Bugnion - with his post about using Navigation Service for switching Views . It's actually about Windows Phone & Silverlight but same should apply to WPF .

Also this answer in related question uses this approach.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM