Asp.net Mvc 中使用Repeater的6种解决方案

 

请先阅读这里:

ASP.NET Framework Features That Are Compatible with MVC

It might appear that Web Forms and MVC are very different technologies. However, both of these technologies are built on the ASP.NET framework. Therefore, most ASP.NET framework features that you have used to create applications that are based on Web Forms are also available to you for developing MVC applications. This includes features such as membership, authentication, roles, and configuration, which work the same way in an MVC application as they do in a Web Forms application. Most ASP.NET namespaces, classes, and interfaces can be used in an ASP.NET MVC application.

 ASP.NET Framework Features That Are Incompatible with MVC

Because ASP.NET MVC does not maintain state information by using view state, you must find other ways to manage state information, if you need it. In addition, server controls that rely on view state and postback will not work as designed in an ASP.NET MVC application. Therefore, you should not use controls such as the GridView, Repeater, and DataList controls.

源文档 <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(thisout 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 " ) %>   &nbsp;&nbsp;
            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 GridSparkViewEngine也是具有技术可行性.但是是否要引入到项目中要谨慎考虑.

 

<% =  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/>

 

嗯哼,全文完.

坚强2002和你一起回头再说...
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值