我使用的是asp.mvc 4。假设我有一个名为Person的带有字段的模型
public class Person
{
public int ID { get; set; }
public string FirstName { get; set; }
public string SecondName { get; set; }
public DateTime DateOfBirth { get; set; }
public DateTime DateOfWorkstart { get; set; }
public int NumberOfChildren { get; set; }
public int DepartmentID { get; set; }
public virtual Department Department { get; set; }
}
public class Department
{
public int ID { get; set; }
public int NameOfDepartment { get; set; }
}
在我自动生成的剃刀编辑视图中,字段显示如下(为了清晰起见,我在这篇文章中只包含了重要的行)
@Html.DisplayFor(modelItem => item.FirstName)
@Html.DisplayFor(modelItem => item.SecondName)
现在我想把linqlambda表达式存储在一个列表中,稍后再使用,我不知道如何做到这一点,我需要这样的东西:
@{
string itemsToShow = "namepart"; // this could also be "otherpart"
List <Expression<>> list = new List();
if (itemsToShow.equals("namepart")
{
list.add(modelItem => item.FirstName);
list.add(modelItem => item.SecondName);
}
else
{
list.add(modelItem => item.DateOfBirth);
list.add(modelItem => item.DateOfWorkStart);
list.add(modelItem => item.NumberOfChildren);
}
}
最后,我想使用像这个一样生成的列表
@foreach (var lambda in list)
{
@Html.DisplayFor(lambda)
}
我会为此编写一个自定义帮助程序:
public static class HtmlExtensions
{
public static IHtmlString MyHelper(this HtmlHelper<MyViewModel> html, string itemsToShow)
{
var sb = new StringBuilder();
if (itemsToShow == "namepart")
{
sb.Append(html.DisplayFor(x => x.FirstName));
sb.Append(html.DisplayFor(x => x.SecondName));
}
else
{
sb.Append(html.DisplayFor(x => x.DateOfBirth));
sb.Append(html.DisplayFor(x => x.DateOfWorkStart));
sb.Append(html.DisplayFor(x => x.NumberOfChildren));
}
return new HtmlString(sb.ToString());
}
}
然后简单地进入视图:
@Html.MyHelper("namepart")
如果你想渲染另一部分:
@Html.MyHelper("otherpart")
作为替代方案,只需将此内容放入2个不同的局部视图中,然后:
@if (itemsToShow == "namepart")
{
@Html.Partial("_NamePart", Model)
}
else
{
@Html.Partial("_OtherPart", Model)
}
我的大脑有了一些小进步。谢谢你的建议。正如@darin-dimitrov所说,秘密是存储一个表达式树。我更新了我的第一篇文章,并添加了一个相关的表格。仅当模型在编辑视图中提取了"数据库表中的1单行"时,此示例才有效;
// first a small helper, which creates the member and checks nullable fields
public static Expression getExpressionPart(ParameterExpression param,
String s1, String s2)
{
Expression member = null;
if (s2 == null)
{
member = Expression.Property(param, s1);
}
else
{
// the second string is to deal with foreign keys/related data
member = Expression.PropertyOrField(
Expression.PropertyOrField(param, s1), s2
);
}
Type typeIfNullable = Nullable.GetUnderlyingType(member.Type);
if (typeIfNullable != null)
{
member = Expression.Call(member, "GetValueOrDefault", Type.EmptyTypes);
}
}
现在创建列表和表达式
List<Expression<Func<Person, object>>> list =
new List<Expression<Func<Person, object>>>();
ParameterExpression param = Expression.Parameter(typeof(Person), "p");
// maps to expression p => p.FirstName
Expression member = getExpressionPart(param, "Firstname", null);
list.Add(Expression.Lambda<Func<Person, object>>(member, param));
// maps to expression p => p.Department.NameOfDepartment
member = getExpressionPart(param, "Department", "NameOfDepartment");
list.Add(Expression.Lambda<Func<Person, object>>(member, param));
现在它起作用了!
@foreach (var lambda in list)
{
@Html.DisplayNameFor(lambda)
@Html.DisplayFor(lambda)
}
你试过这样存储lambda吗:
Func<Person,bool> personExpression = (u => u.FirstName == firstname);
@Html.DisplayFor(personExpression)
对于两种输入类型,您的代码看起来像这样:
Func<Person,Ticket,bool> personExpression =
((u,t) => u.FirstName == firstname && u.SecondName == t.SecondName);
要在剃刀视图中循环遍历模型属性,应使用ViewData.ModelMetadata.Properties
,如本答案所示。例如:
@* Loop through properties. *@
@foreach (var property in ViewData.ModelMetadata.Properties)
{
@Html.Display(property.PropertyName)
}