ViewModel 应该如何关闭表单? [英] How should the ViewModel close the form?

查看:15
本文介绍了ViewModel 应该如何关闭表单?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习 WPF 和 MVVM 问题,但遇到了障碍.这个问题与这个问题相似但不完全相同 作为这个问题 (handling-dialogs-in-wpf-with-mvvm)...

I'm trying to learn WPF and the MVVM problem, but have hit a snag. This question is similar but not quite the same as this one (handling-dialogs-in-wpf-with-mvvm)...

我有一个登录"使用 MVVM 模式编写的表单.

I have a "Login" form written using the MVVM pattern.

此表单有一个 ViewModel,其中包含用户名和密码,这些用户名和密码使用普通数据绑定绑定到 XAML 中的视图.它还有一个登录"绑定到登录"的命令表单上的按钮,使用普通数据绑定.

This form has a ViewModel which holds the Username and Password, which are bound to the view in the XAML using normal data bindings. It also has a "Login" command which is bound to the "Login" button on the form, agan using normal databinding.

当登录"命令触发,它调用 ViewModel 中的一个函数,该函数关闭并通过网络发送数据以登录.当这个函数完成时,有两个动作:

When the "Login" command fires, it invokes a function in the ViewModel which goes off and sends data over the network to log in. When this function completes, there are 2 actions:

  1. 登录无效 - 我们只显示一个 MessageBox,一切正常

  1. The login was invalid - we just show a MessageBox and all is fine

登录是有效的,我们需要关闭登录表单并让它返回 true 作为它的 DialogResult...

The login was valid, we need to close the Login form and have it return true as its DialogResult...

问题是,ViewModel 对实际视图一无所知,那么它如何关闭视图并告诉它返回特定的 DialogResult 呢??我可以在 CodeBehind 中粘贴一些代码,和/或将 View 传递给 ViewModel,但这似乎会完全破坏 MVVM 的全部意义......

The problem is, the ViewModel knows nothing about the actual view, so how can it close the view and tell it to return a particular DialogResult?? I could stick some code in the CodeBehind, and/or pass the View through to the ViewModel, but that seems like it would defeat the whole point of MVVM entirely...

最后我只是违反了纯洁"MVVM 模式,让 View 发布一个 Closed 事件,并公开一个 Close 方法.然后 ViewModel 将只调用 view.Close.该视图仅通过接口已知并通过 IOC 容器连接,因此不会丢失可测试性或可维护性.

In the end I just violated the "purity" of the MVVM pattern and had the View publish a Closed event, and expose a Close method. The ViewModel would then just call view.Close. The view is only known via an interface and wired up via an IOC container, so no testability or maintainability is lost.

接受的答案是 -5 票似乎很愚蠢!虽然我很清楚一个人在纯粹"的情况下解决问题所带来的好感,但我当然不是唯一一个认为 200 行事件、命令和行为只是为了避免单行方法的人以模式"的名义和纯度"有点可笑....

It seems rather silly that the accepted answer is at -5 votes! While I'm well aware of the good feelings that one gets by solving a problem while being "pure", Surely I'm not the only one that thinks that 200 lines of events, commands and behaviors just to avoid a one line method in the name of "patterns" and "purity" is a bit ridiculous....

推荐答案

我的灵感来自于 Thejuan 的答案 编写一个更简单的附加属性.没有样式,没有触发器;相反,你可以这样做:

I was inspired by Thejuan's answer to write a simpler attached property. No styles, no triggers; instead, you can just do this:

<Window ...
        xmlns:xc="clr-namespace:ExCastle.Wpf"
        xc:DialogCloser.DialogResult="{Binding DialogResult}">

这几乎和 WPF 团队一开始就做对了并让 DialogResult 成为依赖属性一样干净.只是放一个 bool?您的 ViewModel 上的 DialogResult 属性并实现 INotifyPropertyChanged,瞧,您的 ViewModel 可以通过设置属性来关闭窗口(并设置其 DialogResult).MVVM 应有的样子.

This is almost as clean as if the WPF team had gotten it right and made DialogResult a dependency property in the first place. Just put a bool? DialogResult property on your ViewModel and implement INotifyPropertyChanged, and voilà, your ViewModel can close the Window (and set its DialogResult) just by setting a property. MVVM as it should be.

这是 DialogCloser 的代码:

Here's the code for DialogCloser:

using System.Windows;

namespace ExCastle.Wpf
{
    public static class DialogCloser
    {
        public static readonly DependencyProperty DialogResultProperty =
            DependencyProperty.RegisterAttached(
                "DialogResult",
                typeof(bool?),
                typeof(DialogCloser),
                new PropertyMetadata(DialogResultChanged));

        private static void DialogResultChanged(
            DependencyObject d,
            DependencyPropertyChangedEventArgs e)
        {
            var window = d as Window;
            if (window != null)
                window.DialogResult = e.NewValue as bool?;
        }
        public static void SetDialogResult(Window target, bool? value)
        {
            target.SetValue(DialogResultProperty, value);
        }
    }
}

我也发布了这个 在我的博客上.

这篇关于ViewModel 应该如何关闭表单?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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