65.9K
CodeProject 正在变化。 阅读更多。
Home

Razor 视图的自动下拉列表

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.31/5 (11投票s)

2013年12月29日

CPOL

2分钟阅读

viewsIcon

46184

在 Razor 中使用元数据属性和编辑器模板来创建下拉列表。

引言

本文展示了如何将一个DropDownList元数据属性应用于一个视图模型属性,并让EditorFor HTML 辅助方法渲染一个DropdDownList

背景

我非常喜欢 ASP.NET MVC 中的运行时脚手架。 这就是你使用例如 EditorFor HTML 辅助方法来决定如何为你的视图模型的属性渲染 HTML 元素。 例如,如果一个属性使用 DataType 属性标记,并且该属性指示该属性的 DataTypeDateTime,那么它将自动渲染一个日期选择器。 对于整数属性,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 上收到了一份热情的赞扬。 我已经很久没有写文章了,我认为分享这个会是一个不错的选择。

© . All rights reserved.