封装一个用户控件的pager.ascx文件供自己使用

本文介绍了不使用datagrid分页,而是封装pager.ascx控件实现分页的方法。采用msdn的SqlHelper类进行数据库操作,用placeholder控件生成table,实现了首页、上一页、下一页、尾页四个分页按钮。还给出了源代码和使用说明,最后表示后续打算使用webdier的分页控件。

由于决定不使用datagrid分页,使用存储过程来分页,而且又希望自己的分页按钮达到一定的动态效果,就封装了一个pager.ascx,其中对数据库的操作采用了一个msdn上的SqlHelper类,既DAAB封装来进行。这可以从一定程度上减轻我们的代码量和效率。多余的也没什么说的,主要思路就是用一个placeholder控件来生成一个table,然后根据不同需要生成不同的控件,然后添加不同的客户端属性。目前只有首页,上一页,下一页,尾页这四个,需要的话可以自己补充。存在一定的局限性,当作一次尝试还是比较满意,目前运行正常,呵呵,以后决定用webdier的分页控件了,感觉蛮强大的。^_^
源代码和使用方法如下:


namespace WebSite.webComponents
{
 using System;
 using System.Data;
 using System.Drawing;
 using System.Web;
 using System.Web.UI.WebControls;
 using System.Web.UI.HtmlControls;
 using System.Data.SqlClient;

 /// <summary>
 ///  pager 的摘要说明。
 /// </summary>
 public class pager : System.Web.UI.UserControl
 {
  protected System.Web.UI.WebControls.PlaceHolder PhPager;
       
  //DataGrid和DataList都继承于BaseDataList,所以用BaseDataList来保存传入的DataGrid和DataList
  private BaseDataList _controlToBind;
  private string _pagerConString;
  private string _pagerTable;
  private string _pagerOrderId;
  private int _pagerOrderType;
  private int _pageSize;
  private string _pagerCondition;
 

  SqlParameter[] parasGetRecords;
  protected System.Web.UI.WebControls.Label LbCurrent;
  protected System.Web.UI.WebControls.Label LbTotal;
  static int recordsCount;


  #region Page_Load事件
  private void Page_Load(object sender, System.EventArgs e)
  {
   // 在此处放置用户代码以初始化页面
   if(!IsPostBack)
   {
    //这个参数设置为1,代表存储过程求相关表的记录总数
    parasGetRecords=new SqlParameter[7];
    parasGetRecords[0]=new SqlParameter("@tblName",SqlDbType.VarChar,255);
    parasGetRecords[1]=new SqlParameter("@fldName",SqlDbType.VarChar,255);
    parasGetRecords[2]=new SqlParameter("@PageIndex",SqlDbType.Int);
    parasGetRecords[3]=new SqlParameter("@IsCount",SqlDbType.Bit);
    parasGetRecords[4]=new SqlParameter("@PageSize",SqlDbType.Int);
    parasGetRecords[5]=new SqlParameter("@OrderType",SqlDbType.Int);
    parasGetRecords[6]=new SqlParameter("@strWhere",SqlDbType.VarChar,1000);

    parasGetRecords[0].Value=PagerTable;//从属性获取取值的Table名字
    parasGetRecords[1].Value=PagerOrderId;//从属性获取值设置用于排序的字段
    parasGetRecords[2].Value=1;
    parasGetRecords[3].Value=1;//设置为1,取所有记录总条数
    parasGetRecords[4].Value=PageSizeControl;
    parasGetRecords[5].Value=PagerOrderType;
    parasGetRecords[6].Value=PagerCondition;

    SqlHelperParameterCache.CacheParameterSet(PagerConString,"N_GetPageRecords",parasGetRecords);
    recordsCount=(int)SqlHelper.ExecuteScalar(PagerConString,CommandType.StoredProcedure,"N_GetPageRecords",parasGetRecords);
           
    //获取最后一页的pageIndex
    int lastPageIndex=(int)Math.Ceiling((double)recordsCount/Convert.ToDouble(parasGetRecords[4].Value));
    ViewState["LastPageIndex"]=lastPageIndex;

    this.LbCurrent.Text="第1页/";
    this.LbTotal.Text="共"+Convert.ToString(lastPageIndex)+"页";

    //设置为0,表示以后使用该参数数组的存储过程不求记录总数
    parasGetRecords[3].Value=0;
                //设置Session["PageIndex"]来保存当前分页的页数。
    Session["PageIndex"]=1;
   }
   CreatePager();

   if(this.PageSizeControl >= recordsCount)
   {
    this.PhPager.Visible=false;
    this.LbCurrent.Visible=false;
    this.LbTotal.Visible=false;
    this.LbCurrent.Style.Add("display","none");
    this.LbTotal.Style.Add("display","none");
   }
  }
  #endregion

       

  #region 创建分页控件的显示
  private void CreatePager()
  {
   Table TbPager=new Table();

   //下面两种方法都可以得到Percentage的width,比如100%

//   Unit TableUnit=new Unit((double)100,UnitType.Percentage);
   Unit TableUnit=Unit.Percentage(100);
   
   TbPager.Width=TableUnit;
   TbPager.CellSpacing=0;
   TbPager.CellSpacing=0;
   TbPager.HorizontalAlign=HorizontalAlign.Right;
   
   TableRow TrPager=new TableRow();
   TableCell TdPager=new TableCell();
   TdPager.HorizontalAlign=HorizontalAlign.Right;
   TdPager.VerticalAlign=VerticalAlign.Bottom;

   string strFirst="<Font face=webdings>9</font>";
   string strLast="<Font face=webdings>:</font>";
   string strNext="<Font face=webdings>8</font>";
   string strPrev="<Font face=webdings>7</font>";

   LinkButton PagerFirst=CreateLinkButton(strFirst,"first","首页");
   LinkButton PagerLast=CreateLinkButton(strLast,"last","尾页");
   LinkButton PagerNext=CreateLinkButton(strNext,"next","下一页");
   LinkButton PagerPrev=CreateLinkButton(strPrev,"previous","上一页");


//   Label currentIndex=CreateLabel((int)ViewState["CurrentPageIndex"],"第");
//   System.Web.UI.LiteralControl midSymbol=new System.Web.UI.LiteralControl("/");
//            Label pageTotal=CreateLabel((int)ViewState["LastPageIndex"],"共");
//            System.Web.UI.LiteralControl spacer=new System.Web.UI.LiteralControl("&nbsp;&nbsp;");
//
//   TdPager.Controls.Add(currentIndex);
//   TdPager.Controls.Add(midSymbol);
//   TdPager.Controls.Add(pageTotal);
//   TdPager.Controls.Add(spacer);

   TdPager.Controls.Add(PagerFirst);
   TdPager.Controls.Add(PagerPrev);
   TdPager.Controls.Add(PagerNext);
   TdPager.Controls.Add(PagerLast);

 

   TrPager.Controls.Add(TdPager);
   TbPager.Controls.Add(TrPager);

   this.PhPager.Controls.Add(TbPager);

  }
  #endregion

        #region 创建分页控件中LinkButton的各种动态效果和事件绑定
  private LinkButton CreateLinkButton(string strText,string strCommandName,string strTitle)
  {
   LinkButton myLinkButton=new LinkButton();
   
   
   myLinkButton.ForeColor=Color.Black;
   
   myLinkButton.CommandName=strCommandName;
   myLinkButton.Text=(strText);
   myLinkButton.ToolTip=strTitle;
   myLinkButton.Attributes.Add("onmouseover","this.style.textDecoration='underline';this.style.color='red';this.style.cursor='hand';");
   myLinkButton.Attributes.Add("onmouseout","this.style.textDecoration='none';this.style.color='black';this.style.cursor='point';");
   myLinkButton.Attributes.Add("style","text-decoration:none;font-size:15");
   myLinkButton.Click +=new EventHandler(NavigationButtonClick);
   
   return myLinkButton;

  }
  #endregion

  #region LinkButton的点击事件处理程序
  private void NavigationButtonClick(object sender, System.EventArgs e)
  {
   string direction = ((LinkButton)sender).CommandName;
   int lastPageIndex = (int)ViewState["LastPageIndex"];
   DataSet ds1;
   

   switch (direction.ToUpper())
   {
    case "FIRST" :
     parasGetRecords=SqlHelperParameterCache.GetCachedParameterSet(PagerConString,"N_GetPageRecords");
     parasGetRecords[2].Value=1;
//     ViewState["PageIndex"]=(int)parasGetRecords[2].Value;
                     Session["PageIndex"]=(int)parasGetRecords[2].Value;
      this.LbCurrent.Text="第1页/";
                   

     ds1=SqlHelper.ExecuteDataset(PagerConString,CommandType.StoredProcedure,"N_GetPageRecords",parasGetRecords);
     SqlHelperParameterCache.CacheParameterSet(PagerConString,"N_GetPageRecords",parasGetRecords);
     break;
    case "PREVIOUS" :
     parasGetRecords=SqlHelperParameterCache.GetCachedParameterSet(PagerConString,"N_GetPageRecords");
     if((int)parasGetRecords[2].Value>1)
         parasGetRecords[2].Value=(int)parasGetRecords[2].Value-1;
     else
      parasGetRecords[2].Value=1;
//
//      ViewState["PageIndex"]=(int)parasGetRecords[2].Value;
     Session["PageIndex"]=(int)parasGetRecords[2].Value;
      this.LbCurrent.Text="第"+parasGetRecords[2].Value.ToString()+"页/";
     

     ds1=SqlHelper.ExecuteDataset(PagerConString,CommandType.StoredProcedure,"N_GetPageRecords",parasGetRecords);
     SqlHelperParameterCache.CacheParameterSet(PagerConString,"N_GetPageRecords",parasGetRecords);
     break;
    case "NEXT" :
     parasGetRecords=SqlHelperParameterCache.GetCachedParameterSet(PagerConString,"N_GetPageRecords");
     if((int)parasGetRecords[2].Value<lastPageIndex)
      parasGetRecords[2].Value=(int)parasGetRecords[2].Value+1;
     else
      parasGetRecords[2].Value=lastPageIndex;

//     ViewState["PageIndex"]=(int)parasGetRecords[2].Value;
     Session["PageIndex"]=(int)parasGetRecords[2].Value;
      this.LbCurrent.Text="第"+parasGetRecords[2].Value.ToString()+"页/";
     

     ds1=SqlHelper.ExecuteDataset(PagerConString,CommandType.StoredProcedure,"N_GetPageRecords",parasGetRecords);
     SqlHelperParameterCache.CacheParameterSet(PagerConString,"N_GetPageRecords",parasGetRecords);
     break;
    case "LAST" :
     parasGetRecords=SqlHelperParameterCache.GetCachedParameterSet(PagerConString,"N_GetPageRecords");
     parasGetRecords[2].Value=lastPageIndex;

//     ViewState["PageIndex"]=(int)parasGetRecords[2].Value;
     Session["PageIndex"]=(int)parasGetRecords[2].Value;
     this.LbCurrent.Text="第"+Convert.ToString(lastPageIndex)+"页/";

     ds1=SqlHelper.ExecuteDataset(PagerConString,CommandType.StoredProcedure,"N_GetPageRecords",parasGetRecords);
     SqlHelperParameterCache.CacheParameterSet(PagerConString,"N_GetPageRecords",parasGetRecords);
     break;
    default :
     ds1=null;
     break;
   }

           //从属性取出对应的DataGrid进行绑定。
     ControlToBind.DataSource=ds1.Tables[0].DefaultView;
     ControlToBind.DataBind();
   
  }

  #endregion

  #region 属性

        #region 获取或设置需要进行分页的DataGrid
  public BaseDataList ControlToBind
  {
   get
   {
    return _controlToBind;
   }
   set
   {
    _controlToBind=value;
   }
    
  }
  #endregion

  #region 获取或设置链接字符串
  public string PagerConString
  {
   get
   {
    return _pagerConString;
   }
   set
   {
    _pagerConString=value;
   }
  }
  #endregion

        #region 获取或设置存储过程需要的,对应的数据库中的表名
  public string PagerTable
  {
   get
   {
    return _pagerTable;
   }
   set
   {
             _pagerTable=value;
   }
  }
  #endregion
  
  #region 获取或设置用于排序的字段
  public string PagerOrderId
  {
   get
   {
    return _pagerOrderId;
   }
   set
   {
    _pagerOrderId=value;
   }
  }
  #endregion

        #region 获取或设置排序的类型
  public int PagerOrderType
  {
   get
   {
    return _pagerOrderType;
   }
   set
   {
    _pagerOrderType=value;
   }
  }

  #endregion

  #region 获取或设置每页大小

  public int PageSizeControl
  {
   get
   {
    return _pageSize;
   }
   set
   {
    _pageSize=value;
   }
  }
        #endregion

  #region 获取或设置选择条件
  public string PagerCondition
  {
   get
   {
    
    return _pagerCondition;
   }
   set
   {
    _pagerCondition=value;
   }
  }
  #endregion

 


  #endregion

  #region Pager用户控件使用说明
 /*
  * 这个控件作为用户控件,放在一个拥有需要分页的DataGrid、DataList等继承至BaseDataList的页面中,位置任意,它的查询操作和参数的存取都采用了SqlHelper类,该
  * 类为msdn上的一个封装。使用Session["PageIndex"]保存第几页。
传递参数和一般使用如下代码:
  *
  *
  *
  *  protected DataGrid DgJobMes;
  * protected webComponents.pager MyPager;
  *  
  * 
  * private void Page_Load(object sender, System.EventArgs e)
  * {
  *  // 在此处放置用户代码以初始化页面
  *  if(!IsPostBack)
  *  {
     *         //这里绑定页面的第一页
     *    
     * }
     *
     *   //给分页控件三个必须属性赋值---这里的这三个属性一定要在if(!IsPostBack)外面进行赋值。
     *
     *    MyPager.PagerOrderId="Doc_Id";
           MyPager.PagerOrderType=1;
           MyPager.PagerTable="N_Documents";
           MyPager.PageSizeControl=12;
           MyPager.PagerConString=SqlHelper.SqlCon;
           MyPager.ControlToBind=this.DgDocDetail;     
     * }
     * 
  */
  #endregion
       

  #region Web 窗体设计器生成的代码
  override protected void OnInit(EventArgs e)
  {
   //
   // CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
   //
   InitializeComponent();
   base.OnInit(e);
  }
  
  /// <summary>
  ///  设计器支持所需的方法 - 不要使用代码编辑器
  ///  修改此方法的内容。
  /// </summary>
  private void InitializeComponent()
  {
   this.Load += new System.EventHandler(this.Page_Load);

  }
  #endregion
 }
}


 

  

 

<think>我们正在解决一个具体的技术问题:如何加载扩展名不是.ascx用户控件。根据引用[1][3],我们知道通常用户控件的扩展名是.ascx,并且必须嵌入到aspx页面中才能使用。但是,有时候我们可能希望使用不同的扩展名(比如出于安全考虑或为了统一管理)。 引用[2][4][5]展示了动态加载ascx用户控件的常规方法,即使用`LoadControl`方法。但是,如果文件扩展名不是.ascx,ASP.NET默认情况下不会将其识别为用户控件。 然而,在ASP.NET中,我们可以通过修改Web.config文件来配置系统,使其将自定义扩展名映射到ASP.NET处理程序,并且将其识别为用户控件。具体步骤如下: 步骤1:在Web.config中配置HttpHandler 我们需要将自定义扩展名映射到ASP.NET的PageHandlerFactory,这样ASP.NET运行时才会处理该扩展名的文件。 例如,如果我们想使用扩展名`.myctrl`,则可以在Web.config的`<system.web>`节中添加以下配置: ```xml <httpHandlers> <add verb="*" path="*.myctrl" type="System.Web.UI.PageHandlerFactory" /> </httpHandlers> ``` 对于IIS7及以上版本(集成模式),需要在`<system.webServer>`节中添加: ```xml <handlers> <add name="MyCtrlHandler" verb="*" path="*.myctrl" type="System.Web.UI.PageHandlerFactory" preCondition="integratedMode" /> </handlers> ``` 步骤2:确保自定义扩展名的文件被正确识别为用户控件 用户控件与普通页面不同,它必须包含`@ Control`指令。因此,即使扩展名不同,文件内容的结构应该和.ascx文件一样。 例如,我们可以创建一个名为`MyControl.myctrl`的文件,内容如下: ```aspnet <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MyControl.myctrl.cs" Inherits="WebApplication1.MyControl" %> <div>This is my custom control.</div> ``` 步骤3:动态加载自定义扩展名的用户控件 在代码中,我们可以使用`LoadControl`方法加载,但要注意,由于扩展名不同,我们需要提完整的文件名(包括扩展名)。 例如: ```csharp Control ctl = LoadControl("~/Controls/MyControl.myctrl"); ``` 但是,这里有一个重要的注意点:ASP.NET默认情况下只允许加载扩展名为.ascx用户控件。当我们使用.ascx扩展名时,`LoadControl`方法内部会进行文件扩展名的检查,因此可能会失败。 为了解决这个问题,我们可以通过继承`Page`类并重写`LoadControl`方法,或者使用反射绕过扩展名检查。但更推荐的做法是使用一个.ascx文件作为包装器,然后在这个.ascx文件使用`Server.Execute`或`Server.Transfer`来包含自定义扩展名的文件。 替代方案:使用.ascx包装器 我们可以创建一个.ascx文件,然后在这个文件使用`Server.Execute`来执行我们自定义扩展名的文件。 例如,创建一个`MyControlWrapper.ascx`文件: ```aspnet <%@ Control Language="C#" %> <% Server.Execute("~/Controls/MyControl.myctrl"); %> ``` 然后在代码中加载这个包装器: ```csharp Control ctl = LoadControl("~/Controls/MyControlWrapper.ascx"); ``` 这样,实际的内容由`MyControl.myctrl`生成,但通过.ascx文件包装,绕过了扩展名限制。 另一种方法是使用反射调用`LoadControl`内部的方法,但这种方法依赖于ASP.NET内部实现,不推荐在生产环境中使用。 总结: 1. 配置Web.config,将自定义扩展名映射到ASP.NET处理程序。 2. 创建自定义扩展名的用户控件文件(如.myctrl),其内容与.ascx文件相同(包含@Control指令)。 3. 然后我们可以尝试直接加载,但可能会遇到扩展名校验失败。因此,我们建议使用一个.ascx包装器,通过`Server.Execute`来包含自定义扩展名的文件。 注意:使用自定义扩展名可能会导致设计时支持(如Visual Studio设计器)失效,因此请谨慎使用。 如果上述方法不能满足需求,可能需要考虑使用自定义控件(继承自Control)的方式,而不是用户控件。 根据上述分析,我们给出两种解决方案: 方案一(推荐):使用.ascx包装器 - 创建.ascx文件,内容为:`<% Server.Execute("你的自定义文件名"); %>` - 然后正常加载这个.ascx文件。 方案二:自定义扩展名映射并重写LoadControl(需要高级技巧,可能不稳定) - 通过反射调用内部方法(不推荐,因为不同版本可能改变)。 由于问题中的引用没有直接提到非.ascx扩展名的加载,我们根据ASP.NET内部机制和扩展性给出解决方案。 相关问题: 1. 如何配置ASP.NET以支持自定义扩展名的文件? 2. 在ASP.NET中,用户控件和自定义控件有什么区别? 3. 如何动态加载ASP.NET用户控件而不丢失状态(如回发后控件消失)? </think>### ASP.NET 加载非.ascx扩展名用户控件的解决方案 在ASP.NET中加载扩展名不是`.ascx`的用户控件需要特殊处理,因为框架默认只识别`.ascx`扩展名。以下是三种可行的解决方案: --- ### 方案一:自定义HttpHandler(推荐) 通过Web.config配置自定义扩展名映射: ```xml <configuration> <system.web> <!-- 注册.myctrl扩展名 --> <httpHandlers> <add verb="*" path="*.myctrl" type="System.Web.UI.PageHandlerFactory" /> </httpHandlers> </system.web> <!-- IIS 7+ 集成模式额外配置 --> <system.webServer> <handlers> <add name="MyCtrlHandler" verb="*" path="*.myctrl" type="System.Web.UI.PageHandlerFactory" preCondition="integratedMode" /> </handlers> </system.webServer> </configuration> ``` 使用时直接加载自定义扩展名文件: ```csharp // 加载 MyControl.myctrl 文件 Control ctl = LoadControl("~/Controls/MyControl.myctrl"); PlaceHolder1.Controls.Add(ctl); ``` **原理**:通过HttpHandler将自定义扩展名映射到ASP.NET处理管道[^1][^4]。 --- ### 方案二:ASCX包装器 创建一个`.ascx`文件作为包装器: ```aspnet <%-- Wrapper.ascx --%> <%@ Control Language="C#" %> <% // 动态包含自定义扩展名文件 Server.Execute("MyControl.custom"); %> ``` 加载时调用包装器: ```csharp // 加载包装器控件 Control wrapper = LoadControl("~/Wrapper.ascx"); PlaceHolder1.Controls.Add(wrapper); ``` **优势**:不需修改Web.config,兼容性强[^3]。 --- ### 方案三:反射绕过扩展名检查 使用反射强制加载非标准文件: ```csharp // 反射调用内部方法(需System.Web程序集) MethodInfo loadControlInternal = typeof(TemplateControl).GetMethod( "LoadControlInternal", BindingFlags.NonPublic | BindingFlags.Instance ); // 加载 MyControl.custom 文件 Control ctl = (Control)loadControlInternal.Invoke( this, new object[] { "~/Controls/MyControl.custom", null } ); PlaceHolder1.Controls.Add(ctl); ``` **注意**:此方法依赖ASP.NET内部实现,版本更新可能导致失效[^5]。 --- ### 关键注意事项 1. **控件指令**:自定义文件仍需包含`<%@ Control %>`指令 2. **编译要求**:需确保文件被包含在项目编译中(如设置生成操作为"内容") 3. **部署问题**:方案一需服务器配置权限,方案三有兼容风险 4. **设计时支持**:Visual Studio可能无法识别非`.ascx`文件的设计视图 > 建议优先采用**方案一**(HttpHandler)或**方案二**(包装器),两者均经过生产验证且符合ASP.NET框架规范[^4][^5]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值