Razor 视图的自动下拉列表






4.31/5 (11投票s)
在 Razor 中使用元数据属性和编辑器模板来创建下拉列表。
引言
本文展示了如何将一个DropDownList
元数据属性应用于一个视图模型属性,并让EditorFor
HTML 辅助方法渲染一个DropdDownList
。
背景
我非常喜欢 ASP.NET MVC 中的运行时脚手架。 这就是你使用例如 EditorFor HTML 辅助方法来决定如何为你的视图模型的属性渲染 HTML 元素。 例如,如果一个属性使用 DataType
属性标记,并且该属性指示该属性的 DataType
是 DateTime
,那么它将自动渲染一个日期选择器。 对于整数属性,EditorFor
渲染一个 UpDown
微调控件。 如果 EditorFor
可以顺利处理你的所有属性,你可以使用单个 EditorForModel
元素将整个视图模型正确地渲染到视图中。
Using the Code
使用这个系统涉及在你的 MVC 应用程序的几个区域进行新的代码和修改的代码。 它不仅仅是一个库或插件,尽管我计划在版本 2 中使用 Unity 在我修改代码的这些点上。
public class DemoModel
{
[DropDownList("LanguageSelect")]
public int? LanguageId { get; set; }
public SelectList LanguageSelect { get; set; }
}
现在当我使用 Razor 标记 @EditorFor(m => m.LanguageId)
时,我将得到一个从 LanguageSelect
列表中填充的下拉列表。 这是因为 DropDownListAttrbute
类将选择列表名称附加到 LanguageId
模型。
public class DropDownListAttribute : UIHintAttribute, IMetadataAware
{
public DropDownListAttribute(string selectListName) :
base(KnownUiHints.DropDown, KnownPresentationLayers.Mvc, selectListName)
{
SelectListName = selectListName;
}
public string SelectListName { get; set; }
public void OnMetadataCreated(ModelMetadata metadata)
{
var listProp = metadata.ContainerType.GetProperty(SelectListName);
metadata.AdditionalValues[KnowMetadataKeys.SelectListName] = SelectListName;
}
}
我的所有视图模型都继承自 ViewModel
,它提供了一个 SelectListDictionary
属性
private IDictionary<string,> _selectListdictionary;
public virtual IDictionary<string,> SelectListDictionary
{
get
{
if (_selectListdictionary == null)
{
var props = GetType().GetProperties().Where(p => p.PropertyType == typeof(SelectList));
_selectListdictionary = props.ToDictionary
(prop => prop.Name, prop => (SelectList)prop.GetValue(this, null));
}
return _selectListdictionary;
}
}
在我的基础控制器中,我重写了 View
方法,以从视图模型中提取整个选择列表字典,并将其插入到视图的 ViewData 中,使其可用于编辑器模板
protected override ViewResult View(string viewName, string masterName, object model)
{
var result = base.View(viewName, masterName, model);
if ((model is ViewModel) && (!ViewData.ContainsKey(KnowMetadataKeys.ViewDataSelectLists)))
{
var vm = (ViewModel)model;
result.ViewData.Add(KnowMetadataKeys.ViewDataSelectLists, vm.SelectListDictionary);
}
return result;
}
上述编辑器模板
@using Erisia.Constants
@{
var list = (SelectList)ViewData.ModelMetadata.AdditionalValues
[ViewData.ModelMetadata.AdditionalValues[KnowMetadataKeys.SelectListName].ToString()];
var listWithSelected = new SelectList(list.Items, list.DataValueField, list.DataTextField, Model);
}
@Html.DropDownListFor(m => Model, listWithSelected, " - select - ")
备注
可能还有更好的方法来做到这一点,并且在视图模型中填充选择列表可能不太规范,但是这个小“框架”为我在许多项目上节省了大量时间,并且我还在 Code Review beta 上收到了一份热情的赞扬。 我已经很久没有写文章了,我认为分享这个会是一个不错的选择。