在 MVVM 中打开一个新窗口 [英] Open a new Window in MVVM
问题描述
假设我有一个 MainWindow
和一个 MainViewModel
,我没有使用 MVVM Light 或 Prism在这个例子中.
在这个 MainWindow
我想点击一个 MenuItem
或 Button
来打开一个 NewWindow.xaml
而不是 用户控件
.
我知道如何将它与 UserControl
一起使用,在 ContrntControl
或 Frame
的现有窗口中打开一个新的 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");
}
}
}
在 MainWindow
的 ResourceDitionary
中,我有:
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
绑定到 MenuItem
或 Button
.
我知道这不是正确的方法,但正确的方法是什么?
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屋!