Как я могу сделать так, чтобы столбцы WebGrid принимали настоящую лямбду для обеспечения безопасности типов? - PullRequest
0 голосов
/ 06 января 2020

При создании WebGridColumn требуется передать строку для columnName, которое будет использоваться. Почему он не позволяет передавать лямбда-выражения, как большинство других HTML помощников? Как я могу передать простую лямбду, чтобы получить интеллигентные подсказки, сохранить безопасность типов и предотвратить ошибки времени выполнения из-за опечаток? И с именем столбца, не должен ли 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))
    )
)

1 Ответ

1 голос
/ 06 января 2020

Это был вопрос, заданный мне коллегой. Мы широко используем WebGrid, и необходимость многократно вводить одну и ту же информацию в двух или трех экземплярах для каждого столбца ... разочаровывает, если не сказать больше. Я посмотрел на расширение WebGrid, но казалось, что потребуется много работы, чтобы сделать generi c и безопасный для типов. Вместо этого я написал расширение 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"))
...