免责声明:我之前没有MVVM / MVC / MVP / MVWath的经验,这是我第一次尝试使用任何UI分离模式.
在启动时,我的应用程序需要从配置文件加载数据,这是应用程序工作所需的.
目前,我正在App.xaml.cs中启动时读取配置文件,并且我将文件的内容传递给视图模型:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
string configFile = "settings.txt";
string[] config = File.ReadAllLines(configFile);
var window = new MainWindow();
var viewmodel = new MainWindowViewModel(config);
window.DataContext = viewmodel;
window.Show();
}
}
1.这是“正确的”MVVM方式吗?
我确信这种方式比直接在视图模型中读取文件更好(这就是我先做的方式),但我不确定App.xaml.cs是否适合读取配置文件.
2.我在哪里/如何处理错误?
配置文件中的数据对于应用程序至关重要.
因此,如果文件丢失或为空,或者文件中的数据无效,那么我需要显示错误消息并退出应用程序.
我的第一次尝试也是将它放在App.xaml.cs中:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
string configFile = "settings.txt";
if (!File.Exists(configFile))
{
MessageBox.Show("config file missing");
Application.Current.Shutdown();
return;
}
string[] config = File.ReadAllLines(configFile);
if (config.Count() == 0)
{
MessageBox.Show("config file empty");
Application.Current.Shutdown();
return;
}
var window = new MainWindow();
var viewmodel = new MainWindowViewModel(config);
window.DataContext = viewmodel;
window.Show();
}
}
但这对我来说并不“正确”.我已经对在那里加载文件感到不舒服(参见第一个例子),所以这更糟糕.
注意:我知道我可能不应该直接在这里调用Messagebox.Show.
请注意,这不是我在这里要求的 – 我知道我应该用更像MVVM的东西替换它,但重点是:我仍然需要从某个地方调用它(然后关闭应用程序).
我真正想知道的是App.xaml.cs是否适合这个!
另外,我还有另一种错误:
配置文件的实际解析是由模型完成的(模型是现有库的一部分,我在这里构建的WPF应用程序只是一个很好的用户界面).
因此视图模型创建模型的实例并调用解析方法…如果配置文件中的数据无效,则抛出异常.
我如何处理“MVVM方式”?
只是在视图模型中捕获异常并从那里关闭整个应用程序对我来说是错误的.
编辑:
回答Will关于我为什么不使用app.config的评论:
我正在使用“特殊”配置文件,因为我需要从那里加载几个命名的“值集”. Here’s an example file.
基本上,它是Dictionary< string,List< ClassWithTwoStringProperties>>.
> AFAIK,app.config不支持这样的数据,所以我唯一能做的就是将整个内容保存为app.config中的一个属性中的blob,并且仍然自己进行解析.
– >所以我仍然需要从WPF应用程序的某个地方调用解析.
>我想要一种简单的,可编辑的格式
> WPF应用程序只是一个很好的UI库,我也需要库中的配置文件
最佳答案 我想,这种方式是不正确的.
您应该将app.config视为任何持久数据(例如数据库,文件).如果要以MVVM方式访问持久化数据,则应编写服务(类似于IApplicationDataService)并从MainWindowViewModel代码中调用此服务实现.如果您将从某个ServiceLocator中找到此服务或通过IoC容器注入它,那么它将更加MVVMish – 这有助于稍后编写单元测试.
服务的实现应返回查看模型初始化的模型实例.像这样的东西:
public ApplicationDataService : IApplicationDataService
{
public ApplicationModel LoadApplicationData()
{
// process app.config here
}
}
public ViewModelBase<TModel>
{
public TModel Model
{
get { return model.Value; }
}
private readonly Lazy<TModel> model = new Lazy(GetModel);
protected abstract TModel GetModel();
}
public MainWindowViewModel<ApplicationModel> : ViewModelBase
{
protected override ApplicationModel GetModel()
{
try
{
var dataService = ServiceLocator.GetService<IApplicationDataService>();
return dataService.LoadApplicationData();
}
catch (AnyException e)
{
// oops!
}
}
}