2014-09-25 24 views
0

我有一个MVC 5应用程序,我使用的for循环,所以我可以绑定一个集合时传回控制器。这适用于我所有的属性,除了基于DropDownFor类型的属性。MVC枚举模型绑定在For循环

的问题是该属性的名称没有设置成“产品[0] .TypeOfSubscription

我试图3种不同的方式:该第一2方法最终获得的名称[0] .TypeOfSubscription和第三个具有正确名称的产品[0] .TypeOfSubscription,但没有绑定发生时,我将它传回控制器。

我认为问题是第三个选项是绑定,但因为它隐藏它没有得到分配的选定值。

@Html.EnumDropDownListFor(modelItem => Model[i].TypeOfSubscription) 

@Html.EnumDropDownListFor(modelItem => Model[i].TypeOfSubscription, 
              new { name = "product[" + @i + "].TypeOfSubscription"}) 

@Html.Hidden("product[" + @i + "].TypeOfSubscription", 
              Model[i].TypeOfSubscription) 

型号

public class VmStoreProducts 
    { 
     public VmStoreProducts() 
     { 
      NoOfUsers = 1; 
     } 

     public enum SubscriptionType 
     { 
      Monthly, 
      Annual 

     } 
     public int MojitoProductId { get; set; } 
     [Display(Name = "Category")] 
     public string ProductCategory { get; set; } 
     public virtual string Name { get; set; } 
     public string Description { get; set; } 
     [Display(Name = "Image")] 
     public byte[] ImageData { get; set; } 
     [Display(Name = "Type of Subscription")] 
     public SubscriptionType TypeOfSubscription { get; set; } 
     public decimal Price { get; set; } 
     [Display(Name = "No. of Users")] 
     public int NoOfUsers { get; set; } 

     [Display(Name = "Total Price")] 
     [DisplayFormat(DataFormatString = "{0:C}")] 
     public decimal TotalPrice { get; set; } 


    } 

For循环 - 查看

@model PagedList.IPagedList<VmStoreProducts> 
@using Mojito.Domain 
@using PagedList.Mvc; 
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" /> 
@{ 
    ViewBag.Title = "Index"; 
    Layout = "~/Views/Shared/_Layout.cshtml"; 
} 

<h2>Mojito Products</h2> 
<div class="col-md-9"></div> 
<div class="col-md-3"> 
    @using (Html.BeginForm("Index", "MojitoProducts", FormMethod.Get)) 
    { 
     <p> 
      @Html.TextBox("SearchString", ViewBag.CurrentFilter as string) 
      <input type="submit" value="Search" /> 
     </p> 
    } 
</div> 
@using (Html.BeginForm("AddToCart", "ShoppingCart", FormMethod.Post)) 
{ 
    <table class="table"> 
     <tr> 
      <th> 
       @Html.DisplayNameFor(model => model.FirstOrDefault().ImageData) 
      </th> 
      <th> 
       @Html.ActionLink("Category", "Index", new { sortOrder = ViewBag.SortByCategory, currentFilter = ViewBag.CurrentFilter }) 
      </th> 
      <th> 
       @Html.ActionLink("Product", "Index", new { sortOrder = ViewBag.SortByProduct, currentFilter = ViewBag.CurrentFilter }) 
      </th> 
      <th> 
       @Html.DisplayNameFor(model => model.FirstOrDefault().Description) 
      </th> 
      <th> 
       @Html.DisplayNameFor(model => model.FirstOrDefault().TypeOfSubscription) 
      </th> 
      <th> 
       @Html.ActionLink("Price", "Index", new { sortOrder = ViewBag.SortByPrice, currentFilter = ViewBag.CurrentFilter }) 
      </th> 
      <th> 
       @Html.DisplayNameFor(model => model.FirstOrDefault().NoOfUsers) 
      </th> 
      <th> 
       @Html.DisplayNameFor(model => model.FirstOrDefault().TotalPrice) 
      </th> 

      <th></th> 
     </tr> 

     @for (int i = 0; i < Model.Count; i++) 
     { 

      <tr> 
       <td> 
        @if (Model[i].ImageData != null) 
        { 
         <div class="pull-left" style="margin-right: 10px"> 
          <img class="img-thumbnail" width="75" height="75" 
           src="@Url.Action("GetImage", "MojitoProducts", 
              new { Model[i].MojitoProductId })" /> 
         </div> 
        } 
       </td> 
       <td> 
        @Html.DisplayFor(modelItem => Model[i].ProductCategory) 
       </td> 
       <td> 
        @Html.TextBox("product[" + @i + "].Name", 
           Model[i].Name, new { @readonly = "readonly" }) 
       </td> 
       <td> 
        @Html.DisplayFor(modelItem => Model[i].Description) 
       </td> 
       <td> 
        @Html.EnumDropDownListFor(modelItem => Model[i].TypeOfSubscription) 

        @Html.EnumDropDownListFor(modelItem => Model[i].TypeOfSubscription, 
              new { name = "product[" + @i + "].TypeOfSubscription"}) 

        @Html.TextBox("product[" + @i + "].TypeOfSubscription", 
             Model[i].TypeOfSubscription, new { hidden=true }) 
       </td> 
       <td> 
        @Html.TextBox("product[" + @i + "].Price", 
         Model[i].Price, new { @readonly = "readonly", style = "width:50px" }) 
       </td> 
       <td> 
        @Html.TextBox("product[" + @i + "].NoOfUsers", 
         Model[i].NoOfUsers, new { type = "number", min = "0", style = "width:50px" }) 
       </td> 
       <td> 
        @Html.TextBox("product[" + @i + "].TotalPrice", 
         Model[i].TotalPrice, new { style = "width:50px" }) 
       </td> 
       <td> 
        <div class="pull-right"> 
         @if (Request.Url != null) 
         { 
          @Html.Hidden("product[" + @i + "].MojitoProductId", 
             Model[i].MojitoProductId) 
          @Html.Hidden("returnUrl", Request.Url.PathAndQuery) 
         } 

        </div> 

       </td> 
      </tr> 
     } 
     <tr> 
      <td colspan="6"> 
       <div class="pull-right"> 
        <input type="submit" class="btn btn-success" value="Add to cart" /> 
       </div> 
      </td> 
     </tr> 



    </table> 

} 

控制器方法

public ActionResult AddToCart(List<VmStoreProducts> product, string returnUrl) 
     { 
      ShoppingCart cartObjects = (Session["CartObjects"] as ShoppingCart) ?? new ShoppingCart(); 
      Session["CartObjects"] = cartObjects; 

      foreach (var item in product) 
      { 
       if (item.NoOfUsers > 0) 
       { 
        cartObjects.AddItem(item); 
       } 

      } 

      return RedirectToAction("Index", new { returnUrl }); 
     } 
+0

第一个是正确的用法(第二个是毫无意义的你不能重写'name'属性,第三个没有任何意义 - 它只会回传初始值)。 name属性将是'[0] .TypeOfSubscription',因为那是你绑定的属性的名称。请张贴您的模型和'for'循环 – 2014-09-25 07:23:22

+0

我已经发布了模型和视图for for循环。我正在考虑用Jquery编写一些东西,以便在枚举值更改时更新隐藏文本框的值。我相信这会起作用,但不知道这是否是最佳做法。 – ccocker 2014-09-25 08:00:25

回答

1

移动枚举的定义VmStoreProducts

public enum SubscriptionType 
{ 
    Monthly, 
    Annual 
} 

public class VmStoreProducts 
{ 
    public VmStoreProducts() 
    { 
    NoOfUsers = 1; 
    } 
    public int MojitoProductId { get; set; } 
    .... 
} 

for循环将命名选择外

[0].TypeOfSubscription 
[1].TypeOfSubscription 
.... 

它将在回发上正确绑定(假设您的操作方法是public ActionResult AddToCart(IEnumerable<VmStoreProducts> products) {...

另外,请勿使用

@Html.TextBox("product[" + @i + "].Name", Model[i].Name, new { @readonly = "readonly" }) 

既然你已经使用了隐藏的输入似乎更适合在同一物业的DisplayFor,所以

@Html.HiddenFor(m => m[i].Name) 

,或者如果你想显示两次

@Html.TextBoxFor(m => m[i].Name, new { @readonly = "readonly" }) 

这适用于其他属性以及

+0

这就是我最初尝试过的,我改变了我当前的方法,因为没有发生模型绑定。我还添加了我的控制器方法以及 – ccocker 2014-09-25 12:13:28

+0

我已经显示的将绑定到控制器中的List 。注意'name'属性必须是'[0] .Name','[0] .TypeOfSubscription','[1] .Name','[1] .TypeOfSubscription'等等(不是'product [0] .Name' )否则它不会绑定 – 2014-09-25 12:25:54

+0

名称属性与我的模型完全相同,即名称,TypeOfSubscription等。如果我把@ Html.TextBox(“product [”+ @i +“] .Name”, Model [i] .Name)它绑定,如果我把@ Html.HiddenFor(m => m [i] .Name)它不 – ccocker 2014-09-25 12:27:12

-1

在DropDownListFor的情况下,当数据被调回控制器,选择的值丢失,所以我们需要有一个隐藏的文本框来保持选定的值

0

试试你唱一个文本框和隐藏它坚持的价值或使用他人的财产数据 -