Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# (WPF/MVVM)什么&x27;iSeries设备和ViewModel之间有什么不同?_C#_Wpf_Mvvm_Service_Interface - Fatal编程技术网

C# (WPF/MVVM)什么&x27;iSeries设备和ViewModel之间有什么不同?

C# (WPF/MVVM)什么&x27;iSeries设备和ViewModel之间有什么不同?,c#,wpf,mvvm,service,interface,C#,Wpf,Mvvm,Service,Interface,我想在我的视图模型中使用保存文件对话框,但由于绑定到视图模型中的视图是不正确的,所以我搜索了一些方法。但是我发现了一些答案,它们并没有将视图与视图模型完全分开,如下所示: public interface IOService { void IMessageBox(string Message); string ISaveFileDialog(string DefaultPath); } public class IDialog : IOService { public v

我想在我的视图模型中使用保存文件对话框,但由于绑定到视图模型中的视图是不正确的,所以我搜索了一些方法。但是我发现了一些答案,它们并没有将视图视图模型完全分开,如下所示:

public interface IOService
{
    void IMessageBox(string Message);
    string ISaveFileDialog(string DefaultPath);
}
public class IDialog : IOService
{
    public void IMessageBox(string Message)
    {
        System.Windows.MessageBox.Show(Message);
    }

    public string ISaveFileDialog(string DefaultPath)
    {
        System.Windows.Forms.SaveFileDialog dg = new SaveFileDialog
        {
            InitialDirectory = DefaultPath,
            Filter = "PDF files (*.pdf) | *.pdf"
        };
        dg.ShowDialog();
        if (dg.FileName == null)
            dg.FileName = string.Empty;
        return dg.FileName;
    }
}
他们说,这是一项服务,使用它将视图视图模型分开。但是我们在视图模型中从中创建了一个实例

IDialog iDialog = new IDialog();
所以我想知道,这个方法和直接从ViewModel调用MessageBoxSaveFileDialog有什么区别

注意:我还发现,我可以使用上述服务,但实现方式如下:


但是我不知道如何将IOService作为参数发送到ExportViewModel(因为我们无法从界面创建实例)

您不应该直接从VM弹出对话框以实现自动测试性

如果调用MessageBox.Show(),则测试将被卡住,直到有人关闭对话框


相反,如果您使用“IMessageBox”进行单元测试,您可以注入一个实现,该实现实际上并不显示对话框,而是返回一个特定的值(结果)。

它是一个抽象,用于将UI关注点与视图模型分离,并允许您在单元测试中拦截这些调用。拦截这些调用既可以防止在测试期间显示对话框(这将阻止测试的执行,这不是很好),也可以验证视图模型是否按预期运行

将其称为“服务”或将抽象称为“iSeries设备”没有什么特别之处。这只是对一种常见模式的暗示

  • 我需要做点什么
  • 我自己做不了
  • 我会找到一个服务,我可以雇用做这件事
  • 我找到了一个可以帮我做到这一点的服务
  • 这项服务可以帮我
你也可以称之为“IDontTouchUIStuffInMuhViewModel”,但这并不优雅

通过向视图模型提供接口的实现,可以在运行时轻松解决第二个问题。您的视图模型不应该关心它是如何实现的(),所以您可以在运行时传入一个合法的实现,在测试期间传入一个假的实现


也可以通过使用或来完成此操作。通过使用库(例如)实例化视图模型,将根据您配置容器的方式自动提供所有依赖项。

因此,所有这些服务或接口仅用于单元测试?因此,正如我之前所说,我们可以在VM中调用MessageBox.Show()@莫斯塔法没有。。。您的VM不应该对对话框、控件或任何其他UI元素执行任何操作。如果确实如此,那么您就违反了MVVM原则。威尔所说的全部要点是,您不希望虚拟机实际依赖于UI对象。将接口传递到ctor是一种工具,允许您分离这些接口。这样想:如果我要重新做UI,在屏幕底部显示我自己的自定义文件选择器,而不是文件保存对话框,我可以这样做吗?如果你做得正确,新的用户界面就会连接到界面上,神奇地工作@Lynn我刚才读到了关于DI和IoC的文章,我所理解的是,这个问题取决于他们,我不明白他们是如何工作的!虽然我读了很多参考资料,但还是不明白!我用MVVM编写了我的应用程序,现在我正处于最后阶段,但我没有在所有程序中使用任何DI或IoC,或者至少我认为我没有!“所以我真的不知道我怎么能做像你刚才说的那样的事情。”莫斯塔法在门口停了下来。那里有很多人整天都在做WPF和MVVM。@Mostafa您真的可以决定如何编写代码。有很好的理由从视图模型中抽象UI代码。但是如果您的应用程序很小,并且代码没有被单元测试执行,那么您就不会因为在视图模型中调用MessageBox.Show()而被捕。最重要的是,要明白这些模式的存在是为了服务于我们,我们的存在不是为了服务于它们。在它们能帮你节省工作和痛苦的地方坚持它们,在它们不能的时候弯曲它们。所以这只是测试的问题,而不是把V和VM分开。因为我不使用单元测试,所以我可以只使用MessageBox.Show()并且不违反MVVM?@Mostafa单元测试就是一个例子。另一种情况是,今天您想要使用MessageBox,明天您可能想要使用MyColdialog,因此您可以交换掉实现类,而不是大规模搜索和替换。如果您正在使用MVVM,那么您应该已经在使用DI了,那么有什么大不了的呢?只需定义一个简单的接口并将MessageBox粘贴到实现中。这会让你在将来被淘汰。谢谢,但我不知道接口怎么能做到这一点!我问题的第二部分就是这个。接口只包含一些初始化方法,而不是实现。所以在使用这个接口的每个类中,我必须定义方法体,这一点都没有帮助。我只需编写一个类(如上面的IDialog)并将其与已有的方法一起使用@在大多数情况下,您可能会有一个IDialogService或任何带有“ShowMessageBox(…)”方法或任何您想调用它的方法的东西。当前的实现将调用MessageBox.Show,但您可以在将来轻松地将实现更改为MyColdialog。我已经用MessageBox和FileDialog完成了这项工作,当我将实现更改为更好的实现时,它为我节省了很多时间。@Mostafa,我给了你一个帮助我的用例。。。编写服务的主要原因是为了单元测试和将来的轻松交换。如果你不在乎的话
public class ExportViewModel : BaseViewModel
{
    IOService _IOService;
    public ExportViewModel(IOService ioservice)
    {
        _IOService = ioservice;
        .
        .
    }
}