在 MVVM 中打开一个新窗口 [英] Open a new Window in MVVM

查看:39
本文介绍了在 MVVM 中打开一个新窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个 MainWindow 和一个 MainViewModel,我没有使用 MVVM LightPrism在这个例子中.
在这个 MainWindow 我想点击一个 MenuItemButton 来打开一个 NewWindow.xaml 而不是 用户控件.
我知道如何将它与 UserControl 一起使用,在 ContrntControlFrame 的现有窗口中打开一个新的 UserControl>.

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}" />

代码

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

MainWindowResourceDitionary 中,我有:

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>

问题是我想打开一个新的Window,而不是一个UserControl.所以我使用了一些这样的代码:

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();
}

然后将 OpenNewWindow 绑定到 MenuItemButton.
我知道这不是正确的方法,但正确的方法是什么?

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 ?

谢谢!

推荐答案

使用此类应用程序需要解决两个问题.

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

首先,您不想让 View-Model 直接创建和显示 UI 组件.使用 MVVM 的动机之一是将可测试性引入到您的视图模型中,并且让此类弹出新窗口会使此类更难测试.

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.

你需要解决的第二个问题是如何解决你的应用程序中的依赖关系,或者在这种情况下——你如何将View-Modelhook"到对应的View上?后一个问题的可维护解决方案是通过使用 DI 容器提供的.Mark Seemann 的 .NET 中的依赖注入 对这个主题给出了很好的参考.他其实也讨论了如何解决第一个问题!

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!

为了解决前一个问题,你需要在你的代码中引入一个间接层,使View-Model不依赖于创建一个新窗口的具体实现.下面的代码给出了一个非常简单的例子:

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
}

请注意,您在视图模型的构造函数中采用了 IWindowFactory 的实现,并且新窗口的创建委托给该对象.这允许您在测试期间将生产实现替换为不同的实现.

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.

这篇关于在 MVVM 中打开一个新窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆