通用局部视图:如何将generics类设置为模型?

我正在尝试在ASP.NET MVC应用程序中构建通用网格视图。

让我解释一些代码:

public interface ITrustGrid { IPagedList Elements { get; set; } IList<IColumn> Columns { get; set; } IList Headers { get; } } 

这是一个类的接口,允许我在控制器中设置列和表达式。

我将实现传递给部分视图,如下所示:

 <% Html.RenderPartial("SimpleTrustGridViewer", ViewData["employeeGrid"] as TrustGrid); %> 

问题是我无法弄清楚如何使局部视图呈现网格通用。

换句话说,我想转此:

 <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ITrustGrid>" %> 

变成这样的东西:

 <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ITrustGrid>" %> 

=>如何以最简单的方式使我的部分视图通用?

编辑:

我通过使用具有公共TrustGrid GetTrustGrid()方法的TrustGridBuilder解决了这个问题,该方法返回非genericsTrustGrid。 TrustGrid包含字符串而不是linq的东西。 所以我在GetTrustGrid()方法中执行linq并将字符串放在TrustGrid对象中。

感谢大家帮助我走上正轨。

这样做是不可能的。 原因是.aspx会生成一个你没有太多控制权的类,你不能为它添加一个通用参数。 我想最直接的方法是将它作为object传递。

您可以将要传递给此部分的所有模型类型从基类/接口inheritance,该基类/接口建立此部分视图将使用的基本行为并接受该类/接口类型的任何对象,或者只是拥有该视图接受任何类型的对象,然后使用reflection来基于您的局部视图行为。

例:

 public interface IDisplayModel { string DisplayText{get;set;} string ImageUrl{get;set;} string AltText{get;set;} } public interface ITrustGrid where T : IDisplayModel { IPagedList Elements { get; set; } IList> Columns { get; set; } IList Headers { get; } } <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl>" %> 

当然,您的IDisplayModel会根据您所需的行为而有所不同。 这将允许您将任何内容传递给实现此基本接口的部分以建立一般行为。

我同意Mehrdad,据我所知,不可能制作通用视图。 在我的一个项目中,我使用了一个非常类似的接口,然后将委托函数传递给处理每个项目的特定呈现的视图。

例如,我会使用带有附加字段的非generics视图数据类:

 public interface ITrustGrid { IPagedList Elements { get; set; } IList Columns { get; set; } IList Headers { get; } Func ElementRenderer { get; } } 

在主视图中,您将准备视图数据:

 <% ITrustGrid data = (ITrustGrid)ViewData["employeeGrid"]; data.ElementRenderer = new Func(delegate(o) { var employee = (Employee)o; //render employee return html; }); Html.RenderPartial("SimpleTrustGridViewer", data); %> 

在您的网格部分中,您将像往常一样处理网格,然后调用委托渲染每个单元格:

 <% foreach(var element in ViewData.Elements){ %>  <%=ViewData.ElementRenderer(element) %>  <% } %> 

当然,上面的代码只为每个元素呈现一个单元格,您必须创建一个稍微复杂的委托来呈现多个列(或传入一个委托数组,每列一个)。

我认为这将是最干净的方法之一,虽然有点麻烦。

@Lck:

我在我的控制器中做了类似的事情:

 var columns = new List> { new Column("Full name", e => string.Format("{0} {1}", e.FirstName, e.Name)), new Column("Examination date", e => e.ExaminationDate.HasValue? string.Format("{0} days ago", currentDate.Subtract(e.ExaminationDate.Value).Days) : "Unknown") }; var employeeGrid = new TrustGrid { Columns = columns, Elements = GetEmployees(currentPageIndex)}; ViewData["employeeGrid"] = employeeGrid; 

所以在我的部分视图中,我可以这样做:

 <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl>" %>  <% foreach (string header in Model.Headers) Response.Write(Html.Th(header)); %>  <% foreach (var element in Model.Elements) { Response.Write(""); foreach (var column in Model.Columns) Response.Write(Html.Td(column.ValueExpression(element))); Response.Write(""); } %> 
<%= Html.Pager(Model.Elements.PageSize, Model.Elements.PageNumber, Model.Elements.TotalItemCount)%>

如您所见,我的部分代码都不依赖于使用的类型。 所以我仍然认为这是一个简单的解决方案。