2010-12-17 88 views
2

嘿人。我不知道我是否理解100%的MVC概念。MVC:我做对了吗?

我遇到了Model-View关系的问题。

为了呈现的数据给用户,查看必须能够访问数据,对吧? 该访问是通过将所有需要的数据直接传递给视图(并使视图将其数据作为属性保存在其类中),或者只是将数据“parsed”作为字符串,整数等来获取。是否需要(在用户通过GUI导航时)通过提升事件来控制器?因为数据没有改变,我觉得这是一件有点过度的事情。

顺便说一句,你能告诉我在维基百科上的MVC图上的那些箭头上一个真实的例子吗?谢谢。

+0

请,你会怎么做: 1.使视图召开类别里面的数据,所以它会自动更新本身 2.引发一个事件,使控制器更新组合框与列表从数据中获得的字符串(通过视图上的适当的公共方法) Isnt是否使用单例使数据可用于视图与此模式相矛盾?或者可以,只要我们从单身人士那里获得东西? – dfdfdffd 2010-12-18 07:12:20

回答

4

视图仅用于演示目的。控制器负责调用UI的请求并调用模型中的必要方法,然后将其输出呈现给视图。

箭头表示类之间的关系。虚线是类和接口之间的关系,而实线表示直接关系,这意味着这些类可能拥有与它们相关的类的实例变量。

+0

谢谢你,我的第一个选择是这样吗? – dfdfdffd 2010-12-17 23:09:46

+0

@dfdfdffd对你的第一个问题是的 – Bnjmn 2010-12-17 23:42:47

4

该模型是中央,权威的信息存储库。作为一个例子,拿一个教会的教会目录。

有控制器进入该模型,通知模型应该改变的数据。例如,会众成员在移动或更改电话号码时通知教堂办公室,并更新目录。

也享有成模型,使用数据,但不能进行更改。举个例子,一位教会成员可以从目录中获得关于他人的信息。

注意,在某些情况下,视图和控制器可以是相同的东西,或观看一个模型中,控制器为另一个,等等,等等。例如教堂构件可以是一个视图到其它成员的数据,或改变他们通过与模型进行交互。

要记住的重要一点是谁拥有权威版本的数据。不变的是,它是具有最及时,准确和权威性数据的模型,意味着您确切知道去哪里获取所需的信息。

模型可以通过两种基本方式与视图进行交流:推拉。 推动数据涉及模型方面的情报,以知道在更新信息时应通知哪些视图。 拉动该数据涉及到视图方面的情报,以知道如何以及何时查看模型,以改变其最感兴趣的数据。

+0

谢谢你,喜欢推拉比喻。 因此,如果视图拉动信息并且知道所有数据和关于数据的任何事情,那么它是否可以?或者这是不是建议? – dfdfdffd 2010-12-17 23:39:34

+0

你能回答这个吗?我认为我所有的疑虑都会以一个很好的答案消失:假设视图必须使用模型中的数据更新组合框。你会怎么做? 1.使视图保存类中的数据,因此它自动更新自己2.提出事件并使控制器用从数据中获取的字符串列表更新组合框(通过视图上的适当公共方法) – dfdfdffd 2010-12-17 23:47:46

0

我相信我可以增加一点清晰度。基本上你可以使用Singleton模式,其中只有一个模型实例存在,那么你可以在View中使用Singleton来将视图中的东西绑定到模型上,也就是为模型中的变化添加监听器(在某种意义上或另一种意义上),并且视图在模型更改时自动更新。

模型本身并不直接由视图,而视图调度事件或以其他方式使用的控制器来修改模型的影响。通过这种方式,您可以拥有一个共同的“共享”模型,它是一种通用控制器,它可以修改所述模型以及以有意义的方式显示所述模型的各个部分的各种视图。

视图不需要处理以这种方式在彼此之间传递数据,并且修改模型的通用功能包含在控制器中。当我第一次接触这些概念时,我遇到了一些麻烦,主要是因为你从来没有100%真正的这些部分的分离,它们都是相关的,并且会相互引用(至少通过附加的听众)。

在Flex/AS3中,我的开发环境非常容易实现,您可以在Model.as文件中创建一个名为say modelLocator的静态变量,它本身就是Model.as中的一个新Model()你可以在Controller.as中定义所有的公共变​​量,通过创建一个属性(在这里也可以称之为modelLocator),并且在控制器的构造函数中你可以实例化modelLocator,比如modelLocator = Model.modelLocator,做同样的事情在视图中,然后在视图中更新视图组件(在Flex中,您可以使用{}将值直接绑定到组件的属性上,视图根据@fbereto中的帖子从模型中拉出,好的解释BTW)。

+0

但什么是阻止视图使用单例数据实例来修改数据以及获取数据来生成视图? 或者它应该是这样的 – dfdfdffd 2010-12-18 07:36:11

0

从高层次看,当您考虑应用程序体系结构即数据层,业务逻辑层和表示层时,MVC应该只是您的表示层。我经常看到人们犯了一个错误,认为在MVC中,模型代表数据层,控制器代表业务逻辑层,视图代表表示层。

您应该始终有一个单独的业务逻辑层(或服务层),您的MVC控制器可以访问该业务逻辑层来执行业务逻辑,并且还应该有一个单独的数据访问层(或存储库),只有您的服务/业务逻辑层从数据库中检索数据。

在典型的MVC应用程序中,可能有多个视图模型表示同一个数据层对象(通常代表数据库表)。例如,您可能有2种观点来表示关于某人的信息;一个是摘要视图,另一个是详细视图。在您的MVC应用程序中,您将拥有2个视图模型,即PersonSummary和PersonDetail,这两个视图模型都是从数据层中的相同人员表中填充的,并在控制器调用方法(例如GetPersonSummary()和GetPersonDetails())时返回到Controller Action在PersonService类(业务逻辑层)上。

以这种方式分层您的应用程序将使它们比将视图模型视为数据模型并将所有业务逻辑写入控制器操作中更具可维护性和可测试性。

无论如何,这是我的2cents!希望它可以帮助你更好地理解MVC ...

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 
}