我需要一个通用的内联帮助器来显示字段。
以下是我目前的情况:
@helper DisplayField(Func<MyModel, string> field)
{
if (string.IsNullOrWhiteSpace(field(Model)) == false)
{
<div class="row"> @field(Model) </div>
}
}
用法:
@DisplayField(m => m.Name)
@DisplayField(m => m.PhoneNumber)
我不知道如何在帮助器中显示Label(DisplayAttribute)。请帮忙。
答案 0 :(得分:7)
在页面顶部,添加for System for System.Linq.Expressions,例如。
@using System.Linq.Expressions
(或在web.config中添加此命名空间)。
然后创建帮助器,它看起来像:
@helper DisplayField(Expression<Func<MyModel, string>> field)
{
@Html.LabelFor(field)
@Html.DisplayFor(field)
}
你可以在那里添加额外的逻辑来检查空值等。你可能最好创建一个HtmlHelper,这样你可以使用泛型类型参数而不是上面的“MyModel”和“string”。当我上次尝试时,无法将内联类型参数添加到内联帮助程序,例如。以下不可能,除非此后添加了此功能:
@helper DisplayField<TModel, TValue>(Expression<Func<TModel, TValue>> field)
{
@Html.LabelFor(field)
@Html.DisplayFor(field)
}
因此,要获得泛型方法,您将使用自定义HtmlHelper。要做到这一点:
创建如下文件:
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
namespace MvcApplication1.HtmlHelpers
{
public static class HtmlHelpers
{
public static MvcHtmlString DisplayFieldFor<TModel, TValue>(
this HtmlHelper<TModel> helper,
Expression<Func<TModel, TValue>> field)
{
var labelString = helper.LabelFor(field);
var displayString = helper.DisplayFor(field);
return MvcHtmlString.Create(
labelString.ToString() +
displayString.ToString());
}
}
}
在您的网页中,使用此类内容的方法是:
@Html.DisplayFieldFor(m => m.Name)
@Html.DisplayFieldFor(m => m.PhoneNumber)
等。您可能需要检查页面上的使用情况,或者将HtmlHelper的名称空间添加到web.config中。
答案 1 :(得分:1)
@ David_001为此提供了一个非常优雅的MVC解决方案;我在这里留下我的答案,因为它描述了内部机制,如果您需要解决MVC开箱即用助手未涵盖的问题,可能会有所帮助。
将参数类型从Func<MyModel, string>
更改为Expression<Func<MyModel, string>>
。这样,您可以在方法中接收动态表达式,而不是在当前表单中收到的静态委托
您可以像这样检索字段的值:
var compExpr = field.Compile();
var value = compExpr.DynamicInvoke(Model);
您可以访问动态表达式返回的成员及其属性,如下所示:
var memberAccExpr = (System.Linq.Expressions.MemberAccessExpression)field.Body;
var attr = (DisplayAttribute)memberAccExpr.Member.GetCustomAttributes(typeof(DisplayAttribute), false).FirstOrDefault();
我在C#项目(不是MVC)中大致测试过,所以我不能说它是否适用于Razor;但我相信你也可以把你的代码转移到正常的类。
请注意,使用此方法可以避免某种类型的安全性,因为调用者可以为该方法提供各种动态表达式。因此,如果您分析表达式以便查找属性,则应考虑到这一点。