【问题标题】:Using @Html.DisplayNameFor() with PagedList将 @Html.DisplayNameFor() 与 PagedList 一起使用
【发布时间】:2013-02-02 11:18:14
【问题描述】:

我一直在尝试使用 PagedList 包来为我的索引视图获取分页。一切进展顺利,在控制器级别一切正常,每页仅显示 5 条记录,并根据查询字符串显示适当的页面。

我的问题在于视图。我将@Model 更改为PagedList.IPagedList,因此我可以访问Model.HasNextPage 和其他属性,但现在@Html.DisplayNameFor(model => model.ItemName) 不再工作。我收到此错误:

PagedList.IPagedList<Dossier.Models.Item>' does not contain a definition for 'ItemName' and no extension method 'ItemName' accepting a first argument of type 'PagedList.IPagedList<Dossier.Models.Item>' could be found (are you missing a using directive or an assembly reference?)

以下是视图的相关部分:

@model PagedList.IPagedList<Dossier.Models.Item>
@using Dossier.Models.Item

...

<th>
    @Html.DisplayNameFor(model => model.ItemName)
</th>

IPagedList 似乎与 DisplayNameFor() 不兼容。知道为什么会这样,我该如何解决?我知道我可以手动输入列名,但我希望稍后将该信息保留(并且可以更改)在模型中。

【问题讨论】:

  • 为什么不使用 ViewBag 来携带您的数据并让 @model 保持原来的样子?

标签: asp.net-mvc entity-framework razor asp.net-mvc-4 pagedlist


【解决方案1】:

你可以试试这个

@Html.DisplayNameFor(model => model.FirstOrDefault().ItemName)

【讨论】:

  • 当序列中没有元素时,使用First() 将抛出InvalidOperationException。使用FirstOrDefault() 可避免此异常。或者您可以使用FirstOrDefault 'dummy element',正如这个重复问题中所建议的那样:stackoverflow.com/a/13780314/1364650
  • @viniciusdeLemos:这也解决了我的问题 :)
【解决方案2】:

作为已接受答案的替代解决方案,请记住 IPagedList 继承自 IEnumerable。这意味着你可以写:

@model IEnumerable<Dossier.Models.Item>

在页面的开头,并在需要时将模型转换为 IPagedList:

@Html.PagedListPager((IPagedList)Model, page => Url.Action("Index", new { page = page }))

您甚至可以在标题中声明转换后的变量,以便在页面中多次使用它:

@{
    ViewBag.Title = "My page title";
    var pagedlist = (IPagedList)Model;
}

这将允许您使用 DisplayNameFor 辅助方法,并访问所有 PagedList 方法/属性,而无需虚拟元素,也无需为每个字段调用 .FirstOrDefault()。

【讨论】:

  • 一年后,这个解决方案仍然有效。在提供的所有答案中,这个对我最有帮助,因为 (a) 它有效,并且 (b) 它简短而简单。
  • 这感觉是最干净的解决方案。
  • 这应该是答案。太好了!
【解决方案3】:

我通过创建一个接受IPagedList&lt;TModel&gt;DisplayNameFor 重载解决了这个问题。

namespace PagedList.Mvc
{
    public static class Extensions
    {

        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
        public static MvcHtmlString DisplayNameFor<TModel, TValue>(this HtmlHelper<IPagedList<TModel>> html, Expression<Func<TModel, TValue>> expression)
        {
            return DisplayNameForInternal(html, expression);
        }

        [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", Justification = "This is an extension method")]
        internal static MvcHtmlString DisplayNameForInternal<TModel, TValue>(this HtmlHelper<IPagedList<TModel>> html, Expression<Func<TModel, TValue>> expression)
        {
            return DisplayNameHelper(ModelMetadata.FromLambdaExpression(expression, new ViewDataDictionary<TModel>()),
                                     ExpressionHelper.GetExpressionText(expression));
        }

        internal static MvcHtmlString DisplayNameHelper(ModelMetadata metadata, string htmlFieldName)
        {
            string resolvedDisplayName = metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last();

            return new MvcHtmlString(HttpUtility.HtmlEncode(resolvedDisplayName));
        }
    }
}

我将向 PageList 项目发送一个拉取请求,以将其包含到每个人的项目中。

【讨论】:

    【解决方案4】:

    您无需更改@Html.DisplayNameFor。在视图中声明模型为:

    @model IEnumerable<Dossier.Models.Item>
    

    只需将您的寻呼机移动到局部视图(我们将其命名为“_Pager”):

    @model IPagedList
    
    ...
    
    @Html.PagedListPager(Model, 
       page => Url.Action("Index", new { page, pageSize = Model.PageSize }))
    
    ...
    

    在您的视图中呈现寻呼机:

    @Html.Partial("_Pager", Model)
    

    就是这样。

    附:您可以创建 Html 助手而不是部分视图...

    【讨论】:

      【解决方案5】:

      作为替代解决方案,您可以尝试:

      @Html.DisplayNameFor(x => x.GetEnumerator().Current.ItemName)
      

      即使列表为空也可以使用!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-09-27
        • 1970-01-01
        • 2011-11-12
        • 1970-01-01
        • 2022-12-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多