避免在 ASP.NET MVC 中重复查看代码
Avoiding Repetitive View Code in ASP.NET MVC
这适用于 Razor 视图中的 ASP.NET MVC 4 应用程序。我正在将模型传递给局部视图,并尝试遍历模型中包含的给定属性列表以显示为 table.
给定类似 List<string> propertyNames
的内容,在此 table 中,我想输出 DisplayNameFor
和 属性 的值,如下所示:
<tr>
<th>@Html.DisplayNameFor(Model.property)</th>
<td>@Model.property</td>
</tr>
我必须在部分中执行几次此操作,因为不同的属性对应于部分中不同的 div
元素,其中将插入不同的 table,因此我创建了一个帮手,这就是我挂断电话的地方。首先,我知道如何做到这一点的唯一方法是反射,而且我读到反射很昂贵,尤其是一次只做一个属性。另外,使用这种方法,我无法使 @Html.DisplayNameFor
正常工作,因为使用反射,我不太了解语法:
@helper IterateDetailPropertyNames(List<string> propertyNames) {
foreach (var property in propertyNames)
{
<tr>
<th>
@Html.DisplayNameFor(m => m.GetType().GetProperty(property).GetValue(Model, null));
@*Error: Templates can be used only with field access, property access...*@
</th>
<td>
@Model.GetType().GetProperty(property).GetValue(Model, null)
</td>
</tr>
}
}
我怎样才能使它工作并改进它?
模型 ModelMetadata
为您提供生成 table 所需的数据。除了 DisplayName
、DisplayFormatString
、NullDisplayText
等属性之外,它还包含模型值,这些属性是根据应用于您的属性的注释确定的。
有关 ModelMetadata
的更多信息,请参阅 documentation and ASP.NET MVC 2 Templates, Part 2: ModelMetadata。
要生成您的 table,您可以编写以下 HtmlHelper
扩展方法
public static class TableHelper
{
public static MvcHtmlString DisplayTableFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
{
// Get the ModelMetadata for the model
ModelMetadata metaData = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);
StringBuilder html = new StringBuilder();
// Loop through the ModelMetadata of each property in the model
foreach (ModelMetadata property in metaData.Properties)
{
var x = metaData.DisplayFormatString;
string label = property.DisplayName;
string value = null;
if (property.Model == null)
{
value = metaData.NullDisplayText;
}
else if (metaData.DisplayFormatString != null)
{
value = string.Format(metaData.DisplayFormatString, property.Model);
}
else
{
value = property.Model.ToString();
}
TagBuilder labelCell = new TagBuilder("td");
labelCell.InnerHtml = label;
TagBuilder valueCell = new TagBuilder("td");
valueCell.InnerHtml = value;
StringBuilder innerHtml = new StringBuilder();
innerHtml.Append(labelCell.ToString());
innerHtml.Append(valueCell.ToString());
TagBuilder row = new TagBuilder("tr");
row.InnerHtml = innerHtml.ToString();
html.Append(row.ToString());
}
TagBuilder table = new TagBuilder("table");
table.InnerHtml = html.ToString();
return new MvcHtmlString(table.ToString());
}
}
并在视图中
@using YourAssembly.TableHelper
....
@Html.DisplayTableFor(m => m)
您还可以将程序集包含在 web.config
文件中,这样视图中就不需要 @using
语句
作为旁注,<table>
元素用于表格数据,不应用于布局。而是考虑使用样式 <div>
元素
这适用于 Razor 视图中的 ASP.NET MVC 4 应用程序。我正在将模型传递给局部视图,并尝试遍历模型中包含的给定属性列表以显示为 table.
给定类似 List<string> propertyNames
的内容,在此 table 中,我想输出 DisplayNameFor
和 属性 的值,如下所示:
<tr>
<th>@Html.DisplayNameFor(Model.property)</th>
<td>@Model.property</td>
</tr>
我必须在部分中执行几次此操作,因为不同的属性对应于部分中不同的 div
元素,其中将插入不同的 table,因此我创建了一个帮手,这就是我挂断电话的地方。首先,我知道如何做到这一点的唯一方法是反射,而且我读到反射很昂贵,尤其是一次只做一个属性。另外,使用这种方法,我无法使 @Html.DisplayNameFor
正常工作,因为使用反射,我不太了解语法:
@helper IterateDetailPropertyNames(List<string> propertyNames) {
foreach (var property in propertyNames)
{
<tr>
<th>
@Html.DisplayNameFor(m => m.GetType().GetProperty(property).GetValue(Model, null));
@*Error: Templates can be used only with field access, property access...*@
</th>
<td>
@Model.GetType().GetProperty(property).GetValue(Model, null)
</td>
</tr>
}
}
我怎样才能使它工作并改进它?
模型 ModelMetadata
为您提供生成 table 所需的数据。除了 DisplayName
、DisplayFormatString
、NullDisplayText
等属性之外,它还包含模型值,这些属性是根据应用于您的属性的注释确定的。
有关 ModelMetadata
的更多信息,请参阅 documentation and ASP.NET MVC 2 Templates, Part 2: ModelMetadata。
要生成您的 table,您可以编写以下 HtmlHelper
扩展方法
public static class TableHelper
{
public static MvcHtmlString DisplayTableFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
{
// Get the ModelMetadata for the model
ModelMetadata metaData = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);
StringBuilder html = new StringBuilder();
// Loop through the ModelMetadata of each property in the model
foreach (ModelMetadata property in metaData.Properties)
{
var x = metaData.DisplayFormatString;
string label = property.DisplayName;
string value = null;
if (property.Model == null)
{
value = metaData.NullDisplayText;
}
else if (metaData.DisplayFormatString != null)
{
value = string.Format(metaData.DisplayFormatString, property.Model);
}
else
{
value = property.Model.ToString();
}
TagBuilder labelCell = new TagBuilder("td");
labelCell.InnerHtml = label;
TagBuilder valueCell = new TagBuilder("td");
valueCell.InnerHtml = value;
StringBuilder innerHtml = new StringBuilder();
innerHtml.Append(labelCell.ToString());
innerHtml.Append(valueCell.ToString());
TagBuilder row = new TagBuilder("tr");
row.InnerHtml = innerHtml.ToString();
html.Append(row.ToString());
}
TagBuilder table = new TagBuilder("table");
table.InnerHtml = html.ToString();
return new MvcHtmlString(table.ToString());
}
}
并在视图中
@using YourAssembly.TableHelper
....
@Html.DisplayTableFor(m => m)
您还可以将程序集包含在 web.config
文件中,这样视图中就不需要 @using
语句
作为旁注,<table>
元素用于表格数据,不应用于布局。而是考虑使用样式 <div>
元素