在嵌套类上使用DropDownList(For)和模型绑定

时间:2014-08-07 16:23:07

标签: c# asp.net-mvc model-binding html.dropdownlistfor

我在我的应用程序中严重依赖EditorTemplates,但是我遇到了一个我似乎无法解决的问题,而没有离开EditorTemplates下拉列表。

考虑这个(视图)模型:

public class CreateStudentViewModel
{
    public DropDownList StudentTypes { get; set; }
    public CreateStudent Command { get; set; }
}

public class DropDownList {
    public string SelectedValue { get; set; }
    public IList<SelectListItem> Items { get; set; }
}

public class CreateStudent {
    public string Name { get; set; }
    public int StudentTypeId { get; set; }
}

我使用它为前端用户提供了一种设置学生类型的方法,这是通过以下EditorTemplate完成的:

@model DropDownList
<div class="form-group@(Html.ValidationErrorFor(m => m.SelectedValue, " has-error"))">
    @Html.LabelFor(m => m)
    @Html.DropDownListFor(m => m.SelectedValue, Model.Items)
    @Html.ValidationMessageFor(m => m.SelectedValue, null)
</div>

在我的观点中使用:

@Html.EditorFor(m => m.StudentTypes)

现在这个EditorTemplate绑定到StudentTypes.SelectedValue上的DropDownList,这在某些情况下很好 - 但是我需要将此绑定到我的Model.Command.StudentTypeId

我知道我可以将所有这些代码直接移到视图中并直接绑定它,而不是将它放在EditorTemplate中,但我会尽力避免这种情况。

理想情况下,我正在考虑扩展EditorFor以提供类似的方式:

@Html.EditorFor(m => m.StudentTypes, new { selectedValue = Model.Command.StudentTypeId });

但我似乎无法将其转化为:

@Html.DropDownList(@ViewBag.selectedValue.ToString(), Model.Items);

因为这只是将值(int)作为字段名称。欢迎任何建议! : - )

1 个答案:

答案 0 :(得分:1)

这里的主要问题是将下拉列表封装在一个类中,以便依赖于C#类型编辑器模板约定。相反,只需直接使用您的模型并使用UIHint告诉Razor使用特定模板。这是我使用的简化版本:

查看模型

[UIHint("Choice")]
public int SelectedFoo { get; set; }

public IEnumerable<SelectListItem> FooChoices { get; set; }

<强>视图\共享\ EditorTemplates \ Choice.cshtml

@{
    var choices = ViewData["choices"] as IEnumerable<SelectListItem> ?? new List<SelectListItem>();

    if (typeof(System.Collections.IEnumerable).IsAssignableFrom(ViewData.ModelMetadata.ModelType) && ViewData.ModelMetadata.ModelType != typeof(string))
    {
        @Html.ListBox("", choices)
    }
    else
    {
        @Html.DropDownList("", choices)
    }
}

查看

@Html.EditorFor(m => m.SelectedFoo, new { choices = Model.FooChoices })

如果不明显,编辑器模板中的条件将确定属性是值还是列表类型,并分别使用下拉列表控件或列表框控件。