如何在MVVM中管理多个窗口

dan*_*oks 6 c# wpf xaml mvvm

我知道有几个与此问题类似的问题,但是我还没有找到确切的答案。我正在尝试使用MVVM,并尽可能保持纯净,但不确定在遵循模式的情况下如何精确启动/关闭窗口。

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

经过一番谷歌搜索/阅读答案之后,我遇到了a的概念WindowManager(例如在CaliburnMicro中),现在,如果我要在香草MVVM项目中实现其中一个,那么ViewModels可以加入吗?还是只是我应用程序的核心?我目前正在将我的项目分为一个Model程序集/项目,ViewModel程序集/项目和View程序集/项目。是否应该将其放入不同的“核心”程序集中?

这就引出了我的下一个问题(与上述情况有些相关),如何从MVVM的角度启动应用程序?最初,我将从App.xaml启动MainView.xaml,XAML中的DataContext将附加分配的ViewModel。如果添加WindowManager,这是我的应用程序启动的第一件事吗?我是从后面的代码执行此操作的App.xaml.cs吗?

ken*_*n2k 4

好吧,这主要取决于您的应用程序的外观(即同时打开了多少个窗口,是否为模式窗口......等等)。

我给出的一般建议是不要尝试做“纯粹的”MVVM;我经常读到诸如“后面应该有零代码”之类的东西,我不同意。

我目前正在将我的项目分为模型程序集/项目、ViewModel 程序集/项目和视图程序集/项目。这应该进入不同的“核心”组件吗?

将视图和 ViewModel 分离到不同的程序集中是确保您永远不会引用与 viewModel 中的视图相关的内容的最佳方法。你会适应这种强烈的分离。

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

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

现在,对于您有关视图的问题(如何显示它们...等),我会说做 simple。就我个人而言,我喜欢在视图的代码隐藏中实例化我的视图模型。我还经常在 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">
Run Code Online (Sandbox Code Playgroud)