在Asp.Net MVC 3应用程序中收集复杂的子对象? [英] Collection of complex child objects in Asp.Net MVC 3 application?

查看:96
本文介绍了在Asp.Net MVC 3应用程序中收集复杂的子对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想能够在同一视图中更新模型及其子对象的所有集合。我参考了这些例子: http: //haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length -list-aspnet-mvc-2-style /

I want to be able to update a model and all its collections of child objects in the same view. I have been referred to these examples: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx and http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/ .

例如,我有一个对象Consultant,它有一个WorkExperiences集合。所有这些都在实体框架模型中。在这个视图中,顾问对象的简单属性没有问题,但是我收不到文本框来显示。我尝试了以上链接中的示例,但它不起作用。问题是,在这些示例中,模型只是一个列表(不是具有子列表属性的对象)。而且,该模型又是一个EF模型。而且由于某些原因似乎没有像这些例子那样起作用。

For example, I have an object Consultant, that has a collection of "WorkExperiences". All this is in an Entity Framework model. In the view, the simple properties of the Consultant object is no problem, but the collection I cannot get a textbox to show up for. I tried following the examples in the links above, but it doesn't work. The problem is, in those examples the model is just a list (not an object with a child list property). And also, the model again is an EF model. And for some reason that doesn't seem to work as in those examples.

只是为了简单,我试图按照Phil Haacks的例子做一些事情,并且只需要查看即可显示文本框:

Just to make it simple, I tried to do something along the lines of Phil Haacks example, and just get the View to show the textbox:

@for (int i = 0; i < Model.WorkExperiences.Count; i++)
{
    Html.TextBoxFor(m => m.WorkExperiences[i].Name);
}

我试图在控件中为ViewModel创建一个新的WorkExperience对象: / p>

I tried to create a new WorkExperience object in the controller for the ViewModel:

    public ActionResult Create(int id)
    {
        Consultant consultant = _repository.GetConsultant(id);
        DetailsViewModel vm = new DetailsViewModel();
        vm.WorkExperiences = consultant.WorkExperiences.ToList();
        vm.WorkExperiences.Add(new WorkExperience());           
        return View(vm);
    }

但是,View不会显示WorkExperience Name属性的任何空文本框。如果另一方面,我创建一个单独的视图只是为了添加一个新的WorkExperience对象,传递一个新的空的WorkExperience对象作为模型,这工作正常:

But the View doesn't show any empty textbox for the WorkExperience Name property. If on the other hand I create a separate View just for adding a new WorkExperience object, passing a new empty WorkExperience object as the model, this works fine:

@Html.EditorFor(model => model.Name)

我是一个空的文本框,我可以保存新的对象。但是为什么我不能像顾问对象那样看待这个问题,根据上面的链接中的例子,收藏品如何?

That gives me an empty textbox, and I can save the new object. But why can't I do this in the same view as the Consultant object, with collections according to the examples in the links above?

BTW,这是一种后面的问题提到了一个较早的一个问题,指出了上述的联系,但是我从未得到最终的解决方案。如果需要更多信息,请查看该问题:创建MVC 3应用程序模型中对象属性的视图?

BTW, this is sort of a follow-up question to an earlier one, that pointed me to the above links, but I never got to a final solution for it. See that question if more info is needed: Create Views for object properties in model in MVC 3 application?

更新:

根据答案以下是View和EditorTemplate的更新:

According to answers and comments below, here's an update with the View and an EditorTemplate:

视图:

@model Consultants.ViewModels.DetailsViewModel

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Add work experience", "CreateWorkExperience", new { id = ViewBag.Consultant.Id })
</p>
<table>
    <tr>
        <th></th>
        <th>
            Name
        </th>

    </tr>

@foreach (var item in Model.WorkExperiences) {
    <tr>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
            @Html.ActionLink("Details", "Details", new { id = item.Id }) |
            @Html.ActionLink("Delete", "Delete", new { id = item.Id })
        </td>
        <td>
            @item.Name
        </td>

    </tr>

}

</table>

@for (int i = 0; i < Model. WorkExperiences.Count; i++)
{
    Html.EditorFor(m => m. WorkExperiences[i]);
}

(请注意,这一切并不是我如何设计的最后,我现在所有的目的是让WorkExperience对象显示为一个空的文本框以填写,并且能够添加和删除像Phil Haack和Steven Sanderson的例子中的这样的文本框。)

(Please note that all this is not really how I'll design it in the end, all I am after right now is to get the WorkExperience object to show up as an empty textbox to fill out, and to be able to add and delete such textboxes as in Phil Haack's and Steven Sanderson's examples.)

EditorTemplate:

The EditorTemplate:

@model Consultants.Models.WorkExperience


@Html.TextBoxFor(m => m.Name);

这个与EditorTemplate的东西在Phil Haack的示例项目中可以正常工作,我下载了这个项目,但是在这里,与EF模型或任何问题,我根本没有任何文本框。视图中的表只是一个测试,因为在表中我可以获得WorkExperiences的行,无论我添加一个空的WorkExperience对象还是填写其属性并不重要,每个对象都显示出这些行。但是再一次,没有文本框...

This stuff with the EditorTemplate works fine in Phil Haack's sample project, which I downloaded to try, but here, with the EF model or whatever the problem is, I don't get any textbox at all. The table in the view is just there as a test, because in the table I do get the rows for WorkExperiences, whether I add an empty WorkExperience object or fill out its properties doesn't matter, the rows show up for each object. But again, no textbox...

推荐答案


例如,我有一个对象顾问,有一个工作经验的集合。所有这一切都在实体框架模型中。

For example, I have an object Consultant, that has a collection of "WorkExperiences". All this is in an Entity Framework model.

这是您应该改进的第一件事:引入视图模型,不要使用您的域模型进入视图。

That's the first thing you should improve: introduce view models and don't use your domain models into the view.

这就是说我们转向模板。所以你可以完全消除在你的意见中写循环的需要。

This being said let's move on to the templates. So you can completely eliminate the need to write loops in your views.

所以这里是你的看法如下:

So here's how your view might look like:

@model Consultants.ViewModels.DetailsViewModel

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Add work experience", "CreateWorkExperience", new { id = ViewBag.Consultant.Id })
</p>
<table>
    <tr>
        <th></th>
        <th>
            Name
        </th>
    </tr>
    @Html.DisplayFor(x => x.WorkExperiences)
</table>

@Html.EditorFor(x.WorkExperiences)

所以你可以我们正在使用显示模板和编辑器模板。现在我们来定义它们。

So as you can we are using a display template and an editor template. Let's define them now.

显示模板(〜/ Views / Shared / DisplayTemplates / WorkExperience.cshtml ): / p>

Display template (~/Views/Shared/DisplayTemplates/WorkExperience.cshtml):

@model AppName.Models.WorkExperience
<tr>
    <td>
        @Html.ActionLink("Edit", "Edit", new { id = Model.Id }) |
        @Html.ActionLink("Details", "Details", new { id = Model.Id }) |
        @Html.ActionLink("Delete", "Delete", new { id = Model.Id })
    </td>
    <td>
        @Model.Name
    </td>
</tr>

编辑器模板(〜/ Views / Shared / EditorTemplates / WorkExperience.cshtml ):

@model AppName.Models.WorkExperience
@Html.TextBoxFor(x => x.SomePropertyOfTheWorkExperienceModelYouWantToEdit)
...

这里重要的是命名约定。模板的名称应该是集合中项目类型的名称。所以例如在你的视图模型中,你有一个属性

What is important here is the naming convention. The name of the template should be the name of the type of the item in the collection. So for example if in your view model you have a property

public IEnumerable<Foo> { get; set; }

相应的模板应该称为 Foo.cshtml 并且应该位于〜/ Views / Shared / DisplayTemplates 〜/ Views / Shared / EditorTemplates 它的作用。

the corresponding template should be called Foo.cshtml and should be located in ~/Views/Shared/DisplayTemplates or ~/Views/Shared/EditorTemplates depending on its role.

所以你可以看到我们摆脱了令人讨厌的循环。现在,不仅视图看起来很干净,而且您可以为输入字段获取正确的名称,以便您可以在后期操作中绑定值。

So as you can see we have gotten rid of the nasty loops. Now not only that the views look clean, but you get correct names for the input fields so that you can bind the values back in the post action.

这篇关于在Asp.Net MVC 3应用程序中收集复杂的子对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆