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

请先阅读这里:

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 " ) %>   &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 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 >

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值