Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Open a new Window in MVVM

Tags:

c#

mvvm

Lets say I have a MainWindow and a MainViewModel, I'm not using MVVM Light or Prism in this example.
In this MainWindow I want to click a MenuItem or Button to open a NewWindow.xaml not a UserControl.
I know how to use this with UserControl to open a new UserControl in my existing Window in a ContrntControl or a Frame.

<ContentControl Content="{Binding Path=DisplayUserControl,UpdateSourceTrigger=PropertyChanged}" />

Code

public ViewModelBase DisplayUserControl
{
    get
    {
        if (displayUserControl == null)
        {
            displayUserControl = new ViewModels.UC1iewModel();
        }
        return displayUserControl;
    }
    set
    {
        if (displayUserControl == value)
        {
            return;
        }
        else
        {
            displayUserControl = value;
            OnPropertyChanged("DisplayUserControl");
        }
    }
}

In the ResourceDitionary for MainWindow I have :

<DataTemplate DataType="{x:Type localViewModels:UC1ViewModel}">
    <localViews:UC1 />
</DataTemplate>
<DataTemplate DataType="{x:Type localViewModels:UC2ViewModel}">
    <localViews:UC2 />
</DataTemplate>

The thing is that I want to open a new Window, not a UserControl. So I use some code like this :

private ICommand openNewWindow;

public ICommand OpenNewWindow
{
    get { return openNewWindow; }
}

public void DoOpenNewWindow()
{
    View.NewWindowWindow validationWindow = new View.NewWindow();
    NewWindowViewModel newWindowViewModel = new NewWindowViewModel();
    newWindow.DataContext = ewWindowViewModel;
    newWindow.Show();
}

and then a bind OpenNewWindow to a MenuItem or Button.
I know this is not the right way, but what is the right way to do this ?

Thanks!

like image 315
xargs Avatar asked May 20 '13 15:05

xargs


People also ask

How do I close windows MVVM?

<local:ViewModel/> </Window. DataContext> <StackPanel>

How do I start MVVM project?

MVVM – First Application Step 1 − Create a new WPF Application project MVVMDemo. Step 2 − Add the three folders (Model, ViewModel, and Views) into your project. Step 4 − Add another StudentViewModel class into ViewModel folder and paste the following code.

What is MVVM command?

Commands are an implementation of the ICommand interface that is part of the . NET Framework. This interface is used a lot in MVVM applications, but it is useful not only in XAML-based apps.


1 Answers

There are two problems you need to solve with this type of application.

Firstly, you do not want to have the View-Model creating and displaying UI components directly. One of the motivations for using MVVM is to introduce test-ability in to your View-Model, and having this class pop up new windows makes this class harder to test.

The second problem you need to solve is how to resolve the dependencies in your application, or in this instance – how to you “hook up” the View-Model to the corresponding View? A maintainable solution to this latter problem is given by the use of a DI container. A very good reference to this subject is given by Mark Seemann’s Dependency Injection in .NET. He actually also discusses how to solve the first problem too!

To solve the former problem, you need to introduce a layer of indirection to your code, to make the View-Model not dependent on a concrete implementation of creating a new window. A very simple example is given in the code below:

public class ViewModel
{
    private readonly IWindowFactory m_windowFactory;
    private ICommand m_openNewWindow;

    public ViewModel(IWindowFactory windowFactory)
    {
        m_windowFactory = windowFactory;

        /**
         * Would need to assign value to m_openNewWindow here, and associate the DoOpenWindow method
         * to the execution of the command.
         * */
        m_openNewWindow = null;  
    }

    public void DoOpenNewWindow()
    {
        m_windowFactory.CreateNewWindow();
    }

    public ICommand OpenNewWindow { get { return m_openNewWindow; } }
}

public interface IWindowFactory
{
    void CreateNewWindow();
}

public class ProductionWindowFactory: IWindowFactory
{

    #region Implementation of INewWindowFactory

    public void CreateNewWindow()
    {
       NewWindow window = new NewWindow
           {
               DataContext = new NewWindowViewModel()
           };
       window.Show();
    }

    #endregion
}

Note that you take an implementation of IWindowFactory in the constructor of your View-Model, and it is to this object that the creation of the new window is delegated to. This allows you to substitute the production implementation for a different one during testing.

like image 132
Lawrence Avatar answered Oct 12 '22 23:10

Lawrence