Wpf 使用MVVM显示新窗口并获取更新数据

Wpf 使用MVVM显示新窗口并获取更新数据,wpf,mvvm,interface,modal-dialog,Wpf,Mvvm,Interface,Modal Dialog,我正在开发一个WPF MVVM应用程序。我正在数据网格中显示一些数据。我有两个按钮来添加和编辑所选记录。我在ViewModel中有数据,我必须显示另一个窗口(视图),并确保ViewModel不包含有关视图的信息。 我应该在哪里创建其视图和视图模型? 如何取回数据并更新datagrid? 如何在MVVM中实现这一点? 我们还没有决定使用任何框架,所以我必须创建自己的界面。这取决于您如何处理数据。我将假设只有当用户单击“保存”之类的按钮时,弹出窗口中所做的更改才能被接受,否则这些更改将被丢弃。 因此

我正在开发一个WPF MVVM应用程序。我正在数据网格中显示一些数据。我有两个按钮来添加和编辑所选记录。我在ViewModel中有数据,我必须显示另一个窗口(视图),并确保ViewModel不包含有关视图的信息。 我应该在哪里创建其视图和视图模型? 如何取回数据并更新datagrid? 如何在MVVM中实现这一点?
我们还没有决定使用任何框架,所以我必须创建自己的界面。

这取决于您如何处理数据。我将假设只有当用户单击“保存”之类的按钮时,弹出窗口中所做的更改才能被接受,否则这些更改将被丢弃。 因此,首先,我建议使用MVC方法作为控制器非常适合此类任务。您可以在其中构建视图模型,将其指定为o视图并显示视图。VM只保存数据和命令,命令执行方法保存在控制器中。换句话说,您有一个管理VM和视图的singleton类。 您应该检查一下框架。它提供了一些很棒的功能,比如查看区域,您可以在运行时注入不同的用户控件,命令和MVC分层以及IOC和DI模式。

注意:这是一个很长的答案-如果有什么不清楚的地方,请问我

对话窗口的实现在MVVM设计中是一个有争议的问题,不同的人使用不同的方法

和你一样,我决定不使用任何框架,而是手工实现大多数东西。谈到对话框窗口,我选择从ViewModel内部启动对话框窗口,以务实的态度实现MVVM。此外,我允许每个对话框ViewModel都有一个对其显示窗口的引用,以便它可以在适当时关闭它(详细信息如下)。这打破了一些严格的MVVM“规则”,但它完成了任务

这样做的主要缺点是,如果您正在测试通过对话框的内容,那么它可能会破坏单元测试。然而,你可以走很长一段路而不会遇到这个问题,而且它还没有困扰我

我已经建立了一个对话框视图模型库,可以很容易地进行扩展。在这里发布的代码太多了,但我将向您展示其中的亮点

对话框的基本视图模型

我的每个对话框窗口都有一个从
DialogViewModelBase
继承的ViewModel,它与我的常规
ViewModelBase
相似,因为它提供了对
INotifyPropertyChanged
等的支持。有趣的部分是这个公共方法,我从任何地方调用它来启动对话框:

//
///为此对话框viewmodel创建窗口实例并显示它,从而获得对话框结果。
/// 
公共void ShowDialogWindow()
{
//这是DialogViewModelBase类的一个属性-因此,每个DialogViewModel都持有对其自己的DialogWindow的引用:
this.DialogWindow=新建Dialogs.Views.DialogWindow();
//告诉对话框窗口显示此ViewModel:
this.DialogWindow.DataContext=此;
//使用窗口基类的方法启动窗口,该方法仅在窗口关闭时返回:
这个.DialogWindow.ShowDialog();
}
在上述方法中启动的窗口将在设置其
窗口时关闭。DialogResult
属性。这就是为什么
DialogWindow
DialogViewModelBase
类的属性-当子类化对话框
ViewModel
想要关闭对话框窗口时,它只需设置结果:

protectedvoid CloseDialogWithResult(bool dialogWindowResult)
{
//设置此属性将自动关闭对话框窗口:
this.DialogWindow.DialogResult=dialogWindowResult;
}
对话框视图的主机窗口

ShowDialogWindow
方法实例化的
Dialogs.Views.DialogWindow
类在XAML中定义,是
Window
的子类。它有两个重要特征。首先,它的主要内容元素只是绑定到当前上下文的
ContentControl
。这允许我为
DialogViewModelBase
的不同子类定义不同的
视图
,并且
对话框窗口
将根据上下文类型承载相应的
视图

<ContentControl Content="{Binding}" /> <!-- In reality this is inside a border etc but its simplified here for demonstration -->
这一切的作用是,我可以将对话框定义为
DialogViewModelBase
的子类,并为每个对话框实现一个
View
,然后告诉
DialogWindow
哪个
View
它的
ContentControl
必须显示哪个对话框
ViewModel

启动对话框并获得结果

下面是我的一个应用程序
ViewModels
中的一个示例,我在其中启动了一个对话框窗口,允许用户选择要创建的资产类型:

public void CreateNewAsset()
{
//实例化所需的对话框ViewModel:
Dialogs.NewAssetTypeSelectionDialogViewModel dialog=新建对话框。NewAssetTypeSelectionDialogViewModel();
//通过调用对话框基类上的方法启动对话框:
ShowDialogWindow();
//执行将在此停止,直到对话框窗口关闭。。。
//用户的选择存储在对话框ViewModel的属性中,现在可以检索:
CalculatorBase.AssetTypeEnum newAssetType=dialog.AssetType;
开关(新资产类型)
{
//根据用户的选择做一些事情。。。
}
}

PS:我真的应该为此写一篇博客文章——当我写的时候,我会在这里发布链接,因为博客文章可能会有更完整的代码示例。

你的“另一个窗口”像一个模式对话框吗?也就是说,是不是有一个单独的窗口,将焦点保持到再次关闭,然后焦点返回到主窗口?是的,这是一个模式对话框。谢谢您的帖子,MVVM生存指南
<Window.Resources>
    <!-- DEFAULT ViewModel-View TEMPLATES -->

    <DataTemplate DataType="{x:Type dialogs:YesNoMessageBoxDialogViewModel}">
        <views:MessageBoxView />
    </DataTemplate>

    <DataTemplate DataType="{x:Type dialogs:ErrorDialogViewModel}">
        <views:ErrorDialogView/>            
    </DataTemplate>

</Window.Resources>