ASP.NET MVC4模型的子集合下拉列表没有正确绑定

时间:2014-06-23 18:58:00

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

我相信我遇到了与here相同的问题,但解决方法对我不起作用。 我的问题是我在主视图的ViewModel中有一个子模型集合。它们包含要在两个字段中显示的数据,即下拉列表和密码字段。每个下拉列表选择必须是唯一的。一切都在保存并正确发送到视图,但是当调用视图但密码字段为时,下拉列表不会绑定到选定的值。它们都默认为第一个选择,即使它们要绑定的属性是唯一的,只有一个可以是第一个值。任何帮助或见解表示赞赏。感谢。

以下是我视图中发生问题的部分。我已经评论了我的努力并尝试了上述链接的解决方法无济于事:

@functions {
private IEnumerable<SelectListItem> Mark(IEnumerable<SelectListItem> items, object Id)
{
    foreach (var item in items)
        if (string.CompareOrdinal(item.Value, Convert.ToString(Id)) == 0)
            item.Selected = true;
    return items;
}
}



@for (int j = 0; j < Model.PasswordResetQuestionUserAnswers.Count(); j++)
{
@Html.Hidden("PasswordResetQuestionUserAnswers.Index", j)
@Html.HiddenFor(p => Model.PasswordResetQuestionUserAnswers[j].Id)
@Html.HiddenFor(p => Model.PasswordResetQuestionUserAnswers[j].UserId)
<div class="form-group">
<label class="col-md-2 control-label">Password Reset Question @(j+1)</label>
<div class="col-md-6">
@*@Html.DropDownList("PasswordResetQuestionUserAnswers[" + j + "].PasswordResetQuestionId", Model.PasswordResetQuestionList, new { @class = "form-control passwordQuestion" })*@
@*@Html.DropDownListFor(x => Model.PasswordResetQuestionUserAnswers[j].PasswordResetQuestionId, Model.PasswordResetQuestionList, new { @class = "form-control passwordQuestion" })*@
@Html.DropDownListFor(x => Model.PasswordResetQuestionUserAnswers[j].PasswordResetQuestionId, Mark(Model.PasswordResetQuestionList, Model.PasswordResetQuestionUserAnswers[j].PasswordResetQuestionId))
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">Password Reset Answer @(j+1)</label>
<div class="col-md-6">
@Html.Password("PasswordResetQuestionUserAnswers[" + j + "].Answer", Model.PasswordResetQuestionUserAnswers[j].Answer, new { @class = "form-control passwordQuestionUserAnswer" })
@*@Html.PasswordFor(x => Model.PasswordResetQuestionUserAnswers[j].Answer, new { @class = "form-control passwordQuestionUserAnswer" })*@
</div>
</div>
}

3 个答案:

答案 0 :(得分:3)

我刚遇到同样的问题。这种语法对我有用:

 @Html.DropDownListFor(x => x.ChildCollection[i].ChildID, new SelectList(ViewBag.ChildCollectionSelect as SelectList, "Value", "Text", Model.ChildCollection[i].ChildID))

将SelectList定义为new,然后专门设置模型中的选定值。

答案 1 :(得分:0)

这是对以上示例的改编,适用于类似情况下的工作,其中itm表示集合中的子对象。我不确定该示例中发生的一切-太多的“问题”,“用户”和“答案”,但是请说您是否要删除用户列表,并用特定的已分配给该子项目:

foreach (var itm in Model.PasswordResetQuestionUserAnswers)
{
    @Html.DropDownListFor(modelItem => itm.UserId,
                          new SelectList( (IEnumerable<SelectListItem>)ViewData["users"], "Value", "Text", itm.UserId),
                          htmlAttributes: new { @class = "form-control" }
                        )
}

在呈现视图的Controller方法中,将ViewData["users"]填满的位置:

var usersList = GetUsersList();
ViewData["users"] = usersList;

并具有以下支持功能:

private static SelectListItem[] _UsersList;

/// <summary>
/// Returns a static category list that is cached
/// </summary>
/// <returns></returns>
public SelectListItem[] GetUsersList()
{
    if (_UsersList == null)
    {
        var users = repository.GetAllUsers().Select(a => new SelectListItem()
         {
             Text = a.USER_NAME,
             Value = a.USER_ID.ToString()
         }).ToList();
         users.Insert(0, new SelectListItem() { Value = "0", Text = "-- Please select your user --" });

        _UsersList = users.ToArray();
    }

    // Have to create new instances via projection
    // to avoid ModelBinding updates to affect this
    // globally
    return _UsersList
        .Select(d => new SelectListItem()
    {
         Value = d.Value,
         Text = d.Text
    })
     .ToArray();
}

Repository.cs

上述功能的我的存储库功能GetAllUsers()

Model1 db = new Model1(); // Entity Framework context

// Users
public IList<USERS> GetAllUsers()
{
    return db.USERS.OrderBy(e => e.USER_ID).ToList();
}

Users.cs

public partial class USERS
{
    [Key]
    public int USER_ID { get; set; }

    [Required]
    [StringLength(30)]
    public string USER_NAME { get; set; }
}

修改

重新阅读问题之后,似乎是有关发布密码重置问题的问题。

foreach (var itm in Model.PasswordResetQuestionUserAnswers)
{
    @Html.DropDownListFor(modelItem => itm.PasswordResetQuestionId,
                          new SelectList( (IEnumerable<SelectListItem>)ViewData["pwordResetQuestions"], "Value", "Text", itm.PasswordResetQuestionId),
                          htmlAttributes: new { @class = "form-control" }
                        )
}

在呈现该视图的控制器方法中,您必须像这样填充ViewData["pwordResetQuestions"]

var questionsList = GetQuestionsList();
ViewData["questions"] = questionsList;

以及以下支持功能/对象:

private SelectListItem[] _QuestionsList;
public SelectListItem[] GetQuestionsList()
{
    if (_QuestionsList == null)
    {
        var questions = PasswordResetQuestionUserAnswers.Select(a => new SelectListItem()
        {
            Text = a.Answer, //? I didn't see a "PasswordResetQuestionText" call in your example, so...
            Value = a.PasswordResetQuestionId.ToString()
        }).ToList();
        questions.Insert(1, new SelectListItem() { Value = "1", Text = "Mother's Maiden Name" });
        questions.Insert(2, new SelectListItem() { Value = "2", Text = "Elementary school attended" });

        _QuestionsList = questions.ToArray();
    }

    // Have to create new instances via projection
    // to avoid ModelBinding updates to affect this
    // globally
    return _QuestionsList
         .Select(d => new SelectListItem()
    {
         Value = d.Value,
         Text = d.Text
    })
    .ToArray();
}

我在那里硬编码了一些问题-我有点怀疑您会为他们准备一张表,通常公司只有不到10个表。但是如果它们是使用数据库表-这就是为什么我在此处保留该示例的原因。

答案 2 :(得分:0)

我遇到了同样的问题并与之抗争。上面的示例让我难以理解,但是我可以通过修改后的方式简化使用代码的方式:

原始代码

@Html.DropDownListFor(x => Model.PasswordResetQuestionUserAnswers[j].PasswordResetQuestionId, Model.PasswordResetQuestionList, new { @class = "form-control passwordQuestion" })

更新代码:(用新的SelectList包装)

@Html.DropDownListFor(x => Model.PasswordResetQuestionUserAnswers[j].PasswordResetQuestionId, new SelectList(Model.PasswordResetQuestionList, "Value", "Text", Model.PasswordResetQuestionUserAnswers[j].PasswordResetQuestionId, new { @class = "form-control passwordQuestion" })

这消除了对ViewBag或ViewData的需求。