MVC4从视图中的项目列表中进行选择

时间:2013-04-28 18:00:36

标签: c# asp.net-mvc asp.net-mvc-4 razor partial-views

我正在寻找一种方法来从我从数据库中检索的项目列表中进行选择。我将这些项目发送到视图,我想从列表中选择并将其返回到控制器以填充数据库中的辅助表。我可以将项目传递给视图并让它们显示但我似乎无法将这些项目传回控制器。

控制器调用(再次更新):

    public ActionResult Create()
    {
        var myMeal = new CreateMeal();
        List<ProductsToInclude> pti = new List<ProductsToInclude>();
        myMeal.ProductsToInclude = pti;
        IList<Product> prods = db.Products.ToList();


        foreach(var prod in prods)
        {
            pti.Add(new ProductsToInclude { Product = prod });
        }

        return View(myMeal);
    }

    //
    // POST: /Meal/Create

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(CreateMeal myMeal)
    {
        if (ModelState.IsValid)
        {
            /* Add code to handle my meal and create a meal for data base*/
            db.Meals.Add(meal);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(pti);
    }

ProductsToInclude ViewModel

public class ProductsToInclude
{
    public Product Product { get; set; }
    public Boolean Include { get; set; }
}

New CreateMeal ViewModel:

public class CreateMeal
{
    public String Name { get; set; }
    public IList<ProductsToInclude> ProductsToInclude { get; set; }
}

创建视图:

@model MealPlanner.ViewModels.CreateMeal

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>Meal</legend>

        <div>
          @Html.LabelFor(m => m.Name)
           @Html.TextBoxFor(m => m.Name)
        </div>

        <div>
            @Html.EditorFor(m => m.ProductsToInclude)
        </div>

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

编辑Templete(UpDated):

@model MealPlanner.ViewModels.ProductsToInclude

<tr>
    <td>
        @Html.CheckBoxFor(m => m.Include)
    </td>
    <td>
        @Model.Product.Name 
        @Model.Product.Quantity 
        @Model.Product.unit.UnitName
        @Html.HiddenFor(m => m.Product.Name) 
        @Html.HiddenFor(m => m.Product.Quantity) 
        @Html.HiddenFor(m => m.Product.unit.UnitName)
    </td>
</tr>

膳食模型:

public class Meal
{
    public int MealId { get; set; }
    public String Name { get; set; }
    //public virtual IList<Product> Products { get; set; }
    public int UserId { get; set; }
}

更新:

切换到EditorTemplete我无法显示它。我现在收到myMeal.ProductsToInclude.Add(new ProductsToInclude {Product = prod,Include = false})的错误;在创建方法中。 prod是人口中有8种产品。

1 个答案:

答案 0 :(得分:0)

这里有两个基本问题。 (第三,你没有将任何模型传递给视图,但是你的视图期望一个Meal对象)首先,你发布的是不同于你渲染的模型。因此,当您发布表单时,它不会识别Meal.Name对象,因为post操作期望ProductsToInclude列表。

如果您不打算更改Meal.Name的值,那么我建议使用DisplayFor而不是EditorFor渲染它。

其次,渲染表单字段的方式不会创建正确的命名结构,以允许默认模型绑定器绑定到集合。你可以使用EditorTemplates,这是我喜欢的方法。

您将创建名为ProductsToInclude.cshtml的编辑器模板,而不是使用Partial,将模型类型设置为ProductsToInclude(不包含List),然后渲染,就好像它是单个项目一样。您还需要将表格和标题信息移到主视图中。

EditorTemplates处理这种情况,而不必做任何特殊的事情。它们会自动迭代集合,并正确呈现名称。尽可能使用它们。

<div>
    <table>
        <tr>
            <th>
                @Html.DisplayName("Include")
            </th>
            <th>
                @Html.DisplayName("Available Products")
            </th>
            <th></th>
       </tr>
       @Html.EditorFor(m => m.ProductsToInclude)
    </table>
</div>

您的ProductsToInclude.cshtml应位于〜/ Views / Shared或本地视图文件夹中名为EditorTemplates的文件夹中。

@model ProductsToInclude
<tr>
    <td>
        @Html.CheckBoxFor(m => m.Include)
    </td>
    <td>
        @Html.DisplayFor(m => m.Product.Name) 
        @Html.DisplayFor(m => m.Product.Quantity) 
        @Html.DisplayFor(m => m.Product.unit.UnitName)
    </td>
    <td>
        @Html.ActionLink("Edit", "Edit", new { id=Model.PrimaryKey }) |
        @Html.ActionLink("Details", "Details", new { id=Model.PrimaryKey }) |
        @Html.ActionLink("Delete", "Delete", new { id=Model.PrimaryKey })
    </td>
</tr>