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() %>
<% }%>
<%@ 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);
}
}
}
{
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; }
}
{
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;
}
}
{
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;
}
}