Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to open a new window using MVVM Light Toolkit

I am using MVVM Light toolkit in my WPF application. I would like to know what is the best approach for opening a new window from an existing window. I have got this MainViewModel, which is responsible for MainWindow of my application. Now in the MainView, on a button click, I would like to open a second window on top of it. I have got RelayCommmand binded to the Button's Command. In the RelayCommand's method, I can create a new window object and simply call Show(), something like this:

var view2 = new view2()
view2.Show()

but I don't think the ViewModel should be responsible for creating the new view2 object. I have read this post WPF MVVM Get Parent from VIEW MODEL where Bugnion has suggested to pass message to the view1 from the viewmodel1 and then view1 should create the new view2. But I am not sure what does he actually mean by passing the message to the view1? How should the view1 handle the message? In it's code behind or what?

Regards, Nabeel

like image 551
nabeelfarid Avatar asked Aug 02 '10 09:08

nabeelfarid


People also ask

What is MVVM toolkit?

Mvvm package (aka MVVM Toolkit) is a modern, fast, and modular MVVM library. It is part of the Windows Community Toolkit and is built around the following principles: Platform and Runtime Independent - . NET Standard 2.0 and . NET 5 🚀 (UI Framework Agnostic)


4 Answers

Passing a message from ViewModel1 to View1 means to use the messaging capabilities in the MVVM Light Toolkit.

For example, your ViewModel1 could have a command called ShowView2Command, then it would send a message to display the view.

public class ViewModel1 : ViewModelBase
{
    public RelayCommand ShowView2Command { private set; get; }

    public ViewModel1() : base()
    {
        ShowView2Command = new RelayCommand(ShowView2CommandExecute);
    }

    public void ShowView2CommandExecute()
    {
        Messenger.Default.Send(new NotificationMessage("ShowView2"));
    }
}

View1 would register to receive messages in its code behind and display View2 when it receives the correct message.

public partial class View1 : UserControl
{
    public View1()
    {
        InitializeComponent();
        Messenger.Default.Register<NotificationMessage>(this, NotificationMessageReceived);
    }

    private void NotificationMessageReceived(NotificationMessage msg)
    {
        if (msg.Notification == "ShowView2")
        {
            var view2 = new view2();
            view2.Show();
        }
    }
}
like image 73
Matt Casto Avatar answered Oct 10 '22 20:10

Matt Casto


Why do you go this route? Its simple. If you replace your button with a toggleButton, or a hyperlink, or any other number of button-like controls, you don't need to update your "code behind" - its a basic principle of the MVVM pattern. In your new toggleButton (or whatever), you still end up binding to the same exact Command.

For example, I'm creating a project for a client who wants to have 2 UI's - one is going to be fundamentally different in every way, in terms of presentation. Horizontal tabs vs Vertical RadPanelBar (think Accordion) for navigation. Both of these views can point to the same viewModel - when a user clicks the Work Order tab in View 1, it fires the same "WorkOrderCommand" that's fired in the Work Order Header in the panel bar.

In a code-behind model, you'd have to code two separate events. Here you only have to code one.

Furthermore, it allows a designer using Blend to create any layout they want. As long as they have the hooks (EventToCommand control) in place, myself (as a developer) couldn't care less what the final product looks like.

Loose coupling is incredibly powerful.

like image 31
Scott Silvi Avatar answered Oct 10 '22 21:10

Scott Silvi


You can do in this way like you need to create some events and register those in view and call these in view model.and open that pop up window.

Like This example

public class Mainclass : MainView
{
    public delegate abc RegisterPopUp(abc A);
    public RegisterPopUp POpUpEvent ;

    public RelayCommand ShowCommand { private set; get; }  


    public void ShowCommand() 
    { 
        ShowCommand("Your parameter");
    } 
}

inside the view MainView mn=new MainView();

Register the event here like thake mn.POpUpEvent += than click on tab button double time

and in registers popup method right the code for opening the pop up window.

like image 36
Hoshiyar Avatar answered Oct 10 '22 22:10

Hoshiyar


Unless I am missing the point here - if I were to use the code behind, then why not directly implement button_click event and open the second view?

What Bugnion seems to be suggesting is view1 -> button click -> relay command -> viewmodel1 -> message -> view1 -> view1.cs -> open view 2.

You are going to sacrifice testability anyhow by writing code-behind, so why take such a long route?

like image 31
Pratz Avatar answered Oct 10 '22 20:10

Pratz