asp.net mvc 2 给我们提供了强大的自定义功能,今天主要说下DropdownList自定义绑定字段显示,通过ViewData设定DropdownList的数据项。自动绑定显示。实现的方式。在global.asax 中注册 FieldTemplateMetadataProvider,
- ModelMetadataProviders.Current = new mvc.Models.FieldTemplateMetadataProvider();
通过返回的 FieldTemplateMetadata 。在MetaData中指定使用DropDownList的字段
- [Display( Name="",Order=12)]
- [Required]
- [SearchFilter]
- [DisplayName("栏目")]
- [DropDownList("Category", "Id", "Name")]
- public int Cid { get; set; }
通过DropDownList指定调用的模板为dropdownlist.ascx ,在dropdownlist.ascx 将默认的 ModelMetadata 转成FieldTemplateMetadata 获取 DropDownListAttribute 。
- <script runat="server">
- DropDownListAttribute GetDropDownListAttribute()
- {
- FieldTemplateMetadata metaData = ViewData.ModelMetadata as FieldTemplateMetadata;
- return (metaData != null) ? metaData.Attributes.OfType<DropDownListAttribute>().SingleOrDefault() : null;
- }
- </script>
通过DropDownListAttribute 获得 ViewData的key ,绑定的文本对应的字段,值对应的字段,使用html.DropDownlist显示数据
DropdownList.ascx 代码
- <%@ Import Namespace="mvc.Models"%>
- <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
- <script runat="server">
- DropDownListAttribute GetDropDownListAttribute()
- {
- FieldTemplateMetadata metaData = ViewData.ModelMetadata as FieldTemplateMetadata;
- return (metaData != null) ? metaData.Attributes.OfType<DropDownListAttribute>().SingleOrDefault() : null;
- }
- </script>
- <% DropDownListAttribute attribute = GetDropDownListAttribute();%>
- <% if (attribute != null) {%>
- <%= Html.DropDownList(string.Empty, new SelectList(ViewData[attribute.ViewDataKey] as IEnumerable, attribute.DataValueField, attribute.DataTextField, Model), attribute.OptionLabel, attribute.HtmlAttributes) %>
- <% }%>
- <% else {%>
- <%= Html.DisplayForModel() %>
- <% }%>
自定义DropDownListAttribute 属性
- namespace mvc.Models
- {
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.ComponentModel.DataAnnotations;
- using System.Linq;
- using System.Web.Routing;
- [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
- public sealed class DropDownListAttribute : Attribute, ITemplateField
- {
- private static string defaultTemplateName;
- public DropDownListAttribute(string viewDataKey, string dataValueField) : this(viewDataKey, dataValueField, null)
- {
- }
- public DropDownListAttribute(string viewDataKey, string dataValueField, string dataTextField) : this(viewDataKey, dataValueField, dataTextField, null)
- {
- }
- public DropDownListAttribute(string viewDataKey, string dataValueField, string dataTextField, string optionLabel) : this(DefaultTemplateName, viewDataKey, dataValueField, dataTextField, optionLabel, null)
- {
- }
- public DropDownListAttribute(string viewDataKey, string dataValueField, string dataTextField, string optionLabel, object htmlAttributes) : this(DefaultTemplateName, viewDataKey, dataValueField, dataTextField, optionLabel, htmlAttributes)
- {
- }
- public DropDownListAttribute(string templateName, string viewDataKey, string dataValueField, string dataTextField, string optionLabel, object htmlAttributes)
- {
- if (string.IsNullOrEmpty(templateName))
- {
- throw new ArgumentException("Template name cannot be empty.");
- }
- if (string.IsNullOrEmpty(viewDataKey))
- {
- throw new ArgumentException("View data key cannot be empty.");
- }
- if (string.IsNullOrEmpty(dataValueField))
- {
- throw new ArgumentException("Data value field cannot be empty.");
- }
- TemplateName = templateName;
- ViewDataKey = viewDataKey;
- DataValueField = dataValueField;
- DataTextField = dataTextField;
- OptionLabel = optionLabel;
- HtmlAttributes = new RouteValueDictionary(htmlAttributes);
- }
- public static string DefaultTemplateName
- {
- get
- {
- if (string.IsNullOrEmpty(defaultTemplateName))
- {
- defaultTemplateName = "DropDownList";
- }
- return defaultTemplateName;
- }
- set
- {
- defaultTemplateName = value;
- }
- }
- public string TemplateName { get; private set; }
- public string ViewDataKey { get; private set; }
- public string DataValueField { get; private set; }
- public string DataTextField { get; private set; }
- public string OptionLabel { get; private set; }
- public IDictionary<string, object> HtmlAttributes { get; private set; }
- public object GetSelectedValue(object model)
- {
- return GetPropertyValue(model, DataValueField);
- }
- public object GetSelectedText(object model)
- {
- return GetPropertyValue(model, !string.IsNullOrEmpty(DataTextField) ? DataTextField : DataValueField);
- }
- private static object GetPropertyValue(object model, string propertyName)
- {
- if (model != null)
- {
- PropertyDescriptor property = GetTypeDescriptor(model.GetType()).GetProperties()
- .Cast<PropertyDescriptor>()
- .SingleOrDefault(p => string.Compare(p.Name, propertyName, StringComparison.OrdinalIgnoreCase) == 0);
- if (property != null)
- {
- return property.GetValue(model);
- }
- }
- return null;
- }
- private static ICustomTypeDescriptor GetTypeDescriptor(Type type)
- {
- return new AssociatedMetadataTypeTypeDescriptionProvider(type).GetTypeDescriptor(type);
- }
- }
- }
自定义DataAnnotationsModelMetadata
- public class FieldTemplateMetadata : DataAnnotationsModelMetadata
- {
- public FieldTemplateMetadata(DisplayAttribute aa, DataAnnotationsModelMetadataProvider provider, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName, DisplayColumnAttribute displayColumnAttribute, IEnumerable<Attribute> attributes) : base(provider, containerType, modelAccessor, modelType, propertyName, displayColumnAttribute)
- {
- Attributes = new List<Attribute>(attributes);
- Display = aa;
- }
- public IList<Attribute> Attributes
- {
- get;
- private set;
- }
- public DisplayAttribute Display { get; set; }
- }
自定义 DataAnnotationsModelMetadataProvider
- public class FieldTemplateMetadataProvider : DataAnnotationsModelMetadataProvider
- {
- protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
- {
- DataAnnotationsModelMetadata result = (DataAnnotationsModelMetadata) base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
- string templateName = attributes.OfType<ITemplateField>()
- .Select(field => field.TemplateName)
- .LastOrDefault();
- List<System.Attribute> attributeList = new List<System.Attribute>(attributes);
- DisplayAttribute disp = attributeList.OfType<DisplayAttribute>().FirstOrDefault();
- if (disp != null)
- {
- result.ShortDisplayName = disp.Order.ToString(); ;
- result.Description = disp.Description;
- }
- var data= (new FieldTemplateMetadata(disp, this, containerType, modelAccessor, modelType, propertyName, attributes.OfType<DisplayColumnAttribute>().FirstOrDefault(), attributes)
- {
- TemplateHint = !string.IsNullOrEmpty(templateName) ? templateName : result.TemplateHint,
- HideSurroundingHtml = result.HideSurroundingHtml,
- DataTypeName = result.DataTypeName,
- IsReadOnly = result.IsReadOnly,
- NullDisplayText = result.NullDisplayText,
- DisplayFormatString = result.DisplayFormatString,
- ConvertEmptyStringToNull = result.ConvertEmptyStringToNull,
- EditFormatString = result.EditFormatString,
- ShowForDisplay = result.ShowForDisplay,
- ShowForEdit = result.ShowForEdit,
- DisplayName = result.DisplayName,
- Description = result.Description,
- ShortDisplayName = result.ShortDisplayName,
- });
- SearchFilterAttribute searchFilterAttribute = attributes.OfType<SearchFilterAttribute>().FirstOrDefault();
- if (searchFilterAttribute != null)
- {
- data.AdditionalValues.Add("Search", searchFilterAttribute);
- }
- OrderByAttribute orderByAttribute = attributes.OfType<OrderByAttribute>().FirstOrDefault();
- if (orderByAttribute != null)
- {
- data.AdditionalValues.Add("OrderBy", orderByAttribute);
- }
- return data;
- }
- }