I have a database table with several foreign key fields. When I load a record for editing, there are dropdown lists, created in Razor using @Html.DropDownList
, which correctly display the possible values from the table which the foreign key columns reference. And, because I'm editing a record, if a value has previously been selected from the foreign key table, its ID is in the foreign key column of my primary table, as you'd expect.
However, if the record I'm loading for editing does NOT have a value in one of the foreign key columns - i.e., the value in a column is NULL (and they're all nullable, for reasons beyond my control), the dropdowns by default have the first option selected. Not only is this misleading, because there's no way to know if the option is being displayed because it was previously saved or because it's simply the first option, it also means that when I subsequently save the record, the value of that first option is incorrectly saved to the database.
What I need is for each dropdown list to also include an "Unknown" option, added dynamically (i.e. not in the database), which is selected when the page loads if the underlying foreign key column has a NULL value, and which can be selected by the user if they want to change a previously saved value to NULL.
I have had no trouble adding a value to the dropdowns using jQuery when the page loads, like this:
$("select").prepend("<option value=''>Unknown</option>")
However, when the page loads, even though this new option is successfully added as the first option in the list, it is not selected. The first 'real' option is. And, even though I can force the 'dummy' option to be selected using jQuery, that also selects the dummy option in dropdowns where a real value exists in the database.
This really doesn't seem like something that should be unusual or obscure, and yet I've struggled to find any solutions after an afternoon's Googling. I've tried various things from Stack Overflow which I thought I might be able to make work, but to no avail.
Can anyone suggest a solution? I think adding a 'dummy' option in the controller might be the neatest way, if I could figure out how to. I'm surprised this isn't a very common problem!
The code in my controller which is loading the dropdown lists' values looks like this:
ViewBag.PremisesID = new SelectList(db.Premises, "ID", "StreetName", colicCase.PremisesID);
The corresponding Razor for the dropdown looks like this:
<div class="form-group">
@Html.LabelFor(model => model.PremisesID, htmlAttributes: new { @class = "control-label col-md-4" })
<div class="col-md-8">
@Html.DropDownList("PremisesID", null, htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.PremisesID, "", new { @class = "text-danger" })
</div>
</div>
答案 0 :(得分:2)
此功能已经内置到MVC中,使用了接受DropDownList()
参数的DropDownListFor()
或optionLabel
方法的重载之一,例如
public static MvcHtmlString DropDownList(
this HtmlHelper htmlHelper,
string name,
IEnumerable<SelectListItem> selectList,
string optionLabel,
object htmlAttributes
)
或强类型版
public static MvcHtmlString DropDownListFor<TModel, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression,
IEnumerable<SelectListItem> selectList,
string optionLabel,
object htmlAttributes
)
其中optionLabel
的值将作为第一个选项添加null
值(例如生成<option value="">Unknown</option>
)。
我强烈建议您使用强类型版本,并使用view model使用SelectList
的属性,而不是使用ViewBag
,但无论如何,请勿使用您绑定的属性和ViewBag
属性的名称相同(有关详细信息,请参阅this answer)
您的代码应为
public class MyViewModel
{
....
public int? PremisesID { get; set; }
public IEnumerable<SelectListItem> PremisesList { get; set; }
....
}
和GET方法
var model = new MyViewModel()
{
.... // map properties from the data model
PremisesID = dataModel.PremisesID,
PremisesList = new SelectList(db.Premises, "ID", "StreetName")
};
return View(model);
并在视图中
@Html.DropDownListFor(m => m.PremisesID, Model.PremisesList, "Unknown", new { @class = "form-control" })
如果PremisesID
的值为null
或与ID
表中的Premises
值之一不匹配,则会选择第一个选项。