使用MVVM显示新窗口并获取更新数据 [英] Using MVVM show new window and get updates data

查看:205
本文介绍了使用MVVM显示新窗口并获取更新数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm working on a WPF MVVM application. I'm showing some data in a datagrid. I've two buttons to Add and Edit the selected record. I've data in ViewModel and I've to show another window (view) and make sure that ViewModels should have no information about views. Where should I create its view and viewmodel? How to get the data back and update datagrid? How can I achieve this in MVVM? We have not yet decided to use any framework, so I've to create my own interface.

推荐答案

注意:这最终是一个很长的答案 - 请问我是否有任何不清楚

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

The implementation of dialog windows is a contentious issue in MVVM designs, and different people use different approaches.

像你一样,我决定不使用任何框架并手动实现大多数事情。谈到对话框窗口,我选择通过从ViewModel内部启动对话窗口来实现我对MVVM的实现。此外,我允许每个Dialog ViewModel引用它所显示的Window,因此它可以在适当时关闭它(详情如下)。这打破了一些严格的MVVM规则,但它完成了工作。

Like you, I've decided not to use any framework and implement most things by hand. When it comes to dialog windows, I choose to be pragmatic about my implementation of MVVM, by launching the Dialog Window from inside my ViewModel. Also, I allow each Dialog ViewModel to have a reference to the Window it is displayed in, so it can close it when appropriate (details below). This breaks some of the strict MVVM "rules", but it gets the job done.

这样做的主要缺点是,如果你正在测试某些东西,它可能会破坏单元测试通过一个对话框。但是,你可以走很长的路而不会遇到这个问题而且它还没有打扰我。

The main downside of this is that it might break unit testing if you are testing something that goes through a dialog. However, you can go a long way without running into that problem and it has not bothered me yet.

我已经构建了一个对话框ViewModels的库我可以轻松扩展。这里发布的代码太多了,但我会向您展示亮点。

I've built up a bit of a library of dialog ViewModels which I can easily extend. It's way too much code to post here, but I'll show you the highlights.

对话框的基本ViewModel

我的每个对话框窗口都有一个ViewModel,它继承自 DialogViewModelBase ,类似于我常规的 ViewModelBase 因为它提供了对 INotifyPropertyChanged 等的支持。有趣的部分是这个公共方法,我从哪里开始调用Dialog:

Each of my dialog windows has a ViewModel that inherits from DialogViewModelBase, which is similiar to my regular ViewModelBase in that it provides support for INotifyPropertyChanged etc. The interesting part is this public method, which I call from wherever to launch the Dialog:

/// <summary>
/// Creates window instance for this dialog viewmodel and displays it, getting the dialog result.
/// </summary>
public void ShowDialogWindow()
{
    // This is a property of the DialogViewModelBase class - thus, each DialogViewModel holds a reference to its own DialogWindow:
    this.DialogWindow = new Dialogs.Views.DialogWindow();
    // Tell the DialogWindow to display this ViewModel:
    this.DialogWindow.DataContext = this;
    // Launch the Window, using a method of the Window baseclass, that only returns when the window is closed:
    this.DialogWindow.ShowDialog();
}

上述方法启动的窗口将在时关闭Window.DialogResult 属性已设置。这就是为什么 DialogWindow DialogViewModelBase 类的属性 - 当子类化对话框 ViewModel时想要关闭对话窗口,它只是设置结果:

Window launched in the above method will close when its Window.DialogResult property is set. This is why the DialogWindow is a property of the DialogViewModelBase class - when the subclassing dialog ViewModel wants to close the dialog window, it simply sets the result:

protected void CloseDialogWithResult(bool dialogWindowResult)
{
    // Setting this property automatically closes the dialog window:
    this.DialogWindow.DialogResult = dialogWindowResult;
}

对话视图的主机窗口

ShowDialogWindow 方法实例化的 Dialogs.Views.DialogWindow 类在XAML中定义,是 Window 的子类。它有两个重要特征。第一个是它的主要内容元素只是一个绑定到当前上下文的 ContentControl 。这允许我为 DialogViewModelBase DialogWindow <的不同子类定义不同的 Views 。 code>将根据上下文的类型托管相应的查看

The Dialogs.Views.DialogWindow class that the ShowDialogWindow method instantiates is defined in XAML and is a subclass of Window. It has two important features. The first is that it's primary content element is simply a ContentControl that binds to the current context. This allows me to define different Views for different subclasses of DialogViewModelBase, and the DialogWindow will host the corresponding View based on the type of the context:

<ContentControl Content="{Binding}" /> <!-- In reality this is inside a border etc but its simplified here for demonstration -->

DialogWindow XAML的第二个重要特征是它定义哪个对话框 Views 使用哪个对话框 ViewModels 。以下是一个示例:

The second important feature of the DialogWindow XAML is that it defines which dialog Views go with which dialog ViewModels. Here is a sample:

<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>

这一切是什么,我可以将对话框定义为 DialogViewModelBase的子类并为每个实现查看,然后告诉 DialogWindow 哪个查看 ContentControl 必须显示哪个对话框 ViewModel

What all this does, is that I can define dialogs as subclasses to DialogViewModelBase and implement a View for each, and then tell DialogWindow which View its ContentControl must show for which dialog ViewModel.

启动对话框并获得结果

以下是我的某个应用程序<$ c $的示例c> ViewModels ,其中我启动一个允许用户选择创建资产类型的对话窗口:

Below is a sample from one of my application ViewModels, in which I launch a Dialog Window that allows the user to select an Asset Type for creation:

public void CreateNewAsset()
{
    // Instantiate desired Dialog ViewModel:
    Dialogs.NewAssetTypeSelectionDialogViewModel dialog = new Dialogs.NewAssetTypeSelectionDialogViewModel();

    // Launch Dialog by calling method on Dialog base class:
    dialog.ShowDialogWindow();

    // Execution will halt here until the Dialog window closes...

    // The user's selection is stored in a property on the dialog ViewModel, and can now be retrieved:
    CalculatorBase.AssetTypeEnum newAssetType = dialog.AssetType;

    switch (newAssetType)
    {
        // Do stuff based on user's selection...
    }
}

PS:我应该写一篇关于此的博客文章 - 当我这样做时,我会在这里发布链接,作为博客条目可能会有更完整的代码示例。

这篇关于使用MVVM显示新窗口并获取更新数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆