自定义MVC HtmlHelper,使用已有的HtmlHelper with Expressions
本文关键字:HtmlHelper with Expressions MVC 自定义 | 更新日期: 2023-09-27 18:12:22
我正在尝试制作一个自定义HtmlHelper,它将在现有HtmlHelper的帮助下生成多个HTML元素,如Html.TextBoxFor
和Html.LabelFor
。我遇到的主要问题是,我不能创建表达式由这些现有的助手使用,除非他们都传递到我的自定义HtmlHelper单独。我希望能够将整个模型传递给自定义HtmlHelper,并创建helper内部的表达式,并将它们传递给现有的表达式。我试图这样做,希望属性仍然可以工作,例如DisplayName的Required和国际化。这可能吗?
我知道我可以通过表达式将每个Address属性传递到自定义HtmlHelper中,但是感觉不像在helper中那样干净和容易使用。
地址模型public class Address
{
[Required(ErrorMessage = "Required"), DisplayName("First Name")]
public String FirstName { get; set; }
[Required(ErrorMessage = "Required"), DisplayName("Last Name")]
public String LastName { get; set; }
[Required(ErrorMessage = "Required"), DisplayName("Line 1")]
public String Line1 { get; set; }
[Required(ErrorMessage = "Required"), DisplayName("Line 2")]
public String Line2 { get; set; }
[Required(ErrorMessage = "Required"), DisplayName("City")]
public String City { get; set; }
[Required(ErrorMessage = "Required"), DisplayName("State")]
public String State { get; set; }
[Required(ErrorMessage = "Required"), DisplayName("Country")]
public String Country { get; set; }
[Required(ErrorMessage = "Required"), DisplayName("Postal Code")]
public String PostalCode { get; set; }
}
定制HtmlHelper public static class AddressExtension
{
public static MvcHtmlString AddressEditorForModel<TModel>(this HtmlHelper<TModel> helper, Address address, String prefix, Boolean showLabels)
{
// There will be more markup in here, this is just slimmed down..
StringBuilder sb = new StringBuilder();
sb.AppendLine(String.Format("<div id='{0}_AddressContainer' >", prefix));
// First Name
if (showLabels)
sb.AppendLine(helper.DisplayFor(????).ToString());
sb.AppendLine(helper.EditorFor(????).ToString());
// Last Name
if (showLabels)
sb.AppendLine(helper.DisplayFor(????).ToString());
sb.AppendLine(helper.EditorFor(????).ToString());
// Line 1
if (showLabels)
sb.AppendLine(helper.DisplayFor(????).ToString());
sb.AppendLine(helper.EditorFor(????).ToString());
// Line 2
if (showLabels)
sb.AppendLine(helper.DisplayFor(????).ToString());
sb.AppendLine(helper.EditorFor(????).ToString());
// City
if (showLabels)
sb.AppendLine(helper.DisplayFor(????).ToString());
sb.AppendLine(helper.EditorFor(????).ToString());
// State
if (showLabels)
sb.AppendLine(helper.DisplayFor(????).ToString());
sb.AppendLine(helper.EditorFor(????).ToString());
// Country
if (showLabels)
sb.AppendLine(helper.DisplayFor(????).ToString());
sb.AppendLine(helper.EditorFor(????).ToString());
// Postal Code
if (showLabels)
sb.AppendLine(helper.DisplayFor(????).ToString());
sb.AppendLine(helper.EditorFor(????).ToString());
sb.AppendLine("</div>");
return MvcHtmlString.Create(sb.ToString());
}
视图(cshtml)
@Html.AddressEditorForModel(Model, "test", true)
您可以通过如下方式使用反射和表达式树:
public static MvcHtmlString AddressEditorForModel<TModel>(this HtmlHelper<TModel> helper, string prefix, bool showLabels)
{
// There will be more markup in here, this is just slimmed down..
StringBuilder sb = new StringBuilder();
sb.AppendLine(String.Format("<div id='{0}_AddressContainer' >", prefix));
//Create a parameter expression for the model type
ParameterExpression paramExpr = Expression.Parameter(typeof (TModel));
//Loop through the properties you want to create a DisplayFor for
foreach (var property in typeof (TModel).GetProperties())
{
//Create a member access expression for accessing this property
MemberExpression propertyAccess = Expression.MakeMemberAccess(paramExpr, property);
//Create the lambda expression (eg. "x => x.Name")
var lambdaExpr = Expression.Lambda<Func<TModel, string>>(propertyAccess, paramExpr);
//Pass this lambda to the DisplayFor method
sb.AppendLine(helper.DisplayFor(lambdaExpr).ToString());
}
...rest of your method
然而,这假设TModel是你的Address对象,所以你也不需要传递它。HTML helper中的TModel来自强类型视图,所以如果你有一个视图,其中@model类型是Address,那么你可以使用上面的方法
视图会这样使用它:
@model Address
@Html.AddressEditorForModel("prefix", true)