简体   繁体   English

C#MVC5 @ Html.EnumDropDownListFor在“回发”时丢失选择

[英]C# MVC5 @Html.EnumDropDownListFor loses selection on “postback”

MVC5 EF6 MVC5 EF6

I have a Product. 我有一个产品。 A product can have multiple Titles, A title has a Type which is an Enum. 一个产品可以有多个标题,一个标题的类型是枚举。

I am working on the Create View for a Product - The Model is the Product 我正在为产品创建视图-模型即产品

View: 视图:

            @for (int x = 0; x < Model.ProdTitles.Count; x++)
            {                    
                <tr>
                    <td>
                        @Html.TextBoxFor(model => model.ProdTitles.ToArray()[x].Title, new { @class = "form-control" })
                        @Html.ValidationMessageFor(model => model.ProdTitles.ToArray()[x].Title, "", new { @class = "text-danger" })
                    </td>
                    <td>
                        @Html.EnumDropDownListFor(model => model.ProdTitles.ToArray()[x].TitleTypeID, new { @class = "form-control" })
                    </td>
                    <td>
                        @Html.EnumDropDownListFor(model => model.ProdTitles.ToArray()[x].CultureID, new { @class = "form-control" })
                    </td>
                </tr>
            }

In the Controller - when I create a product to return to the view, I create one title for each title type and add it to the product. 在Controller中-创建产品返回视图时,我为每种标题类型创建一个标题并将其添加到产品中。 The view displays everything as I expect. 该视图显示了我所期望的一切。

按要求工作

When I hit the Create button, the product and the titles are returned to the controller as expected and I validate the titles (different validation depending on the type). 当我按下“创建”按钮时,产品和标题将按预期返回给控制器,并验证标题(根据类型的不同验证)。 I add any errors to the ModelState and therefore, ModelState.IsValid is false. 我将任何错误添加到ModelState,因此,ModelState.IsValid为false。

I return back to the View return View(product); 我返回到View return View(product); Debugging this product, all the titles are in the product and they all still have their correct types but the View now displays the first Enum in the list, for all titles and not the one that is actually in the model! 调试该产品后,所有标题都在产品中,并且它们都仍然具有正确的类型,但是视图现在显示列表中所有标题的第一个Enum,而不是模型中实际存在的Enum!

显示所有标题的第一个枚举

If I change the EnumDropDown to a text box, the correct type is displayed, so the model is definitely correct: 如果将EnumDropDown更改为文本框,则会显示正确的类型,因此该模型绝对正确:

证明模型具有正确的类型

I'm not sure why this is happening and I hope someone can suggest a fix? 我不确定为什么会发生这种情况,希望有人可以提出修复建议? Is it a bug in the EnumDropDownFor? 是EnumDropDownFor中的错误吗? or am I doing something wrong? 还是我做错了什么?

Controller code: 控制器代码:

    public ActionResult Create()
    {
        Product product = new Product();

        foreach (var enm in Utils.Enums.EnumHelper.GetValues<Utils.Enums.TitleType>())
        {
            product.ProdTitles.Add(new ProdTitle()
            {
                CultureID = Utils.Enums.CultureID.English_United_Kingdom,                    
                DateCreated = DateTime.Now,
                Title = "",
                TitleTypeID = enm
            });
        }

        return View(product);
    }


    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "ProdID,DateCreated")] Product product, ICollection<ProdTitle> prodTitles)
    {
        //ensure titles are all valid before saving
        for (int x = 0; x < prodTitles.Count; x++)
        {
            ProdTitle title = prodTitles.ToArray()[x];
            if (!title.IsValid)
            {
                ModelState.AddModelError(string.Empty, title.TitleTypeID + " title is invalid.");
            }
            product.ProdTitles.Add(title);
        }


        if (ModelState.IsValid)
        {
            db.Products.Add(product);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(product);
    }

ProdTitle model ProdTitle模型

public partial class ProdTitle
{
    public long TitleID { get; set; }
    public long ProdID { get; set; }
    public Utils.Enums.TitleType TitleTypeID { get; set; }
    public string Title { get; set; }
    public Utils.Enums.CultureID CultureID { get; set; }
    public System.DateTime DateCreated { get; set; }

    public virtual Product Product { get; set; }
    public virtual DataSource DataSource { get; set; }
}

When dealing with dropdownlist in a collection you need a custom EditorTemplate . 处理集合中的dropdownlist时,需要自定义EditorTemplate

In /Views/Shared/EditorTemplates/ProdTitle.cshtml /Views/Shared/EditorTemplates/ProdTitle.cshtml

@model yourAssembly.ProdTitle

<tr>
  <td>
    @Html.TextBoxFor(m => m.Title, new { @class = "form-control" })
    @Html.ValidationMessageFor(m => m.Title, new { @class = "text-danger" })
  </td>
  <td>
    @Html.EnumDropDownListFor(m => m.TitleTypeID, new { @class = "form-control" })
  </td>
  <td>
    @Html.EnumDropDownListFor(m => m.CultureID, new { @class = "form-control" })
  </td>
</tr>

Then in the main view 然后在主视图中

@model yourAssembly.Product
@using(Html.BeginForm())
{
  .... // other controls for properties of Product
  @Html.EditorFor(m => m.ProdTitles) // not in a loop!
}

and then modify the controller to 然后将控制器修改为

public ActionResult Create(Product product)

Note: Your current [Bind] attributes excludes the ProdTitle property from binding, and in any case you should be using view models to represent only what you want to display/edit 注意:您当前的[Bind]属性从绑定中排除了ProdTitle属性,在任何情况下,您都应使用视图模型仅表示要显示/编辑的内容

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM