WPF MVVM窗口导航 [英] WPF MVVM Window navigation

查看:267
本文介绍了WPF MVVM窗口导航的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将MVVM模式应用到我的应用程序,该应用程序将具有数十个屏幕(具有各自的ViewModels).现在,我陷入了一个非常简单的问题……谁负责创建新窗口,实例化viewModel并将一个分配给另一个?

我认为在View甚至ViewModel中执行此操作是错误的.我看到许多建议使用外部框架的回复,这对我来说不是一个选择.

您怎么看?

Windows的官方建议是什么?

解决方案

让我们尝试一个示例:用户单击一个按钮,并在确认对话框中显示是/否". 通常,您将在按钮的事件处理程序中引发通知:

private void Button_Click(object sender, MouseRoutedEventArgs e)
{
    var result = MessageBox.Show("Confirm?", MessageBoxButton.YesNo);
    if (result == true)
        //something
    else
        //something else
}

现在,由于我们拥有MVVM,因此必须将业务逻辑(此处为if/else)移动到ViewModel中.但是 UI 必须保留在UI控件上! 假设这是ViewModel:

public class VM
{
    public void DoSomething()
    {
        //raise the confirmation interaction
    }
}

ViewModel不能拥有UI ...但是可以拥有与用户所需交互的摘要.

这可能是交互的界面:

public interface IConfirmationInteraction
{
    bool? RaiseConfirmationRequest(string message);
}

因此ViewModel可以具有以下属性:

public IConfirmationInteraction ConfirmInteraction { get; }

VM不实例化它,VM接受其他人传递的接口实例.例如在构造函数中:

public VM(IConfirmationInteraction confirmInteraction)
{
    if (confirmInteraction == null)
        throw new ArgumentNullException(nameof(confirmInteration));
    ConfirmInteraction = confirmInteraction;
}

因此它的方法可以变成:

public void DoSomething()
{
    var result = ConfirmInteraction.RaiseConfirmationRequest("Confirm?");
    if (result == true)
        //do something
    else
        //do something else
}

UI?您可以创建使用UI元素的具体交互:

public class UIConfirmationInteraction : IConfirmationInteraction
{
    public bool? RaiseConfirmationRequest(string message)
    {
        return MessageBox.Show(message, MessageBoxButton.YesNo);
    }
}

您明白这一点吗?我们已经保存了模式:ViewModel与逻辑一起起作用,将不同的抽象放在一起,但是对实现,消息框,按钮等一无所知. 您可以将这些交互实现为UI交互,例如,在拥有VM:

的UI控件的构造函数中

public class MyControl : USerControl
{
    public MyControl()
    {
        DataContext = new VM(new UIConfirmationInteraction());
    }
}

但是您也可以将它们实现为自动结果,例如,当您要运行测试列表尝试使用默认答案是"或默认答案否"时:

public class YesConfirmationInteraction : IConfirmationInteraction
{
    public bool? RaiseConfirmationRequest(string message)
    {
        return true;
    }
}

这称为"依赖注入".在Google上尝试一下,您可以找到许多教程.在这种情况下,我通过构造函数 构建了依赖项注入.

这是一种可靠的方法,您可以通过ViewModels手动构建UI控件之间的所有桥梁,但保留模式.

I'm applying the MVVM pattern to my application that will have dozens of screens (with the respectives ViewModels). Now I'm stuck in a very simple point ... who has the responsibility to create the new window, instantiate the viewModel and assign one to another?

I think is wrong to do this in the View or even in the ViewModel. I saw many replies advising the use of external frameworks, that is not an option to me.

What do you think?

What is the official Windows recommendation?

解决方案

Let's try an example: the user clicks a button and a confirmation dialog box is shown with Yes/No. Normally you would raise the notification in the event handler of the button:

private void Button_Click(object sender, MouseRoutedEventArgs e)
{
    var result = MessageBox.Show("Confirm?", MessageBoxButton.YesNo);
    if (result == true)
        //something
    else
        //something else
}

Now, since we have MVVM, the business logic (here the if/else) must be moved into the ViewModel. But the UI must remain on the UI control! Suppose this is the ViewModel:

public class VM
{
    public void DoSomething()
    {
        //raise the confirmation interaction
    }
}

The ViewModel can't own the UI... but can own an ABSTRACTION of the interaction required with the user.

This may be the interface of the interaction:

public interface IConfirmationInteraction
{
    bool? RaiseConfirmationRequest(string message);
}

So the ViewModel can have a property like this:

public IConfirmationInteraction ConfirmInteraction { get; }

VM does not instantiate it, VM accepts an instance of the interface passed by someone else. For example in the constructor:

public VM(IConfirmationInteraction confirmInteraction)
{
    if (confirmInteraction == null)
        throw new ArgumentNullException(nameof(confirmInteration));
    ConfirmInteraction = confirmInteraction;
}

So its method can become:

public void DoSomething()
{
    var result = ConfirmInteraction.RaiseConfirmationRequest("Confirm?");
    if (result == true)
        //do something
    else
        //do something else
}

And the UI? You can create a concrete interaction that uses UI elements:

public class UIConfirmationInteraction : IConfirmationInteraction
{
    public bool? RaiseConfirmationRequest(string message)
    {
        return MessageBox.Show(message, MessageBoxButton.YesNo);
    }
}

Do you see the point? We have saved the pattern: the ViewModel acts with the logic, putting together different abstractions, but knows nothing about the implementations, about message boxes, buttons, etc.. You can implement those interactions as UI interactions, for example in the constructor of the UI Control that owns the VM:

public class MyControl : USerControl
{
    public MyControl()
    {
        DataContext = new VM(new UIConfirmationInteraction());
    }
}

But you can also implement them as automatic results, for example when you want to run a test list trying a default answer of "yes" or a default answer of "no":

public class YesConfirmationInteraction : IConfirmationInteraction
{
    public bool? RaiseConfirmationRequest(string message)
    {
        return true;
    }
}

This is called "dependency injection". try it on Google, you can find dozens of tutorials. In this case, I've build a dependency injection by constructor.

This is a solid way in which you can build manually all the bridges between the UI controls, through the ViewModels, but preserving the pattern.

这篇关于WPF MVVM窗口导航的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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