带有EditorTemplate的MVC DropDownList将选定值和无效名称字段显示为propertyName.propertyName

时间:2013-10-04 16:45:40

标签: c# html asp.net-mvc mvc-editor-templates

我有一个通过EditorTemplate呈现的下拉列表。该属性在Validation类中具有UIHints并正确显示,但是当我查看HTML时,控件的名称是PropertyType.PropertyName而不仅仅是PropertyName。

这可以防止模型绑定。

我也无法将选定的值返回给View。

我该如何解决这个问题?

更新有关详细信息,请参阅下面的答案。

视图模型

public partial class HouseholdEditViewModel
{
    public int householdID { get; set; }
    public int familyID { get; set; }
    public string address { get; set; }
    public HousingTypeDropDownViewModel housingType { get; set; }
    public KeyworkerDropDownViewModel keyworker { get; set; }
    public string attachmentDate { get; set; }
    public bool loneParent { get; set; }
    public string familyPhoneCode { get; set; }
    public string familyPhone { get; set; }
}

DropDown ViewModel

public class HousingTypeDropDownViewModel
{
    public int housingTypeID { get; set; }
    public IEnumerable<SelectListItem> Items { get; set; }
}

EditorTemplate

@model WhatWorks.ViewModels.HousingTypeDropDownViewModel

@Html.DropDownListFor(h => h.housingTypeID, new SelectList(Model.Items, "Value", "Text"))

查看

using (Html.ControlGroupFor(property.Name))
{                    
@Html.Label(property.GetLabel(), new { @class = "control-label" })
 <div class="controls">
         @Html.Editor(property.Name, new { @class = "input-xlarge" })
         @Html.ValidationMessage(property.Name, null, new { @class = "help-inline" })
 </div>
}

HTML

<div class="control-group">
    <label class="control-label" for="Housing_Type">Housing Type</label>                 
    <div class="controls">
        <select data-val="true" data-val-number="The field housingTypeID must be a number." data-val-required="The housingTypeID field is required." id="housingType_housingTypeID" name="housingType.housingTypeID">
            <option value="1">Owner Occupied</option>
            <option value="2">Rented - Social Landlord</option>
        </select>
        <span class="field-validation-valid help-inline" data-valmsg-for="housingType" data-valmsg-replace="true"></span>
    </div>
</div>

1 个答案:

答案 0 :(得分:0)

对此进行了更多的研究,似乎这是按预期工作的。

最简单的解决方法是在EditorTemplate中使用DropDownList而不是DropDownListFor。将name设置为空字符串,Html.Editor仅选取一次属性名称。另请注意Model.Items

SelectList的更改
@model WhatWorks.ViewModels.HousingTypeDropDownViewModel

@Html.DropDownList("", Model.Items)

为了进一步详细说明,我试图在我的ViewModel中使用DropDownListIEnumerable<SelectListItem>,并且正在努力让我的HTML标记正确呈现。部分原因是我的编辑视图需要Selected Value

由于这似乎是一个常见的问题,我稍微修改了这篇文章的标题,并将在这里记录控制器代码 - 这对我有用,可能不是最佳实践... Caveat Emptor < / EM>!

<强> IRepository

public interface IHouseholdRepository : IDisposable
{
    IEnumerable<tHousehold> Get();
    tHousehold GetById(int Id);
    IEnumerable<SelectListItem> AddHousingType();
    IEnumerable<SelectListItem> EditHousingType(int id);
    //etc...

}

<强>存储库

public IEnumerable<SelectListItem> AddHousingType()
{
    var query = from ht in context.tHousingType
                orderby ht.housingType
                select new
                {
                    ht.housingTypeID,
                    ht.housingType
                };

    return query.AsEnumerable()
        .Select(s => new SelectListItem
        {
            Value = s.housingTypeID.ToString(),
            Text = s.housingType
        });
}

public IEnumerable<SelectListItem> EditHousingType(int id)
{
    var housingType = (from h in context.tHousehold
                      where h.householdID == id
                      select new
                          {
                              h.tHousingStatus.FirstOrDefault().housingTypeID
                          }
                      );  

    var query = from ht in context.tHousingType
                orderby ht.housingType
                select new
                {
                    ht.housingTypeID,
                    ht.housingType
                };

    return query.AsEnumerable()
        .Select(s => new SelectListItem
           {
               Value = s.housingTypeID.ToString(),
               Text = s.housingType,
               Selected = (housingType.FirstOrDefault().housingTypeID == s.housingTypeID ? true : false)
           });
}

<强>控制器

    public ActionResult Edit(int id = 0)
    {
        HousingTypeDropDownViewModel housingType = new HousingTypeDropDownViewModel
        {
            Items = _repo.EditHousingType(id)
        };

        HouseholdEditViewModel h = GetUpdate(id);
        //GetUpdate is Automapper code unrelated to the DropDown 

        h.housingTypeID = housingType;

        if (h == null)
        {
            return HttpNotFound();
        }
        return View(h);
    }

上述灵感来自太多SO帖子中提及。谢谢大家,希望这有助于其他人。