我正在尝试制作一个自定义HtmlHelper,它将在Html.TextBoxFor
和Html.LabelFor
等现有HtmlHelper的帮助下生成多个HTML元素。我遇到的主要问题是我无法创建表达式以供这些现有帮助程序使用,除非它们都单独传递到我的自定义HtmlHelper中。我希望能够将整个模型传递给自定义HtmlHelper并在帮助程序内部创建表达式并将它们传递给现有模型。我试图这样做,希望属性仍然有效,例如DisplayName的Required和国际化。这可能吗?
我知道我可以通过将每个Address属性传递到自定义HtmlHelper表达式来实现它,但它并不像在帮助程序中完成它那样干净且易于使用。
地址模型
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)
答案 0 :(得分:1)
您可以使用这样的反射和表达式树来执行此操作:
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 是您的地址对象,因此您也不需要将其传入。 TModel 在HTML帮助器中来自强类型视图,因此如果你有一个@model类型是地址的视图,那么你可以使用上面的方法
视图会像这样使用它:
@model Address
@Html.AddressEditorForModel("prefix", true)