我如何使WebGrid列使用真正的lambda进行类型安全?

问题描述 投票:0回答:1

创建WebGridColumn时,它需要为要使用的columnName传入一个字符串。它为什么不允许像大多数其他HTML Helper一样传递lambda表达式?如何传递一个简单的lambda以获得智能提示,保留类型安全性并防止由于错字引起的运行时错误?并且使用列名,WebGrid是否不应该默认使用元数据显示属性来设置标题和格式?

我们定期使用的内容:

@{ var grid = new WebGrid(model) }

@grid.GetHtml(
    // table style formats here...

    columns: grid.Columns(
        grid.Column(columnName: "StudentName",
                    header: Html.DisplayNameFor(model => model.StudentName)),
        grid.Column(columnName: "Birthdate",
                    header: Html.DisplayNameFor(model => model.Birthdate),
                    format: (item) => Html.DisplayFor(modelItem => (item as WebGridRow).Value as Person).Birthdate),
        grid.Column(columnName: "Address.Physical.StreetNumber",
                    header: Html.DisplayFor(model => model.Address.Physical.StreetNumber)),
        grid.Column(columnName: "Address.Physical.StreetName",
                    header: Html.DisplayFor(model => model.Address.Physical.StreetName))
    )
)
c# asp.net asp.net-mvc webgrid
1个回答
1
投票

这是一个同事向我提出的问题。我们广泛使用WebGrid,并且不得不为每一列重复输入相同的信息(一式三份或一式三份),这至少令人沮丧。我研究了扩展WebGrid本身,但是似乎要花很多时间才能使泛型和类型安全。相反,我写了一个HtmlHelper扩展名,返回了WebGridColumn

代码

public static WebGridColumn GridColumnFor<TModel, TValue>(this HtmlHelper<IEnumerable<TModel>> html, Expression<Func<TModel, TValue>> exp, string header = null, Func<dynamic, object> format = null, string style = null, bool canSort = true)
{
    var metadata = ModelMetadata.FromLambdaExpression(exp, new ViewDataDictionary<TModel>());
    var modelText = ExpressionHelper.GetExpressionText(exp);

    if (format == null && metadata.DisplayFormatString != null)
    {
        format = (item) => string.Format(metadata.DisplayFormatString, item[modelText] ?? String.Empty);
    }

    return new WebGridColumn()
    {
        ColumnName = modelText,
        Header = header ?? metadata.DisplayName ?? metadata.PropertyName ?? modelText.Split('.').Last(),
        Style = style,
        CanSort = canSort,
        Format = format
    };
}

通常在任何地方都使用WebGrid.Column()代替使用Html.GridColumnFor()

columns: grid.Columns(
    Html.GridColumnFor(model => model.Name),
    Html.GridColumnFor(model => model.Birthdate),
    Html.GridColumnFor(model => model.Address.Physical.StreetNumber),
    Html.GridColumnFor(model => model.Address.Physical.StreetName),
)

那真漂亮...

发生了什么事?

[它使用内置的Expression功能获取完整的属性名称,以传递给WebGridColumn构造函数,并从MVC获取已内置的元数据,以获取要显示的标题名称,并检查格式。

它还接受标题和格式值的替代,因此您可以自己设置它们;您可能希望一个Person对象用于多个页面,但有些人将Birthdate字段称为“生日”,而另一些人将其称为“出生日期”(我们尽量避免这种情况,但有时这是最终用户的要求),或仅显示日期和月份:

Html.GridColumnFor(model => model.Birthdate, format: (item) => item.Birthdate.ToString("MM/dd"))
© www.soinside.com 2019 - 2024. All rights reserved.