请先阅读这里:
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>
准备工作:
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,这样不管页面中有没有需要绑定的控件,需要绑定的控件是什么,这个方法执行完之后就会完成绑定.首先验证我们的想法:
public class AutoBindViewPage : ViewPage
{
protected override void OnLoad(EventArgs e)
{
this .DataBind();
base .OnLoad(e);
}
}
页面代码片段:
< 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事件:
{
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:
{
{
protected override void OnLoad(EventArgs e)
{
this .DataBind();
base .OnLoad(e);
}
}
}
页面代码片段:
<% @ 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中都是重复的,改造的目的就是为了简化这一语句.方法也很简单:添加对数据源的解析就可以.
{
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);
}
}
页面代码片段:
< ItemTemplate >
Name: <% # Eval ( " Name " ) %>
Number: <% # Eval ( " Number " ) %> < br />
</ ItemTemplate >
</ My:AutoBindRepeaterUseDataKey >
调试,通过.
方案四:MVCRepeater
细心地你一定发现了,在上面的改造中,我们已经在标准的Repeater实现中引入了MVC框架的内容.在MvcFutures项目中的Microsoft.Web.Mvc.Controls里面,我们找到了一个MVCRepeater的实现:
< MVC:Repeater Name ="Students" runat ="server" >
< ItemTemplate >
Name: <% # Eval ( " Name " ) %> < br />
</ ItemTemplate >
</ MVC:Repeater >
MVCRepeater的实现略.
方案五:foreach语句
继续追究为什么要使用Repeater,是因为我们要展示一组数据,走到这里我们的调整一下目标,不再是在MVC使用Repeater控件,而是实现在asp.net MVC 中展示一组数据.
foreach语句具有相当好的表现力:
[Name]: <% = item.Name %> < br />
<% } %>
方案六:MvcContrib Grid & SparkViewEngine
全面考虑, MvcContrib Grid和SparkViewEngine也是具有技术可行性.但是是否要引入到项目中要谨慎考虑.
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/>
< ul if ="products.Any()" >
< li each ="var p in products" > ${p.Name} </ li >
</ ul >
< else >
< p > No products available </ p >
</ else >