IT干货网

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

wuhuacong 2025年02月15日 编程设计 27 0

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

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

经过一些谷歌搜索/阅读答案后,我遇到了 WindowManager 的概念。 (就像在 CaliburnMicro 中一样),现在如果我要在一个普通的 MVVM 项目中实现其中一个,这会与我的 ViewModel 一起使用吗?或者只是在我的应用程序的核心?我目前正在将我的项目分成 Model装配/项目,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?



将 View 和 ViewModel 分离到不同的程序集中是您可以做的最好的事情,以确保您永远不会引用与 viewModel 中的 View 相关的内容。你会接受这种强烈的分离。

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

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

现在对于您关于 View 的问题(如何显示它们......等等),我会说 做简单 .就我个人而言,我喜欢在我的 View 的代码隐藏中实例化我的 View 模型。我也经常用 事件 在我的 ViewModels 中,因此通知关联的 View 它应该打开另一个 View 。

例如,当用户单击按钮时,您有一个 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"> 


评论关闭
IT干货网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!