【发布时间】:2012-06-27 17:43:02
【问题描述】:
如何创建 HTML Helper 来扩展 TextBoxFor() 以添加 CSS 样式?
@Html.TextBoxFor(model => model.FirstName, new { @class = "txt" })
【问题讨论】:
标签: asp.net asp.net-mvc asp.net-mvc-3
如何创建 HTML Helper 来扩展 TextBoxFor() 以添加 CSS 样式?
@Html.TextBoxFor(model => model.FirstName, new { @class = "txt" })
【问题讨论】:
标签: asp.net asp.net-mvc asp.net-mvc-3
您只需要在HtmlHelper 上创建一个extension method:
public static class MyHtmlHelpers
{
public static MvcHtmlString MyTextBoxFor<TModel, TProperty>(
this HtmlHelper<TModel> helper,
Expression<Func<TModel, TProperty>> expression)
{
return helper.TextBoxFor(expression, new { @class = "txt" });
}
}
那么在您看来,您可以将其用作:
@Html.MyTextBoxFor(model => model.FirstName)
注意:如果您有意见,请不要忘记@usingMyHtmlHelpers 的命名空间。
【讨论】:
TextBoxFor,问题是默认包含了内置TextBoxFor的命名空间。因此,要使用您的扩展方法,您需要通过静态类MyHtmlHelpers.TextBoxFor(Html, model => model.FirstName) 调用,否则编译器无法消除歧义。您可以删除默认命名空间包含,但调用内置帮助程序会出现问题。
public static System.Web.Mvc.MvcHtmlString DtxTextBoxFor<TModel, TValue>
(this System.Web.Mvc.HtmlHelper<TModel> html,
System.Linq.Expressions.Expression<System.Func<TModel, TValue>> expression,
System.Collections.Generic.IDictionary<string, object> htmlAttributes = null, bool readOnly = false)
{
if (htmlAttributes == null)
{
htmlAttributes =
new System.Collections.Generic.Dictionary<string, object>();
}
System.Web.Mvc.ModelMetadata oModelMetadata =
System.Web.Mvc.ModelMetadata.FromLambdaExpression(expression, html.ViewData);
if (oModelMetadata == null)
{
if (readOnly)
{
if (htmlAttributes.ContainsKey("readonly") == false)
{
htmlAttributes.Add("readonly", "read-only");
}
}
}
else
{
if (htmlAttributes.ContainsKey("placeholder") == false)
{
string strHtmlFieldName =
System.Web.Mvc.ExpressionHelper.GetExpressionText(expression);
string strLabelText =
oModelMetadata.DisplayName ??
oModelMetadata.PropertyName ??
strHtmlFieldName.Split('.').Last();
if (string.IsNullOrEmpty(strLabelText) == false)
{
htmlAttributes.Add("placeholder", strLabelText);
}
}
if ((readOnly) || (oModelMetadata.IsReadOnly))
{
if (htmlAttributes.ContainsKey("readonly") == false)
{
htmlAttributes.Add("readonly", "read-only");
}
}
}
htmlAttributes.Add("class", "form-control");
System.Linq.Expressions.MemberExpression oMemberExpression =
expression.Body as System.Linq.Expressions.MemberExpression;
if (oMemberExpression != null)
{
System.ComponentModel.DataAnnotations.StringLengthAttribute oStringLengthAttribute =
oMemberExpression.Member.GetCustomAttributes
(typeof(System.ComponentModel.DataAnnotations.StringLengthAttribute), false)
.FirstOrDefault() as System.ComponentModel.DataAnnotations.StringLengthAttribute;
if (oStringLengthAttribute != null)
{
if (htmlAttributes.ContainsKey("maxlength") == false)
{
htmlAttributes.Add("maxlength", oStringLengthAttribute.MaximumLength);
}
}
}
return (html.TextBoxFor(expression, htmlAttributes));
}
【讨论】:
在@nemesv 的回答的基础上,这是一个支持带有额外自定义属性的htmlAttributes 的扩展。
vb.net:
<Extension()>
Function MyTextBoxFor(Of TModel, TProperty)(ByVal helper As HtmlHelper(Of TModel), ByVal expression As Expression(Of Func(Of TModel, TProperty)), htmlAttributes As Object) As MvcHtmlString
'copy htmlAttributes object to Dictionary
Dim dicHtmlAttributes As New Dictionary(Of String, Object)
For Each prop in htmlAttributes.GetType().GetProperties()
dicHtmlAttributes.Add(prop.Name,prop.GetValue(htmlAttributes))
Next
'add custom attribute
dicHtmlAttributes.Add("foo","bar")
Return helper.TextBoxFor(expression, dicHtmlAttributes)
End Function
c#:
public static MvcHtmlString MyTextBoxFor<TModel, TProperty>(
this HtmlHelper<TModel> helper,
Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
{
// copy htmlAttributes object to Dictionary
Dictionary<string, object> dicHtmlAttributes = new Dictionary<string, object>();
foreach (var prop in htmlAttributes.GetType().GetProperties())
{
dicHtmlAttributes.Add(prop.Name, prop.GetValue(htmlAttributes));
}
//add custom attribute
dicHtmlAttributes.Add("foo", "bar");
return helper.TextBoxFor(expression, dicHtmlAttributes);
}
【讨论】: