我遇到了模型 - 视图关系的麻烦。
为了向用户呈现数据,View必须能够访问数据,对吧? 是通过将所有需要的数据直接传递给视图(并使视图将数据作为属性保存在其类中)获得此访问权限,或者只是将数据“解析”为字符串,整数等...因为它是需要(当用户通过GUI导航时)来自控制器,通过提升事件?我觉得这是一个有点过分的事件,因为数据没有改变。
顺便说一句,你能告诉我维基百科上的MVC图上的那些箭头在一个真实的例子中做了什么吗?感谢。答案 0 :(得分:4)
视图仅供演示之用。控制器负责处理来自UI的请求并在模型中调用必要的方法,然后将其输出呈现给视图。
箭头表示类之间的关系。虚线是类和接口之间的关系,而实线表示直接关系,这意味着类可能包含与它们相关的类的实例变量。
答案 1 :(得分:4)
该模型是信息的核心权威信息库。举个例子,拿一个教会的会众目录。
该模型中有控制器可以通知模型应该更改的数据。例如,会众成员在移动或更改电话号码时通知教会办公室,并更新目录。
还有使用该数据的该模型的视图,但无法对其进行更改。例如,一位教会成员可以从目录中获取另一位教会成员的信息。
请注意,在某些情况下,视图和控制器可以是相同的,或者一个模型的视图,另一个模型的控制器等等。例如,教会成员可以查看其他成员的数据,或者更改他们的通过与模型交互来拥有。
要记住的重要一点是谁拥有数据的权威版本。它是具有最及时,准确和权威数据的模型的不变量意味着您确切地知道了获取所需信息的确切位置。
模型可以通过两种基本方式与视图进行通信:推拉。 推送数据涉及模型方面的情报,以了解在更新信息时应通知哪些视图。 拉数据涉及视图方面的情报,以了解如何以及何时查看模型以更改最感兴趣的数据。
答案 2 :(得分:1)
基于之前的答案,这是一个超级简单的应用程序,显示了每个相关区域的各种用法。此应用程序存储和显示销售人员已售出的汽车。
首先我们有我们的模型:
public class Car
{
int Id { get; set; }
string make { get; set; }
string colour { get; set; }
}
public class Salesman
{
int Id { get; set; }
string name { get; set; }
IList<Sale> Sales { get; set; }
}
public class Sale
{
int Id { get; set; }
int CarId { get; set; }
int SalesmanId { get; set; }
decimal Amount { get; set; }
}
现在假设我们需要显示一个页面,其中详细列出了特定销售员销售的所有汽车。为此,我们决定在页面上需要哪些数据,例如:推销员名称和他已售出的汽车名单。我们创建了View Model这些数据。
public class SalesViewModel
{
string SalesmanName { get; set; }
List<Car> CarsSold { get; set; }
}
现在我们需要在我们的控制器中构建(填充)此View模型,以便传递给我们的View。
public ActionResult SalesmanCarsSold(int salesmanId)
{
SalesViewModel salesVm = new SalesViewModel();
using (var dbCtx = new dbCtx())
{
salesVm.SalesmanName = dbCtx.GetSalesmanById(salesmanId).Name;
salesVm.CarsSold = dbCtx.GetCarsSoldBySalesmanId(salesmanId);
}
return View(salesVm);
}
现在所要做的就是将这些数据写入我们的观点,例如
@model MyProject.Web.Models.ViewModels.SalesViewModel
Salesman Name: @Model.SalesmanName
@foreach(var car in Model.CarsSold)
{
Car: @car.make
}
答案 3 :(得分:0)
我相信我可以添加一点清晰度。基本上你可以使用Singleton模式,其中只存在一个模型实例,然后你可以在View中使用所述Singleton将View中的东西绑定到模型,也就是说你为模型的变化添加了监听器(在某种意义上)并且只要模型发生变化,视图就会自动更新。
模型本身不受视图直接影响,而是视图调度事件或以其他方式使用控制器修改模型。通过这种方式,您可以拥有一个共同的“共享”模型,该模型是一个通用控制器,可以修改所述模型和各种视图,以有意义的方式显示所述模型的各个部分。
视图不需要以这种方式处理彼此之间的数据传递,并且修改模型的常见功能包含在控制器中。当我第一次潜入这些概念时,我遇到了一些麻烦,主要是因为你们从来没有100%真正分离这些部分,它们都是相关的,并且会相互引用(至少通过附加的听众)。 / p>
在Flex / AS3我选择的开发环境中这非常容易实现,你在Model.as文件中创建了一个名为modelLocator的静态变量,它本身就是一个新的Model(),在Model.as中你在Controller中定义所有的公共变量。如果你通过创建一个属性来确定模型的句柄(在这里也称之为modelLocator),并且在控制器的构造函数中你可以实例化modelLocator,如modelLocator = Model.modelLocator,在然后在视图中,您只需在模型更改时更新视图组件(在Flex中,您可以使用{}将值直接绑定到组件的属性上,基于@fbereto的帖子从模型中提取视图,很好的解释顺便说一下)。
答案 4 :(得分:0)
从高层次来看,当您考虑应用程序架构即数据层,业务逻辑层和表示层时,MVC应该只是您的表示层。我经常看到人们错误地认为在MVC中,模型代表他们的数据层,控制器代表业务逻辑层,视图代表表示层。
您应始终拥有一个单独的业务逻辑层(或服务层),您的MVC控制器可以访问它来执行业务逻辑,还有一个单独的数据访问层(或存储库),只能由您的服务/业务逻辑层访问从数据库中检索数据。
在典型的MVC应用程序中,您可能有多个视图模型表示相同的数据层对象(通常表示数据库表)。例如,您可能有2个视图来表示有关某个人的信息;一个是摘要视图,另一个是详细信息视图。在您的MVC应用程序中,您将拥有2个视图模型,即PersonSummary和PersonDetail,它们都从数据层中的相同Persons表填充,并在控制器调用方法时返回到Controller Action(例如GetPersonSummary()和GetPersonDetails())在PersonService类(业务逻辑层)上。
以这种方式分层应用程序将使它们比将View Models视为数据模型并在Controller操作中编写所有业务逻辑更具可维护性和可测试性。
无论如何这是我的2cents!希望它能帮助您更好地理解MVC ......