Opening new window in MVVM WPF

wpf popup window mvvm
wpf prism open new window
wpf open new window on button click
mvvm light open new window
mvvm open dialog from viewmodel
wpf mvvm
sample mvvm application in wpf
wpf mvvm example application with database

I have Button and I have bind this button to command in ViewModel say OpenWindowCommand. When I click on button I want to open new window. But creating window instance and showing window from view model is violation of MVVM. I have created interface like

interface IWindowService
{
    void showWindow(object dataContext);
}

and WindowService implements this interface like

class WindowService : IWindowService
{
    public void showWindow(object dataContext)
    {
        ChildWindow window=new ChildWindow();
        window.DataContext=dataContext;
        window.Show();
    }
}

In this class I have specified ChildWindow. So this class is tightly coupled with showing ChildWindow. When I want to show another window, I have to implement another class with same interface and logic. How can I make this class generic so that I can pass just instance of any window and class will be able to open any window?

I am not using any built MVVM frameworks. I have read many articles on StackOverflow but I could not found any solution for this.

You say "creating window instance and showing window from view model is violation of MVVM". This is correct.

You are now trying to create an interface that takes a type of view specified by the VM. This is just as much of a violation. You may have abstracted away the creation logic behind an interface, but you are still requesting view creations from within the VM.

VM's should only care about creating VM's. If you really need a new window to host the new VM, then provide an interface as you have done, but one that does NOT take a view. Why do you need the view? Most (VM first) MVVM projects use implicit datatemplates to associate a view with a particular VM. The VM knows nothing about them.

Like this:

class WindowService:IWindowService
{
    public void ShowWindow(object viewModel)
    {
        var win = new Window();
        win.Content = viewModel;
        win.Show();
    }
}

Obviously you need to make sure you have your VM->View implicit templates set up in app.xaml for this to work. This is just standard VM first MVVM.

eg:

<Application x:Class="My.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:vm="clr-namespace:My.App.ViewModels"
             xmlns:vw="clr-namespace:My.App.Views"
             StartupUri="MainWindow.xaml">
    <Application.Resources>

        <DataTemplate DataType="{x:Type vm:MyVM}">
            <vw:MyView/>
        </DataTemplate>

    </Application.Resources>
</Application>

Opening new window in MVVM WPF, You say "creating window instance and showing window from view model is violation of MVVM". This is correct. You are now trying to create an  You say “creating window instance and showing window from view model is violation of MVVM”. This is correct. You are now trying to create an interface that takes a type of view specified by the VM. This is just as much of a violation. You may have abstracted away the creation logic behind an interface,

One possibility is to have this:

class WindowService:IWindowService
{
 public void showWindow<T>(object DataContext) where T: Window, new() 
 {
  ChildWindow window=new T();
  window.Datacontext=DataContext;
  window.show();
 }
}

Then you can just go something like:

windowService.showWindow<Window3>(windowThreeDataContext);

For more information on the new constraint, see http://msdn.microsoft.com/en-gb/library/sd2w2ew5.aspx

Note: the new() constraint only works where the window will have a parameterless constructor (but I imagine this shouldn't be a problem in this case!) In a more general situation, see Create instance of generic type? for possibilities.

Opening a New Window on a Button click - MVVM WPF, Opening a New Window on a Button click - MVVM WPF. I am new to MVVM architecture, and I would like to keep the standard of MVVM without  mvvm open new window (5) 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 could write a function like this:

class ViewManager
{
    void ShowView<T>(ViewModelBase viewModel)
        where T : ViewBase, new()
    {
        T view = new T();
        view.DataContext = viewModel;
        view.Show(); // or something similar
    }
}

abstract class ViewModelBase
{
    public void ShowView(string viewName, object viewModel)
    {
        MessageBus.Post(
            new Message 
            {
                Action = "ShowView",
                ViewName = viewName,
                ViewModel = viewModel 
            });
    }
}

Make sure the ViewBase has a DataContext property. (You could inherit UserControl)

In general I would make some kind of message bus and have a ViewManager listen for messages asking for a view. ViewModels would send a message asking for a view to be shown and the data to show. The ViewManager would then use the code above.

To prevent the calling ViewModel to know about the View types you could pass a string/logical name of the view to the ViewManager and have the ViewManager translate the logical name into a type.

how to write a mvvm command to display a new window on a button , Here, have a look at these: A Simple MVVM Example[^] WPF MVVM - How to Show a view from MainWindowViewModel upon Clicking on  In this article, we will demonstrate how to open a child window via the button click event in WPF with MVVM pattern using prism library. If you are new to MVVM pattern using Prism Library then you can follow my very first article to start the MVVM and add the dlls into the project from the below link, Now I will show you a demo to show a popup

use a contentpresenter in your Window where you bind your DataConext to. And then define a Datatemplate for your DataContext so wpf can render your DataContext. something similar to my DialogWindow Service

so all you need is your one ChildWindow with a ContentPresenter:

<Window x:Class="ChildWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
WindowStartupLocation="CenterOwner" SizeToContent="WidthAndHeight">
<ContentPresenter Content="{Binding .}">

</ContentPresenter>
</Window>

[PDF] Open A Child Window From View Model In MVVM In WPF, Open A Child Window From View Model In MVVM In WPF. Using Visual Studio 2013 and ShowCommand = new DelegateCommand(ShowMethod);. 17. } 18. Some MVVM frameworks (e.g. MVVM Light) make use of the Mediator pattern. So to open a new Window (or create any View) some View-specific code will subscribe to messages from the mediator and the ViewModel will send those messages.

I find the accepted solution very useful, but when trying it practically, I found that it lacks the ability to make the UserControl (the View that results from the VM -> View mapping) dock within the hosting window in order to occupy the whole area provided by it. So I extended the solution to include this ability:

public Window CreateWindowHostingViewModel(object viewModel, bool sizeToContent)
{
   ContentControl contentUI = new ContentControl();
   contentUI.Content = viewModel;
   DockPanel dockPanel = new DockPanel();
   dockPanel.Children.Add(contentUI);
   Window hostWindow = new Window();
   hostWindow.Content = dockPanel;

   if (sizeToContent)
       hostWindow.SizeToContent = SizeToContent.WidthAndHeight;

   return hostWindow;
}

The trick here is using a DockPanel to host the view converted from the VM.

Then you use the previous method as follows, if you want the size of the window to match the size of its contents:

var win = CreateWindowHostingViewModel(true, viewModel)
win.Title = "Window Title";
win.Show();

or as follows if you have a fixed size for the window:

var win = CreateWindowHostingViewModel(false, viewModel)
win.Title = "Window Title";
win.Width = 500;
win.Height = 300;
win.Show();

Open new window from another window in WPF - Part - 10, In this tutorial you will learn to open a new window from another window in WPF. Also you Duration: 4:30 Posted: Jul 12, 2016 Opening new window in MVVM WPF (4) . I find the accepted solution very useful, but when trying it practically, I found that it lacks the ability to make the UserControl (the View that results from the VM -> View mapping) dock within the hosting window in order to occupy the whole area provided by it.

Open a new WPF windows using MVVM, Hi,I develope a new WPF application using MVVM. I added a new button on the parent window in order to open a new window (child).The child  I have a Button and I bind this button to a command in ViewModel say OpenWindowCommand.When I click on the button I want to open a new window. But creating a window instance and showing a window from view model is a violation of MVVM.

Opening new window in MVVM WPF, When I click on button I want to open new window. But creating window instance and showing window from view model is violation of MVVM. Opening a New Window on a Button click - MVVM WPF I am new to MVVM architecture, and I would like to keep the standard of MVVM without violating its rules. So I implemented an approach to open a new window on a button click using Services.

In MVVM, should ViewModel or View be responsible for creating , It could also open a view based on another view model with this. (there are actually several for WinForms, simple Wpf Windows, a Wpf shell with tabs,. As such, creating a new window is a job for the ViewModel . However  I am new to MVVM architecture, and I would like to keep the standard of MVVM without violating its rules. So I implemented an approach to open a new window on a button click using Services. I don't know if this is the right approach to do so. Here is my code, Inside the service folder, I have two files. IwindowService and WindowNavService.

Comments
  • I've found an alternative way of opening windows in MVVM, using a behavior instead of a service.
  • Why do you need different Window types? The window is just a container for the view. Just use a generic window and use implicit DataTemplates as normal for mapping VM->View
  • One of the reasons the VM knows nothing about the View is because you can have multiple Views to display the data in the ViewModel in different ways. This method makes your views and viewmodels have a 1:1 mapping.
  • This solution will not working if MyView is a Window. It will throw an error of 'Can't put window in style'
  • I hope vw:MyView should be of type UserControl and not of type Window
  • @Ehsan Wherever your view (ie xaml) is defined.
  • windowService.showWindow<Window3>(windowThreeDataContext); this statement is in viewmodel and it contains name of view.Doesn't it violet the MVVM approach?
  • Indeed - sorry, I was taking the question How can I make this class generic so that I can pass just instance of any window and class will be able to open any window? a little too strongly, and didn't properly discuss the root issue! Somewhere in an MVVM approach you will need to make windows/views, so the above can be useful - potentially you either have a mapping from ViewModel to View, or some form of convention (eg \ViewModels\MyViewModel.cs -> \Views\MyView.cs), but it's up to you :)
  • Personally, I'd advocate using a framework if you want to go for a hardcore MVVM approach, which usually wraps all this up for you :). I've used Caliburn Micro which I really like, but it's up to you ^^
  • I may be wrong, but I'm fairly sure you need the where T: ViewBase, new() in order to create a new object of generic type in your function? a la: msdn.microsoft.com/en-gb/library/sd2w2ew5.aspx
  • It was a case of simultaneous answering - yours wasn't there when I wrote mine, then I refreshed to find you had beaten me to it! Apologies Erno :)
  • @DavidEdey - :) np it is not a race
  • @ErnodeWeerd In your case I will still need to refer view from viewmodel. I don't have to create instance there but at least I have to refer to View.So doesn't it violet MVVM?
  • @DTsawant - no you don't. Read the last bit of my answer.