在 MVVM 和松散耦合之后从 MainWindow 打开第二个 Window

Opening a second Window from MainWindow following MVVM and loose coupling

起初:这个应用程序和问题是为了学习目的

我正在使用一个新应用程序并面临这样的问题,即当用户单击 MainView 中的按钮时我想打开一个 Window。在过去,我会设计一个命令来创建新的 Window 并显示它

new RelayCommand((x)=>new SecondWindow().Show());

现在,通过这个新项目,我正试图将所有 类 彼此完全分离。为此,我的应用程序包含 4 个程序集(BL、COM、DAL 和 UI)。 与在每个 WPF 应用程序中一样,应用程序以 MainWindow.xaml 开头。 MainWindow.cs 将创建 MainWindowViewModel:

的实例
public ViewModel VM {get; private set;}
public class MainWindow(){
    VM = new ViewModel();
    InitializeComponent();
}

(已经违反了松散耦合)(关于如何让它变得更好的任何提示?)

我最后一次尝试是在主 window

中创建第二个 Window 的实例
<Window.Resources>
    <local:SecondWindow x:Key="sw"/>
</Window.Resources>

并将其作为命令参数传递给我的命令

CommandParameter="{StaticResource sw}"/>

new RelayCommand((x)=> ((Window)x).Show());

此解决方案有效但有一个很大的缺点 - 第二个 window get 是在应用程序启动后立即创建的 - ViewModel 也是如此,它启动一些繁重的进程(数据库连接等)

我听说过一些关于 IoC 原则的事情,但我真的不知道如何将它用于 wpf 应用程序。

您的思路是正确的....您基本上必须在应用程序启动时创建一个 ViewModel 列表,然后您可以在用户按下按钮时在它们之间切换并将 ViewModel 的名称传递为您的命令处理程序的 CommandParameter....

您可能会在 Rachel Lim 的博客link 中找到这个

https://rachel53461.wordpress.com/2011/12/18/navigation-with-mvvm-2/

此外,我不打算 post 此处的任何代码,因为它太复杂了。所以这里是我能想到的最简单示例的下载

http://www.mediafire.com/download/3bubiq7s6xw7i73/Navigation1.rar

下载并解压缩它(使用 win RAR)您将需要单步执行代码,弄清楚它在做什么以及它是如何做的然后修改它以满足您的需要...或者修改您的需要以适合代码.....

该示例是 Rachel Lim 示例的修改版。它只包含视图和视图模型,没有模型或数据。它演示了两个不同视图之间的切换。

更新 1

具体参考演示代码....您的 VM 被添加到 VM 的静态集合中(请参阅 AddViewModel 函数),当您单击一个按钮例如,通过调用 'SelectViewCommand',它又将 Current_ViewModel 设置为选定的 ViewModel... 然后更新相应的 ContentControl 以显示当前选定的视图...

我知道这很混乱,很难解释

当您按下按钮 'change Views' 时,您实际上是在更改您的 ContentControl 绑定到的 属性 的值,因此您必须在class 你的 ContentControl 也被绑定了...

在演示中你会看到 'LogOn_View' 我调用

 Command="{Binding DataContext.SelectViewCommand, ElementName=Base_V}"CommandParameter="Main_ViewModel"

这里我调用的是Base_ViewModel中的SelectViewCommand(x:Name="Base_V" in Base_View XAML),那是因为我想改变那个View显示在 Base_View 的 'ContentControl'

在Main_View我叫

 Command="{Binding SelectViewCommand}" CommandParameter="MainV1_ViewModel"

这里我调用了Main_ViewModel中的SelectViewCommand,那是因为我想改变MainView中显示的View 'ContentControl'.....

我通常创建一个 WindowService class 用于在 MVVM 中管理 window changes/dialogs。在 ViewModel 中使用 "View" 代码(即 Window.Show())违反了 MVVM 原则。例如:

public class WindowService : IWindowService
{
    public void ShowDialog<T>(ViewModelBase viewModel) where T : IApplicationDialog
    {
        IApplicationDialog dialog = (IApplicationDialog)Activator.CreateInstance(typeof(T));

        dialog.Show();
    }
}

然后来自 ViewModel 的调用将类似于:

windowService.ShowDialog<SecondWindow>(new SecondWindowViewModel());

如果您使用 DI,您可以将 IoC 容器的引用传递给 window 服务并从中创建 window 实例,而不是使用 Activator.CreateInstance(我个人更喜欢 DI 方法)