我正在开发一个MVVM WPF应用程序。我可以告诉你代码看起来更干净但是一些琐碎的任务对我来说已经成了一大麻烦。
一个很好的例子是显示OpenFileDialog或甚至是ModelViewer类的MessageBox。我知道如何使用RelayCommand,但我不能让OpenFileDialog显示。我在SO中读到它需要应用程序服务。什么是应用服务?
我找不到任何关于此的教程。有人可以用一些例子向我解释一下吗?我知道它与接口有关......
答案 0 :(得分:2)
“服务”是一种通用抽象,允许您将某些代码部分与应用程序的其他部分隔离开来。
通常,在WPF / MVVM世界中,“服务”至少包含三个项目:
服务组了一堆相关的方法。可能有“对话服务”(显示对话框),“数据服务”(从数据源获取数据,将数据保存到数据源)等。您可以考虑“服务”,以及关于链接视图模型的方式外部世界。
例如,WPF服务,其目的是显示一些典型的对话框,将具有如下界面:
public interface IDialogService
{
void ShowAboutBox(AboutBoxSettings settings);
MessageBoxResult ShowMessageBox(MessageBoxSettings settings);
bool? ShowSaveFileDialog(FileDialogSettings settings);
bool? ShowOpenFileDialog(FileDialogSettings settings);
}
它的“真实”实现将调用适当类的方法来显示对话框:
public sealed class DialogService : IDialogService
{
// ...
public void ShowMessageBox(MessageBoxSettings settings)
{
return MessageBox.Show(/* ... */);
}
public bool? ShowOpenFileDialog(FileDialogSettings settings)
{
var dialog = new OpenFileDialog();
// ...
return dialog.ShowDialog();
}
// ...
}
同样,通常,以两种方式查看模型访问服务:
两种方式都假设,视图模型从不使用特定实现来访问服务。而不是这样,他们要求服务定位器或DI容器为他们提供一些服务合同的可用实现:
// getting service through service locator
var dialogService = ServiceLocator.GetService<IDialogService>();
或
// inject service dependency with MEF container
[Import]
private IDialogService dialogService;
您应该选择自己访问服务的方式,但最终,您需要了解服务定位器或DI容器的几个现有实现。
最后,你需要什么这些东西?为什么不显示消息框并使用视图模型中的数据库?
答案很简单。
第一个。对于服务,您的视图模型仅包含该代码,该代码负责与视图交互。你有一个结构良好,解耦的代码,其中一组类与视图交互,另一组与WPF表示子系统交互,另一组与数据库或Web服务等。由于视图模型不依赖于服务实现,你可以在不影响视图模型的情况下轻松更改实现代码(例如,修复错误)。
第二个。您可以使用测试模型模拟“真实”服务,并为视图模型编写单元测试。
答案 1 :(得分:1)
据我所知,WPF没有OpenFileDialog,所以应该使用winform。像这样:
var fileName = Application.Current.Dispatcher.Invoke<string>(() =>
{
var openFileDialog = new OpenFileDialog();
openFileDialog.ShowDialog();
return openFileDialog.FileName;
});
正如我在应用程序服务中所理解的那样,它们意味着在使用依赖注入传递给视图模型的某个类中隔离此代码。
不使用消息框,而是更容易使用放在窗体上所有其他控件上的TextBlock(或带子项的某些边框),默认情况下是不可见的。