请先阅读这里:
ASP.NET Framework Features That Are Compatible with MVC
它可能出现的Web窗体和MVC有很大的不同技术。但是,这两种技术是建立在ASP.NET的框架。因此,大多数ASP.NET框架的功能,您有用于创建应用程序都是基于Web的形式也可以提供给您作为发展中国家的MVC应用。这包括的功能,如成员资格,认证,角色和配置,它以同样的方式工作中的MVC应用因为它们在Web窗体应用程序。最ASP.NET命名空间,类和接口,可用于在ASP.NET MVC模式的应用。
ASP.NET Framework Features That Are Incompatible with MVC
由于ASP.NET的MVC不保留状态信息通过使用视图状态,你必须寻找其他的方式来管理状态信息,如果您需要它。此外,服务器控件依赖于视图状态和传将无法正常工作设计在ASP.NET MVC模式的应用。因此,你不应该使用的控制,如GridView ,直放站和DataList控件。
源文档 <http://msdn.microsoft.com/en-us/library/dd381619.aspx>
准备工作:
//一个Student类:
public class Student
{
public int Number { get; set; }
public string Name { get; set; }
}
//Dummy Data构造的绑定数据如下:
List<Student> students = new List<Student>();
students.Add(new Student { Name = "lee", Number = 123 });
students.Add(new Student { Name = "Zen", Number = 234 });
students.Add(new Student { Name = "angle", Number = 101 });
ViewData["Students"] = students;
问题是什么?
在View中使用Repeater的问题其实就是绑定事件的执行,明确了这一点其实问题就很简单了.
方案一:页面级解决
我们设计一个View的基类,该基类在页面Load的时候完成DataBind,这样不管页面中有没有需要绑定的控件,需要绑定的控件是什么,这个方法执行完之后就会完成绑定.首先验证我们的想法:
//View基类
public class AutoBindViewPage : ViewPage
{
protected override void OnLoad(EventArgs e)
{
this.DataBind();
base.OnLoad(e);
}
}
页面代码片段:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="AutoBindViewPage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Helloworld
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>
Repeater Test</h2>
<%=Html.Encode(ViewData["Students"])%><br />
<asp:Repeater ID="Repeater1" DataSource='<%#ViewData["Students"]%>' runat="server">
<ItemTemplate>
Name:<%#Eval("Name")%><br />
</ItemTemplate>
</asp:Repeater>
</asp:Content>
注意:Inherits="AutoBindViewPage"
跑一下程序,成功.
原理:
我们看一下继承关系:AutoBindViewPage-->ViewPage-->Page-->TemplateControl-->Control
考察一下Control类的DataBind事件:
protected virtual void DataBind(bool raiseOnDataBinding)
{
bool flag = false;
if (this.IsBindingContainer)
{
bool flag2;
object dataItem = DataBinder.GetDataItem(this, out flag2);
if (flag2 && (this.Page != null))
{
this.Page.PushDataBindingContext(dataItem);
flag = true;
}
}
try
{
if (raiseOnDataBinding)
{
this.OnDataBinding(EventArgs.Empty);
}
this.DataBindChildren();
}
finally
{
if (flag)
{
this.Page.PopDataBindingContext();
}
}
}
关键就在这里:this.DataBindChildren();
方案二:AutoBindRepeater
扩展ViewPage不是什么好主意,把"Repeater绑定"看做一个职责,那么这个职责应该属于Repeater自己的.想到这里也就简单了,删除掉刚刚扩展的类,实现一个AutoBindRepeater:
namespace TestControls
{
{
protected override void OnLoad(EventArgs e)
{
this.DataBind();
base.OnLoad(e);
}
}
}
页面代码片段:
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>
<%@ Register Namespace="TestControls" Assembly="ZenMvc" TagPrefix="My" %>
… …
<My:AutoBindRepeater DataSource='<%#ViewData["Students"]%>' runat="server">
<ItemTemplate>
Name:<%#Eval("Name")%><br />
</ItemTemplate>
</My:AutoBindRepeater>
跑一下,通过.
方案三:AutoBindRepeaterUseDataKey
方案三其实是做一点简单的改造,可以看到 DataSource='<%#ViewData["Students"]%>'在每一个Repeater中都是重复的,改造的目的就是为了简化这一语句.方法也很简单:添加对数据源的解析就可以.
public class AutoBindRepeaterUseDataKey : System.Web.UI.WebControls.Repeater
{
private string _dataKey;
public string DataKey
{
get { return _dataKey; }
set { _dataKey = value; }
}
protected override void OnLoad(EventArgs e)
{
ViewPage viewPage = (System.Web.Mvc.ViewPage)Page;
this.DataSource = viewPage.ViewData[DataKey];
this.DataBind();
base.OnLoad(e);
}
}
页面代码片段:
<My:AutoBindRepeaterUseDataKey DataKey="Students" runat="server">
<ItemTemplate>
Name:<%#Eval("Name")%>
Number:<%#Eval("Number") %><br />
</ItemTemplate>
</My:AutoBindRepeaterUseDataKey>
调试,通过.
方案四:MVCRepeater
细心地你一定发现了,在上面的改造中,我们已经在标准的Repeater实现中引入了MVC框架的内容.在MvcFutures项目中的Microsoft.Web.Mvc.Controls里面,我们找到了一个MVCRepeater的实现:
<%@ Register Assembly="Microsoft.Web.Mvc" Namespace="Microsoft.Web.Mvc.Controls" TagPrefix="MVC" %>
<MVC:Repeater Name="Students" runat="server" >
<ItemTemplate>
Name:<%#Eval("Name")%><br />
</ItemTemplate>
</MVC:Repeater>
MVCRepeater的实现略.
方案五:foreach语句
继续追究为什么要使用Repeater,是因为我们要展示一组数据,走到这里我们的调整一下目标,不再是在MVC使用Repeater控件,而是实现在asp.net MVC 中展示一组数据.
foreach语句具有相当好的表现力:
<%foreach (var item in (List<Student>)ViewData["Students"]){%>
[Name]: <%=item.Name%><br/>
<%} %>
方案六:MvcContrib Grid & SparkViewEngine
全面考虑, MvcContrib Grid和SparkViewEngine也是具有技术可行性.但是是否要引入到项目中要谨慎考虑.
<%= Html.Grid(Model.People).Columns(column => {
column.For(x => x.Id).Named("Person ID");
column.For(x => x.Name);
column.For(x => x.DateOfBirth).Format("{0:d}");
})
.Attributes(style => "width:100%")
.Empty("There are no people.")
.RowStart(row => "<tr foo='bar'>") %>
源文档 <http://www.jeremyskinner.co.uk/2009/02/22/rewriting-the-mvccontrib-grid-part-2-new-syntax/>
<viewdata products="IEnumerable[[Product]]"/>
<ul if="products.Any()">
<li each="var p in products">${p.Name}</li>
</ul>
<else>
<p>No products available</p>
</else>
源文档 <http://sparkviewengine.com/>