自定义分页控件(四)完善设计时支持和增加分页模式

一、解决ToolboxData元数据与Designer元数据冲突的问题

上一篇文章《千万级数据分页之三----实现设计时支持和数字分页 》 ,实现了设计时支持和数字分页,但还是有些不完善的地方,比如“自动套用格式”有“英文样式”和“字符样式”,但是如果我不想要这两种样式,即需要恢复初始状态时,需要再加入“默认样式”,在AspNetPagerAutoFormat类中加入默认样式。代码如下:

 

using  System;
using  System.Collections.Generic;
using  System.Text;
using  System.ComponentModel;
using  System.Web.UI;
using  System.Web;
using  System.Web.UI.Design;
using  System.Web.UI.Design.WebControls;
using  System.Web.UI.WebControls;
using  System.Drawing;
namespace  CustomControls
{
    
public class AspNetPagerAutoFormat : DesignerAutoFormat
    
{
        
public AspNetPagerAutoFormat(string name) : base(name) { }
        
public override void Apply(Control control)
        
{
            
if (control is AspNetPager)
            
{
                AspNetPager aspNetPager 
= (AspNetPager)control;
                
if (this.Name == "英文样式")
                
{
                    aspNetPager.ButtonText 
= "Go";
                    aspNetPager.FirstPageText 
= "First";
                    aspNetPager.PrePageText 
= "Prev";
                    aspNetPager.NextPageText 
= "Next";
                    aspNetPager.EndPageText 
= "End";
                    aspNetPager.LabelStyle.ForeColor 
= Color.Blue;
                    aspNetPager.LabelStyle.Font.Bold 
= true;
                    aspNetPager.TextBoxStyle.CssClass 
= "blue_rounded";
                    aspNetPager.TextBoxStyle.Width 
= Unit.Parse("50px");
                    aspNetPager.PageSize 
= 20;
                    aspNetPager.RecordCount 
= 0;
                }

                
else if (this.Name == "符号样式")
                
{
                    aspNetPager.ButtonText 
= "转到";
                    aspNetPager.FirstPageText 
= "<font face=webdings color="red">9</font>";
                    aspNetPager.PrePageText 
= "<font face=webdings color="red">7</font>";
                    aspNetPager.NextPageText 
= "<font face=webdings color="red">8</font>";
                    aspNetPager.EndPageText 
= "<font face=webdings color="red">:</font>";
                    aspNetPager.LabelStyle.ForeColor 
= Color.Red;
                    aspNetPager.LabelStyle.Font.Bold 
= true;
                    aspNetPager.TextBoxStyle.CssClass 
= "blue_rounded";
                    aspNetPager.TextBoxStyle.Width 
= Unit.Parse("40px");
                    aspNetPager.PageSize 
= 30;
                }

                
else if (this.Name == "默认样式")
                
{
                    aspNetPager.ButtonText 
= "Go";
                    aspNetPager.FirstPageText 
= "首页";
                    aspNetPager.PrePageText 
= "上一页";
                    aspNetPager.NextPageText 
= "下一页";
                    aspNetPager.EndPageText 
= "末页";
                    aspNetPager.LabelStyle.ForeColor 
= Color.Blue;
                    aspNetPager.LabelStyle.Font.Bold 
= true;
                    aspNetPager.TextBoxStyle.CssClass 
= "blue_rounded";
                    aspNetPager.TextBoxStyle.Width 
= Unit.Parse("40px");
                    aspNetPager.PageSize 
= 20;
                    aspNetPager.RecordCount 
= 0;
                }


            }

            
else
            
{
                
throw new Exception("The method or operation is not implemented.");
            }

        }

    }

}

然后在AspNetPagerDesigner类中加入默认样式,代码如下:

using  System;
using  System.Collections.Generic;
using  System.Text;
using  System.Web;
using  System.Web.UI;
using  System.Web.UI.WebControls;
using  System.ComponentModel;
using  System.Web.UI.Design;
using  System.ComponentModel.Design;
namespace  CustomControls
{
    [SupportsPreviewControl(
true)]
    
public class AspNetPagerDesigner : ControlDesigner
    
{
        
private DesignerAutoFormatCollection _dafc;
        
public override DesignerAutoFormatCollection AutoFormats
        
{
            
get
            
{
                
if (_dafc == null)
                
{
                    _dafc 
= new DesignerAutoFormatCollection();
                    _dafc.Add(
new AspNetPagerAutoFormat("英文样式"));
                    _dafc.Add(
new AspNetPagerAutoFormat("符号样式"));
                    _dafc.Add(
new AspNetPagerAutoFormat("默认样式"));
                }

                
return _dafc;
            }

        }

        
public override DesignerActionListCollection ActionLists
        
{
            
get
            
{
                DesignerActionListCollection actionLists 
= new DesignerActionListCollection();
                actionLists.Add(
new AspNetPagerActionList(this));

                
return actionLists;
            }

        }
  
    }

}

设计效果如下:

当点击默认样式的时候,发现分页控件里面的“首页”,“上一页”等分页文本不见了。这种情况很让人纳闷。

我想了很久也没找出是什么原因造成的。

而我去掉以下代码中的ToolboxData("<{0}:AspNetPager runat='server' PageSize='25' FirstPageText='首页' PrePageText='上一页' NextPageText='下一页' EndPageText='末页' ButtonText='GO'></{0}:AspNetPager>")出现了以下错误,如图所示:

 [Designer( typeof (AspNetPagerDesigner)),ToolboxData( " <{0}:AspNetPager runat='server' PageSize='25' FirstPageText='首页' PrePageText='上一页' NextPageText='下一页' EndPageText='末页' ButtonText='GO'></{0}:AspNetPager> " )]

最后我通过在构造函数里对相关属性进行初始化才解决了这个问题。

 

public  AspNetPager()
        
{
            PageIndex 
= 1;
            PageSize 
= 20;
            FirstPageText 
= "首页";
            PrePageText 
= "上一页";
            NextPageText 
= "下一页";
            EndPageText 
= "末页";
            ButtonText 
= "GO";
        }

效果如下:

原因我一直没能搞明白,希望了解的兄弟告诉一下,谢谢!

二、增加分页模式

在分页控件中加入一个属性PageMode,类型为枚举:

 

 [Category( " Behavior " ),Description( " 设置分页模式 " ),DefaultValue(AspNetPageMode.Comprehensive)]
        
public   virtual  AspNetPageMode PageMode
        
{
            
get
            
{
                
return ViewState["PageMode"!= null ? (AspNetPageMode)ViewState["PageMode"] : AspNetPageMode.Comprehensive;
            }

            
set
            
{
                ViewState[
"PageMode"= value;
            }

        }

其中AspNetPageMode定义如下:

 

using  System;
using  System.Collections.Generic;
using  System.Text;

namespace  CustomControls
{
    
/// <summary>
    
/// 分页模式
    
/// </summary>

    public enum AspNetPageMode
    
{
        Comprehensive
=0,//综合分页(即普通分页与数字分页的综合
        Normal=1,//普通分页

    }

}

分页模式分综合分页模式和普通分页模式,通过设置改属性,可以选取自己需要的分页模式。

在RenderContents(HtmlTextWriter writer)方法里加入判断:

 

if  (PageMode  ==  AspNetPageMode.Comprehensive)
            
{
                
if (_lblPageCount.Text == "")
                
{
                    
for (int i = 0; i < 10; i++)
                    
{
                        LinkButton lb 
= (LinkButton)this.FindControl("_page_" + i.ToString());
                        lb.Enabled 
= false;
                        lb.Text 
= (i + 1).ToString();
                        lb.RenderControl(writer);
                        writer.Write(
"&nbsp;");

                    }

                }

                
else
                
{
                    
int pageCount = int.Parse(_lblPageCount.Text);
                    
int quot = PageIndex / 10;
                    
int rema = PageIndex % 10;
                    
if (pageCount < 10 || pageCount - PageIndex < 10)
                    
{
                        
for (int i = quot * 10 + 1; i <= pageCount; i++)
                        
{
                            LinkButton lb2 
= (LinkButton)this.FindControl("_page_" + (i % 10).ToString());
                            lb2.Text 
= i.ToString();
                            
if (i == PageIndex)
                            
{
                                lb2.Enabled 
= false;
                                lb2.Font.Bold 
= true;
                                lb2.ForeColor 
= Color.Red;
                            }

                            
else
                            
{
                                lb2.Enabled 
= true;
                            }

                            lb2.RenderControl(writer);
                            writer.Write(
"&nbsp;");
                        }

                    }

                    
else
                    
{
                        
for (int i = quot * 10 + 1; i <= quot * 10 + 10; i++)
                        
{
                            LinkButton lb2 
= (LinkButton)this.FindControl("_page_" + (i % 10).ToString());
                            lb2.Text 
= i.ToString();
                            
if (i == PageIndex)
                            
{
                                lb2.Enabled 
= false;
                                lb2.Font.Bold 
= true;
                                lb2.ForeColor 
= Color.Red;
                            }

                            
else
                            
{
                                lb2.Enabled 
= true;
                            }

                            lb2.RenderControl(writer);
                            writer.Write(
"&nbsp;");
                        }

                    }

                }

            }

设置PageMode分页效果如下:

三、完善设计时支持

请看下面的图,除了“自动套用格式”外,还多了一个标题:“设计时面板设置”,还有很多的属性设置,比如宽度,高度等,通过这个面板,我们可以进行快速的外观设计,提高了工作效率。而做到这些就需要继承DesignerActionList类来实现。

DesignerActionList为定义用于创建智能标记面板的项列表的类型提供基类,重载DesignerActionItemCollection GetSortedActionItems(),可以设置控件的属性(DesignerActionPropertyItem)、方法(DesignerActionMethodItem)等。这里主要用的DesignerActionPropertyItem类,代码如下:

 

using  System;
using  System.Collections.Generic;
using  System.Text;
using  System.Web;
using  System.Web.UI;
using  System.Web.UI.WebControls;
using  System.Drawing;
using  System.Web.UI.Design;
using  System.Web.UI.Design.WebControls;
using  System.ComponentModel;
using  System.ComponentModel.Design;
namespace  CustomControls
{
    
public class AspNetPagerActionList:DesignerActionList
    
{
        
private DesignerActionItemCollection _daic;
        
private AspNetPagerDesigner _designer;
        
public AspNetPagerActionList(AspNetPagerDesigner designer)
            : 
base(designer.Component)
        
{
            _designer 
= designer;
        }

        
属性
        
public override DesignerActionItemCollection GetSortedActionItems()
        
{
            
if (_daic == null)
            
{
                _daic 
= new DesignerActionItemCollection();
                _daic.Add(
new DesignerActionHeaderItem("设计时面板设置"));
                _daic.Add(
new DesignerActionPropertyItem("Visible","是否显示"));
                _daic.Add(
new DesignerActionPropertyItem("ButtonText""转到按钮文字"));
                _daic.Add(
new DesignerActionPropertyItem("FirstPageText""首页文本"));
                _daic.Add(
new DesignerActionPropertyItem("PrePageText""上一页文本"));
                _daic.Add(
new DesignerActionPropertyItem("NextPageText""下一页文本"));
                _daic.Add(
new DesignerActionPropertyItem("EndPageText""末页文本"));
                _daic.Add(
new DesignerActionPropertyItem("PageSize""每页记录数"));
                _daic.Add(
new DesignerActionPropertyItem("Width","宽度"));
                _daic.Add(
new DesignerActionPropertyItem("Height""高度"));
                _daic.Add(
new DesignerActionPropertyItem("BackColor","背景色"));
                _daic.Add(
new DesignerActionPropertyItem("BorderStyle""边框类型"));
                _daic.Add(
new DesignerActionPropertyItem("BorderColor""边框颜色"));
                _daic.Add(
new DesignerActionPropertyItem("BorderWidth""边框宽度"));
            }

            
return _daic;
        }

    }

}

然后在AspNetPagerDesigner类重载属性ActionLists,把AspNetPagerActionList加入设计器里。如下面代码的粗体字所示

 

using  System;
using  System.Collections.Generic;
using  System.Text;
using  System.Web;
using  System.Web.UI;
using  System.Web.UI.WebControls;
using  System.ComponentModel;
using  System.Web.UI.Design;
using  System.ComponentModel.Design;
namespace  CustomControls
{
    [SupportsPreviewControl(
true)]
    
public class AspNetPagerDesigner : ControlDesigner
    
{
        
private DesignerAutoFormatCollection _dafc;
        
public override DesignerAutoFormatCollection AutoFormats
        
{
            
get
            
{
                
if (_dafc == null)
                
{
                    _dafc 
= new DesignerAutoFormatCollection();
                    _dafc.Add(
new AspNetPagerAutoFormat("英文样式"));
                    _dafc.Add(
new AspNetPagerAutoFormat("符号样式"));
                    _dafc.Add(
new AspNetPagerAutoFormat("默认样式"));
                }

                
return _dafc;
            }

        }

        
public override DesignerActionListCollection ActionLists
        
{
            
get

            
{
                DesignerActionListCollection actionLists 
= new
 DesignerActionListCollection();
                actionLists.Add(
new AspNetPagerActionList(this
));

                
return
 actionLists;
            }

        }
  
    }

}

到这里,一个分页控件基本上算是完成了,这里面考虑的了几点:

一是分页的实现:

分页有普通分页模式(即上一页、下一页等),还有综合分页模式(即在普通模式的基础上加了数字分页),基本上能满足常用的分页需求。

二是设计时支持:

修正了设计时支持的一些显示错误的问题,增加了“自动套用格式”和“属性列表”,可以快速定制自己的样式。

提供自定义样式支持,可以通过LinkButtonStyle,TextBoxStyle,LabelStyle,ButtonStyle等复杂属性来定制自己需要的样式,如图所示:

看字面意思就知道,LinkButtonStyle就是设置按钮LinkButton的样式,像数字分页,上一页,下一页等用的都是这个按钮。

三、安全性方面

主要集中于数字分页按钮LinkButton和跳转一块,如果用户输入的是非法字符,分页控件将会提示用户“非法页码”并返回,其他安全性方面有待进一步的研究。

 

protected   void  CurrentPage_Click( object  sender, EventArgs e)
        
{
            
string strID = ((LinkButton)sender).ID;
            
if (strID != "")
            
{
                
int pageIndex = 0;
                
int pageNum = PageIndex / 10;
                
try
                
{
                    
int pageNum2 = int.Parse(strID.Split('_')[2]);
                    
if (pageNum2 == 0)
                        pageNum2 
= 10;
                    pageIndex 
= pageNum2 + pageNum*10;
                }

                
catch
                
{
                    System.Web.HttpContext.Current.Response.Write(
"<Script>alert('非法的页码!');</script>");
                    
return;
                }

                _lblCurrentPage.Text 
= pageIndex.ToString();
                OnPageChanged(EventArgs.Empty);
            }

        }

/// <summary>
        
/// 跳转到指定页
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>

         protected   void  BtnChangePage_Click( object  sender, EventArgs e)
        
{
            
int pageIndex = 0;
            
try
            
{
                pageIndex 
= int.Parse(_txtPageIndex.Text);
            }

            
catch
            
{
                System.Web.HttpContext.Current.Response.Write(
"<Script>alert('请输入正确的页数!');</script>");
                
return;
            }

            
int pageCount = int.Parse(_lblPageCount.Text);
            
if (pageIndex == 0)//如果为0,则提示错误
            {
                System.Web.HttpContext.Current.Response.Write(
"<Script>alert('请输入正确的页数!');</script>");
                
return;
            }

            
if (pageIndex > pageCount)//如果大于总页数则提示错误
            {
                System.Web.HttpContext.Current.Response.Write(
"<Script>alert('请输入正确的页数!');</script>");
                
return;
            }

            _lblCurrentPage.Text 
= pageIndex.ToString();
            OnPageChanged(EventArgs.Empty);
        }

四、分页性能方面

以下是在我机子上的测试:查询1000万条数据,每页查询15条记录,40万页以下基本在1秒以内,,40万页以上也就两三秒左右。

当然这主要归功于存储过程写得好,但是如果分页代码写得不好也会影响分页速度。我的做法是记录当前页码,根据当前页码来显示相应的数字页码,比如当前页码是23页,则显示21到30页,并且23页灰显,粗体。除了可以突出显示页面,还可以避免重复点击造成不必要的数据传输。上一页,下一页等分页方式也做了相应的判断。

五、关于删除记录导致总记录数变化的问题

可以通过以下代码来解决这个问题,如粗体代码所示,如果删除成功,则调用TestDataCount()该方法重新统计总记录数,总页数

  删除纪录

六、通用性

适用于GridView,DataGrid,DataList,Repeater等数据绑定控件,其中使用GridView分页效果如下:


需要分页控件源代码和使用示例的,请到这里来下载:

http://d.download.csdn.net/down/408122/46539492

 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值