C# 泛型局部视图:如何将泛型类设置为模型?
我正在尝试在ASP.NETMVC应用程序中构建通用网格视图 让我用一些代码来解释:C# 泛型局部视图:如何将泛型类设置为模型?,c#,asp.net-mvc,generics,C#,Asp.net Mvc,Generics,我正在尝试在ASP.NETMVC应用程序中构建通用网格视图 让我用一些代码来解释: public interface ITrustGrid<T> { IPagedList<T> Elements { get; set; } IList<IColumn<T>> Columns { get; set; } IList<string> Headers { get; } } 公共接口ITrustGrid { IPage
public interface ITrustGrid<T>
{
IPagedList<T> Elements { get; set; }
IList<IColumn<T>> Columns { get; set; }
IList<string> Headers { get; }
}
公共接口ITrustGrid
{
IPagedList元素{get;set;}
IList列{get;set;}
IList头文件{get;}
}
这是一个类的接口,允许我在控制器中设置列和表达式
我将实现传递给局部视图,如下所示:
<% Html.RenderPartial("SimpleTrustGridViewer", ViewData["employeeGrid"] as TrustGrid<EmployeeInfoDTO>); %>
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ITrustGrid<T>>" %>
问题是我不知道如何使渲染网格的局部视图成为通用视图
换言之,我想把这个转变为:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ITrustGrid<EmployeeInfoDTO>>" %>
变成这样:
<% Html.RenderPartial("SimpleTrustGridViewer", ViewData["employeeGrid"] as TrustGrid<EmployeeInfoDTO>); %>
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ITrustGrid<T>>" %>
=>如何以最简单的方式使局部视图通用
编辑:
我通过使用一个TrustGridBuilder解决了这个问题,它有一个公共的TrustGrid GetTrustGrid()方法,该方法返回一个非通用的TrustGrid。信任网格包含字符串而不是linq内容。因此,我在GetTrustGrid()方法中执行linq,并将字符串放入TrustGrid对象中
谢谢大家在正确的轨道上帮助我。这样做是不可能的。原因是,
.aspx
将生成一个您对其没有太多控制权的类,并且您无法向其添加泛型参数。我想最简单的方法是将其作为对象传递
您可以使要传递到该分部的所有模型类型从基类/接口继承,该基类/接口建立该分部视图将使用的基本行为,并接受该类/接口类型的任何对象,或者只是让视图接受任何类型的对象,然后使用反射将局部视图行为建立在对象的基础上
例如:
public interface IDisplayModel
{
string DisplayText{get;set;}
string ImageUrl{get;set;}
string AltText{get;set;}
}
public interface ITrustGrid<T> where T : IDisplayModel
{
IPagedList<T> Elements { get; set; }
IList<IColumn<T>> Columns { get; set; }
IList<string> Headers { get; }
}
<%@ Control Language="C#"
Inherits="System.Web.Mvc.ViewUserControl<ITrustGrid<IDisplayModel>>" %>
公共接口IDisplayModel
{
字符串DisplayText{get;set;}
字符串ImageUrl{get;set;}
字符串AltText{get;set;}
}
公共接口ITrustGrid,其中T:IDisplayModel
{
IPagedList元素{get;set;}
IList列{get;set;}
IList头文件{get;}
}
当然,您的
IDisplayModel
会根据您想要的行为而有所不同。这将允许您将实现此基本接口的任何内容传递给此分部,以建立一般行为。我同意Mehrdad的观点,据我所知,创建一般视图是不可能的。在我的一个项目中,我使用了一个非常类似于您的接口,然后将委托函数传递给处理每个项的特定呈现的视图
例如,我会使用一个非通用视图数据类和一个附加字段:
public interface ITrustGrid {
IPagedList Elements { get; set; }
IList<IColumn> Columns { get; set; }
IList<string> Headers { get; }
Func<object, string> ElementRenderer { get; }
}
公共接口ITrustGrid{
IPagedList元素{get;set;}
IList列{get;set;}
IList头文件{get;}
Func ElementRenderer{get;}
}
在主视图中,您将准备视图数据:
<%
ITrustGrid data = (ITrustGrid)ViewData["employeeGrid"];
data.ElementRenderer = new Func<object, string>(delegate(o) {
var employee = (Employee)o;
//render employee
return html;
});
Html.RenderPartial("SimpleTrustGridViewer", data);
%>
在网格部分中,您将像往常一样处理网格,然后调用代理渲染每个单元格:
<%
foreach(var element in ViewData.Elements){
%>
<tr>
<td><%=ViewData.ElementRenderer(element) %></td>
</tr>
<%
}
%>
当然,上面的代码只为每个元素渲染一个单元格,您必须创建一个稍微复杂的委托来渲染多个列(或者传入一个委托数组,每列一个)
我认为这是最干净的方法之一,尽管有点麻烦。@Lck:
我在控制器中执行类似操作:
var columns = new List<IColumn<EmployeeInfoDTO>>
{
new Column<EmployeeInfoDTO>("Full name", e => string.Format("{0} {1}", e.FirstName, e.Name)),
new Column<EmployeeInfoDTO>("Examination date", e => e.ExaminationDate.HasValue? string.Format("{0} days ago", currentDate.Subtract(e.ExaminationDate.Value).Days) : "Unknown")
};
var employeeGrid = new TrustGrid<EmployeeInfoDTO> { Columns = columns, Elements = GetEmployees(currentPageIndex)};
ViewData["employeeGrid"] = employeeGrid;
var columns=新列表
{
新列(“全名”,e=>string.Format(“{0}{1}”,e.FirstName,e.name)),
新列(“检查日期”,e=>e.ExchangationDate.HasValue?string.Format(“{0}天前”,currentDate.Subtract(e.ExchangationDate.Value).days):“未知”)
};
var employeeGrid=newtrustgrid{Columns=Columns,Elements=GetEmployees(currentPageIndex)};
ViewData[“employeeGrid”]=employeeGrid;
因此,在我看来,我可以做到这一点:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ITrustGrid<EmployeeInfoDTO>>" %>
<table>
<thead>
<tr>
<%
foreach (string header in Model.Headers)
Response.Write(Html.Th(header));
%>
</tr>
</thead>
<tbody>
<%
foreach (var element in Model.Elements)
{
Response.Write("<tr>");
foreach (var column in Model.Columns)
Response.Write(Html.Td(column.ValueExpression(element)));
Response.Write("</tr>");
}
%>
</tbody>
</table>
<div class="pager">
<%= Html.Pager(Model.Elements.PageSize, Model.Elements.PageNumber, Model.Elements.TotalItemCount)%>
</div>
正如您所看到的,我的partial中的任何代码都不依赖于所使用的类型。所以我仍然认为有一个简单的解决方案。嗯,我试过了,但没能想出如何把它转换成有用的东西。你几乎不能把它转换成有用的东西,但您仍然可以将其用作动态对象。您能给出一个如何实现反射解决方案的简短示例吗?添加了示例并将contol INERTIES属性更改为接受“ITrustGrid”希望这就是您想要的。谢谢,但我不喜欢这个解决方案,因为我必须让每个类都实现IDisplayModel接口。我更喜欢一个解决方案,在这个解决方案中,我可以在局部视图中添加一些东西,使其工作。也许我可以向ITrustGrid接口添加一个类型成员?目前我正在尝试类似的方法,但我对这种通用的东西很陌生:)你可以在视图中使用反射,让你的视图模型ITrustGrid,然后使用反射来确定类型,并相应地在局部视图中显示逻辑,但这会使视图比我更膨胀。祝你好运。啊,我搞不懂。。一直在尝试各种各样的东西,但都找不到模型的类型。我尝试将“Type”成员添加到我的接口中,但这也不起作用。由于您的分部不依赖于所使用的类型,您可以只使用Object吗?ITrustGrid?我得到“传入字典的模型项的类型为'Helpers.TrustGrid
1[LinqToSqExample.model.EmployeeInfoDTO]”,但此字典需要'Helpers.ITrustGrid
1[System.Object]'类型的模型项。”当使用TrustGridModel调用分部视图时,当我使用TrustGridModel调用分部视图时,如果我从TrustGrid上的ITrustGrid(具体类)继承,则得到与上面描述的相同的结果。如果我将我的TrustGrid继承更改为ITrustGrid,那么它对我有效。嗯,明天我会尝试。谢谢你的检查。