c# – 如何在MVVM中管理多个窗口

我知道有几个类似于这个的问题,但是我还没有找到明确的答案.我正试图深入了解MVVM,并尽可能保持纯粹的东西,但不确定如何在坚持模式的同时启动/关闭窗口.

我最初的想法是使用ViewModel触发代码来启动新View的数据绑定命令,然后View的DataContext通过XAML设置为它的ViewModel.但这违反了我认为的纯MVVM ……

在一些谷歌搜索/阅读答案之后,我遇到了一个WindowManager的概念(就像在CaliburnMicro中一样),现在如果我要在一个vanilla MVVM项目中实现其中一个,那么我的ViewModels是否可以使用它?或者只是我申请的核心?我目前正在将我的项目分离为模型程序集/项目,ViewModel程序集/项目和View程序集/项目.这应该进入一个不同的“核心”组装吗?

这导致了我的下一个问题(与上述有关),如何从MVVM的角度启动我的应用程序?最初我会从App.xaml启动我的MainView.xaml,而XAML中的DataContext将附加指定的ViewModel.如果我添加一个WindowManager,这是我的应用程序首先启动的吗?我是否从App.xaml.cs的代码中执行此操作?

最佳答案 那么它主要取决于你的应用程序的样子(即同时打开多少个窗口,模态窗口或不等等).

我要给出的一般建议是不要尝试做“纯粹的”MVVM;我经常阅读诸如“应该存在零代码”之类的内容……等等,我不同意.

I’m currently separating out my project into a Model assembly/project,
ViewModel assembly/project and View assembly/project. Should this go
into a different, “Core” assembly?

将视图和ViewModel分离到不同的程序集中是您可以做的最好的事情,以确保您不会在viewModel中引用与视图相关的内容.这种强烈的分离你会没事的.

使用两个不同的程序集从ViewModel中分离模型也是一个好主意,但这取决于模型的外观.我个人喜欢3层架构,所以通常我的模型是WCF客户端代理,并且确实存储在它们自己的程序集中.

无论如何,“核心”程序集总是一个好主意(恕我直言),但只是为了公开可以在应用程序的所有层中使用的基本实用程序方法(例如基本扩展方法等等).

现在,关于观点的问题(如何展示它们等等),我想说的很简单.我个人喜欢在我的Views的代码隐藏中实例化我的ViewModel.我还经常在我的ViewModel中使用事件,因此通知关联视图它应该打开另一个视图.

例如,当用户单击按钮时,您有MainWindow应该显示子窗口的场景:

// Main viewModel
public MainViewModel : ViewModelBase
{
    ...
    // EventArgs<T> inherits from EventArgs and contains a EventArgsData property containing the T instance
    public event EventHandler<EventArgs<MyPopupViewModel>> ConfirmationRequested;
    ...
    // Called when ICommand is executed thanks to RelayCommands
    public void DoSomething()
    {
        if (this.ConfirmationRequested != null)
        {
            var vm = new MyPopupViewModel
            {
                // Initializes property of "child" viewmodel depending
                // on the current viewModel state
            };
            this.ConfirmationRequested(this, new EventArgs<MyPopupViewModel>(vm));
        }
    }
}
...
// Main View
public partial class MainWindow : Window
{
    public public MainWindow()
    {
        this.InitializeComponent();

        // Instantiates the viewModel here
        this.ViewModel = new MainViewModel();

        // Attaches event handlers
        this.ViewModel.ConfirmationRequested += (sender, e) =>
        {
            // Shows the child Window here
            // Pass the viewModel in the constructor of the Window
            var myPopup = new PopupWindow(e.EventArgsData);
            myPopup.Show();         
        };
    }

    public MainViewModel ViewModel { get; private set; }
}

// App.xaml, starts MainWindow by setting the StartupUri
<Application x:Class="XXX.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             ...
             StartupUri="Views/MainWindow.xaml">
点赞