最佳实践背后的 WPF MVVM 代码

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16973400/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 08:56:59  来源:igfitidea点击:

WPF MVVM Code Behind Best Practices

c#wpfmvvmcode-behind

提问by JvN

I'm a student learning C# with WPF using the MVVM pattern. Recently I have been working on a [art of my application (a custom splash screen) that should not be closed when I don't want it to. I have been searching the web for a good way of doing this without code-behind. Unfortunately after days I still did not find a satisfying way. Then I came to think of a way to do it myself, with help of just one line of code in the constructor of my view. It still makes my code testable and decouples the code from the View. The question is, is there a better way of doing what I'm trying to do:

我是一名使用 MVVM 模式使用 WPF 学习 C# 的学生。最近我一直在研究[我的应用程序的艺术(自定义启动画面),当我不想关闭它时不应该关闭它。我一直在网上搜索没有代码隐藏的好方法。不幸的是,几天后我仍然没有找到令人满意的方法。然后我开始想一种方法来自己做,在我视图的构造函数中只需要一行代码的帮助。它仍然使我的代码可测试并将代码与视图分离。问题是,有没有更好的方法来做我想做的事情:

My interface for my ViewModel

我的 ViewModel 界面

public interface IPreventCloseViewModel
{
    bool PreventClose { get; set; }
}

The extension for the View

视图的扩展

public static class PreventCloseViewModelExtension
{
    /// <summary>
    /// Use this extension method in the constructor of the view.
    /// </summary>
    /// <param name="element"></param>
    public static void PreventCloseViewModel(this Window element)
    {
        var dataContext = element.DataContext as IDisposable;
        if (dataContext is IPreventCloseViewModel)
        {
            element.Closing += delegate(object sender, CancelEventArgs args)
                                   {
                                       if (dataContext is IPreventCloseViewModel)
                                       {
                                           args.Cancel = (dataContext as IPreventCloseViewModel).PreventClose;
                                       }
                                   };
        }
    }
}

The code-behind for the View

视图的代码隐藏

public partial class SplashScreen
{
    public SplashScreen()
    {
        InitializeComponent();
        this.PreventCloseViewModel();
    }
}

回答by Federico Berasategui

MVVM does not mean that you cannot use Code-Behind.

MVVM 并不意味着您不能使用代码隐藏。

MVVM means that your application logic should not be tied to UI elements.

MVVM 意味着您的应用程序逻辑不应绑定到 UI 元素。

You can perfectly well handle events in code behind (such as Window.Closing), and "send messages" or execute methods in the ViewModel to react to that.

您可以完美地处理隐藏代码(例如Window.Closing)中的事件,并在 ViewModel 中“发送消息”或执行方法以对此做出反应。

Here, you are not breaking MVVM by placing the event handler in code behind. You would be breaking MVVM if you were placing the logic that determines whether the application can be closed in code behind. That is a responsibility of the application logic, and the application logic lives in ViewModels, not Views.

在这里,您不会通过将事件处理程序放在后面的代码中来破坏 MVVM。如果您将确定应用程序是否可以在后面的代码中关闭的逻辑放置,那么您将破坏 MVVM。这是应用程序逻辑的职责,应用程序逻辑存在于 ViewModels 中,而不是 Views。

回答by H.B.

I usually have a generic Shellclass which subclasses Windowand does something like:

我通常有一个泛型Shell类,它子类化Window并执行以下操作:

public Shell()
{
    InitializeComponent();
    this.Closing += (s,e) =>
    {
        var canClose = Content as ICanClose;
        if (canClose != null)
            e.Cancel = !canClose.CanClose;
    }
}

That way it does not matter what kind of view model you put in, if it implements the interface that will be taken into account.

这样,如果它实现了将要考虑的接口,则放入哪种视图模型并不重要。

Don't see much point in externalizing the logic, and it's fine in terms of the MVVM pattern.

不要认为将逻辑外部化有多大意义,就 MVVM 模式而言,这很好。