ASP MVC 3中的一个视图中的两个模型

Sma*_*rty 92 viewmodel asp.net-mvc-3

我有2个型号:

public class Person
{
    public int PersonID { get; set; }
    public string PersonName { get; set; }
}
public class Order
{
    public int OrderID { get; set; }
    public int TotalSum { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我想在SINGLE视图中编辑BOTH类的对象,所以我需要这样的东西:

@model _try2models.Models.Person
@model _try2models.Models.Order

@using(Html.BeginForm())
{
    @Html.EditorFor(x => x.PersonID)
    @Html.EditorFor(x => x.PersonName)
    @Html.EditorFor(x=>x.OrderID)
    @Html.EditorFor(x => x.TotalSum)
}
Run Code Online (Sandbox Code Playgroud)

当然,这不起作用:.cshtml文件中只允许一个"模型"语句.可能有一些解决方法吗?

And*_*rew 116

创建包含两个模型的父视图模型.

public class MainPageModel{
    public Model1 Model1{get; set;}
    public Model2 Model2{get; set;}
}
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您可以在以后轻松添加其他模型.

  • 当你问自己"为什么我以前没有想到那个?"时的情绪?好的解决方案 (4认同)
  • 使用此解决方案时,请记住,对Model1或Model2的更改可能会对MainPageModel产生影响.它们主要包含的数据多于视图真正需要的数据.如果您的MainPage是已经存在于其他控制器中的事物的组合,则从RenderPartial切换到RenderAction将允许您将事物整齐地分开.考虑阅读Demeter法:http://en.wikipedia.org/wiki/Law_of_Demeter (2认同)
  • 在我看到解决这个问题的所有方法中,这是最适合我的方法.它是迄今为止最简单的解决方案. (2认同)

Ham*_*oli 51

要使用元组,您需要执行以下操作,在视图中将模型更改为:

@model Tuple<Person,Order>
Run Code Online (Sandbox Code Playgroud)

要使用@html方法,您需要执行以下操作,即:

@Html.DisplayNameFor(tuple => tuple.Item1.PersonId)
Run Code Online (Sandbox Code Playgroud)

要么

@Html.ActionLink("Edit", "Edit", new { id=Model.Item1.Id }) |
Run Code Online (Sandbox Code Playgroud)

Item1表示传递给Tuple方法的第一个参数,您可以使用Item2访问第二个模型,依此类推.

在你的控制器中,你需要创建一个类型为Tuple的变量,然后将其传递给视图:

    public ActionResult Details(int id = 0)
    {
        Person person = db.Persons.Find(id);
        if (person == null)
        {
            return HttpNotFound();
        }
        var tuple = new Tuple<Person, Order>(person,new Order());

        return View(tuple);
    }
Run Code Online (Sandbox Code Playgroud)

另一个例子:视图中的多个模型


Bob*_*son 48

另一个不需要创建自定义模型的选项是使用元组<>.

@model Tuple<Person,Order>
Run Code Online (Sandbox Code Playgroud)

根据Andi的回答,它并不像创建包含两者的新类一样干净,但它是可行的.

  • 你可以分别获得每个Model的属性:`@ Model.Item1.Property`和`@ Model.Item2.Property`分别为`Person`和`Order` (3认同)

Fen*_*ton 10

如果您喜欢非常扁平的模型,只是为了支持视图,您应该创建一个特定于此特定视图的模型...

public class EditViewModel
    public int PersonID { get; set; }
    public string PersonName { get; set; }
    public int OrderID { get; set; }
    public int TotalSum { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

许多人使用AutoMapper从他们的域对象映射到他们的平面视图.

视图模型的想法是它只支持视图 - 没有别的.每个视图都有一个,以确保它只包含该视图所需的内容 - 而不是其他视图所需的属性加载.


Jus*_*ohn 5

好的,每个人都说得通,我把所有的内容都放在这里,以帮助像我这样的新手,这些人需要从头到尾进行解释。

根据@Andrew的答案,您将自己的大班设为2个班。

public class teamBoards{
    public Boards Boards{get; set;}
    public Team Team{get; set;}
}
Run Code Online (Sandbox Code Playgroud)

然后在控制器中填充2个模型。有时您只需要填写一个即可。然后在返回中,您引用大模型,它将其中的2带入View。

            TeamBoards teamBoards = new TeamBoards();


        teamBoards.Boards = (from b in db.Boards
                               where b.TeamId == id
                               select b).ToList();
        teamBoards.Team = (from t in db.Teams
                              where t.TeamId == id
                          select t).FirstOrDefault();

 return View(teamBoards);
Run Code Online (Sandbox Code Playgroud)

在视图顶部

@model yourNamespace.Models.teamBoards
Run Code Online (Sandbox Code Playgroud)

然后加载引用大型模型内容的输入或显示:

 @Html.EditorFor(m => Model.Board.yourField)
 @Html.ValidationMessageFor(m => Model.Board.yourField, "", new { @class = "text-danger-yellow" })

 @Html.EditorFor(m => Model.Team.yourField)
 @Html.ValidationMessageFor(m => Model.Team.yourField, "", new { @class = "text-danger-yellow" })
Run Code Online (Sandbox Code Playgroud)

和。。。.back在牧场上,当邮政进来时,请参考大类:

 public ActionResult ContactNewspaper(teamBoards teamboards)
Run Code Online (Sandbox Code Playgroud)

并利用模型返回的内容:

string yourVariable = teamboards.Team.yourField;
Run Code Online (Sandbox Code Playgroud)

该类中可能包含一些DataAnnotation Validation东西,并且可能将if(ModelState.IsValid)放在保存/编辑块的顶部。。。