一尘不染

在MVVM WPF中打开新窗口

c#

我有一个Button,并将此按钮绑定到ViewModel中的一条命令say
OpenWindowCommand。当我单击按钮时,我想打开一个新窗口。但是创建窗口实例并从视图模型显示窗口是违反MVVM的。我已经创建了界面

interface IWindowService
{
    void showWindow(object dataContext);
}

WindowService实现此接口,例如

class WindowService : IWindowService
{
    public void showWindow(object dataContext)
    {
        ChildWindow window=new ChildWindow();
        window.DataContext=dataContext;
        window.Show();
    }
}

在课堂上我指定了ChildWindow。因此,这堂课与表演紧密结合ChildWindow。当我想显示另一个窗口时,必须使用相同的接口和逻辑来实现另一个类。如何使该类通用,以便我可以传递任何窗口的实例,并且该类将能够打开任何窗口?

我没有使用任何内置的MVVM框架。我已经阅读了许多关于StackOverflow的文章,但是找不到任何解决方案。


阅读 806

收藏
2020-05-19

共1个答案

一尘不染

您说“从视图模型创建窗口实例并显示窗口违反了MVVM”。这是对的。

现在,您正在尝试创建一个接口,该接口采用VM指定的视图类型。这同样违反。您可能已经抽象出了界面背后的创建逻辑,但是您仍在从VM内部请求视图创建。

VM仅应关心创建VM。如果您确实需要一个新窗口来托管新VM,则可以像完成操作一样提供一个界面,但不提供视图。为什么需要视图?大多数(VM首先)MVVM项目使用隐式数据模板将视图与特定VM关联。VM对它们一无所知。

像这样:

class WindowService:IWindowService
{
    public void ShowWindow(object viewModel)
    {
        var win = new Window();
        win.Content = viewModel;
        win.Show();
    }
}

显然,您需要确保在app.xaml中设置了VM-> View隐式模板,才能正常工作。这只是标准VM首先的MVVM。

例如:

<Application x:Class="My.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:vm="clr-namespace:My.App.ViewModels"
             xmlns:vw="clr-namespace:My.App.Views"
             StartupUri="MainWindow.xaml">
    <Application.Resources>

        <DataTemplate DataType="{x:Type vm:MyVM}">
            <vw:MyView/>
        </DataTemplate>

    </Application.Resources>
</Application>
2020-05-19