【问题标题】:MVC4 Selecting from a List of Items in a viewMVC4 从视图中的项目列表中进行选择
【发布时间】:2013-04-28 18:00:36
【问题描述】:

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

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

    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 视图模型

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

新的 CreateMeal 视图模型:

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(已更新):

@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 个产品。

【问题讨论】:

  • 我看到了很可能是问题所在的潜在错误,但为了给您一个完整的答案,您能否使用 Meal 课程的代码更新您的问题?
  • 您在回发中检查过请求的表单数据吗?它有没有你需要的东西,只是命名与你所期望的不同?
  • @PeteGO 返回表单数据为空
  • 说“我遇到错误”然后不包括该错误是毫无意义的。
  • @Mystere Man - 抱歉正在编辑中。尝试 myMeal.ProductsToInclude.Add(new ProductsToInclude { Product = prod, Include = false});在创建方法中

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


【解决方案1】:

这里有两个基本问题。 (第三,您没有将任何模型传递给视图,但您的视图需要一个 Meal 对象)首先,您发布的模型与渲染的模型不同。因此,当您发布表单时,它不会识别 Meal.Name 对象,因为发布操作需要一个 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>

【讨论】:

  • 在示例中,您有@Html.EditorFor(m => m.ProductsToInclude):我将发送什么模型到创建方法?那会是 ProductsToInclude (pti?) 的列表。 MealName 在那里供用户命名他们正在创建的餐点。本质上,我需要能够根据之前创建的产品创建一顿饭。我如何到达那里是我的绊脚石。
  • @jbolt - 你必须弄清楚这一点。您不应该在 ViewBag 中传递 ProductsToInclude,而是作为视图模型的一部分,它也应该包含 Name 属性。本质上,您的视图模型应该包含您的视图所需的所有信息。您将该视图模型作为您从控制器操作返回的 View() 方法的参数传递给视图。
  • 更新了代码库(见更新)。这是我从一个例子Editor Templetes.
猜你喜欢
  • 2012-04-04
  • 1970-01-01
  • 2016-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-12
  • 1970-01-01
相关资源
最近更新 更多