我目前正在学习C#,最近我了解了WPF的MVVM设计模式。我正在编写一个简单的程序作为练习它的方法,但我不确定在哪里编写加载数据的方法。
我有一个SalesSheet类,如下所示。这保存了我从.xls文件加载的数据。
class SalesSheet
{
public List<Row> Rows { get; set; }
public SalesSheet()
{
Rows = new List<Row>();
}
public class Row
{
public string CallType { get; set; }
public string HistoryText { get; set; }
}
}
我的问题是,我应该在哪里编写加载数据的方法?写一个像这样的方法是不好的做法:
private void LoadData(string filePath)
在模型中,并将其称为构造函数?
我应该从ViewModel加载吗?
答案 0 :(得分:7)
通常,小型WPF项目应具有以下近似文件夹结构:
DataAccess
是您应存储数据访问类的文件夹。将应用程序的各个方面分开是一种很好的做法;视图,视图模型和数据访问类。这被称为 Separation of Concerns ,这是一种很好的做法,因为它(其中包括)它可以让你切换出层...这意味着你可以以后添加一个网页接口(或更改数据库),同时仍然保持大部分代码相同,这也使得测试代码更容易。
此文件夹中可能只有一个类,我们称之为DataProvider
。在此DataProvider
类中,您将所有数据访问方法。您现在有一个数据访问入口点,您可以在基本视图模型中添加对它的引用:
protected DataProvider DataProvider
{
get { return new DataProvider(); }
}
现在您的视图模型都可以访问项目数据源,然后您可以执行以下操作:
SomeObject someObject = DataProvider.LoadData(filePath);
当然,实现这种模式有很多不同的方法,但现在希望你能理解。
答案 1 :(得分:3)
根据我对 MVVM 的理解,您的LoadData方法属于模型。然后,视图模型可以通过模型中的属性或方法访问加载的数据。 这里重要的一点是,viewmodels不知道具体的文件访问逻辑,它是由模型抽象出来的。
答案 2 :(得分:1)
创建视图模型类。
通过在DataContext
属性中创建视图模型类,在视图的xaml中实例化该视图模型类。
实施一种方法来加载视图模型中的数据,例如LoadData
。
设置视图,以便在加载视图时调用此方法。
您可以通过在视图的事件处理程序中实现Loaded
事件来实现,或者您可以在视图中使用交互触发器并将其链接到视图模型中的方法。
查看(xaml):
<Window x:Class="MyWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Test"
xmlns:viewModel="clr-namespace:ViewModels" Loaded="Window_Loaded">
<Window.DataContext>
<viewModel:ExampleViewModel/>
</Window.DataContext>
查看(代码背后):
private void Window_Loaded(object sender, RoutedEventArgs e)
{
((ExampleViewModel)this.DataContext).LoadData();
}
如果您不想在后面的代码中设置Loaded
事件,您也可以在xaml中执行此操作(参考&#34; Microsoft.Expression.Interactions&#34;和&#34;系统.Windows.Interactivity&#34;是必需的):
<Window x:Class="MyWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Test"
xmlns:viewModel="clr-namespace:ViewModels"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
>
<Window.DataContext>
<viewModel:ExampleViewModel/>
</Window.DataContext>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<ei:CallMethodAction TargetObject="{Binding}" MethodName="LoadData"/>
</i:EventTrigger>
</i:Interaction.Triggers>
在每种情况下,您都可以在ViewModel中调用LoadData
方法。
在这里,您应该调用一个提供数据的单独类。
这个类通常称为存储库。
public class ExampleViewModel
{
/// <summary>
/// Constructor.
/// </summary>
public ExampleViewModel()
{
// Do NOT do complex stuff here
}
public void LoadData()
{
// Make a call to the repository class here
// to set properties of your view model
}
如果存储库中的方法是异步方法,您也可以使LoadData
方法异步,但在每种情况下都不需要这样做。
通常我不会在视图模型的构造函数中加载数据。 在上面的示例中,当设计器显示您的视图时,将调用视图模型的(参数less)构造函数。在这里做复杂的事情可能会在显示你的视图时导致设计师出错(出于同样的原因,我不会在视图构造函数中做出复杂的事情)。
在某些情况下,视图模型构造函数中的代码甚至可能在运行时导致问题,当视图模型构造函数执行时,设置视图模型的属性,这些属性绑定到视图中的元素,而视图对象未完全完成创建
答案 3 :(得分:0)
根据您的项目规格,您有很多选择。
但我发现 DataService 方法简单灵活。
SalesDataService
。GetRows()
或GetSingleById(int id)
...)添加到DataService protected SalesDataService _salesDataService
字段_salesDataService
GetRows()
(如果没有人要求加载数据,则将其放入构造函数中)答案 4 :(得分:0)
Window.ContentRendered
是最安全的事件,如果您使用数据绑定。有些地方,在使用数据绑定时,Window_Loaded
会为时过早,对象仍然为空。