public string BindToControl { get { if (_bindcontrol == null) throw new NullReferenceException("在使用分页控件之前,请先通过设置BindToControl属性绑定到一个控件。"); return _bindcontrol;} set{_bindcontrol=value;} } |
protected override void OnInit(EventArgs e) { _boundcontrol = Parent.FindControl(BindToControl); BoundControl.DataBinding += new EventHandler(BoundControl_DataBound); base.OnInit(e); ... } |
private void BoundControl_DataBound(object sender,System.EventArgs e) { if (HasParentControlCalledDataBinding) return; Type type = sender.GetType(); _datasource = type.GetProperty("DataSource"); if (_datasource == null) throw new NotSupportedException("分页控件要求表现控件必需包含一个DataSource。"); object data = _datasource.GetGetMethod().Invoke(sender,null); _builder = Adapters[data.GetType()]; if (_builder == null) throw new NullReferenceException("没有安装适当的适配器来处理下面的数据源类型:"+data.GetType()); _builder.Source = data; ApplyDataSensitivityRules(); BindParent(); RaiseEvent(DataUpdate,this); } |
publicinterface IDataSourceAdapter { int TotalCount{get;} object GetPagedData(int start,int end); } |
internal class DataViewAdapter:IDataSourceAdapter { private DataView _view; internal DataViewAdapter(DataView view) { _view = view; } public int TotalCount { get{return (_view == null) ? 0 : _view.Table.Rows.Count;} } public object GetPagedData(int start, int end) { DataTable table = _view.Table.Clone(); for (int i = start;i<=end && i<= TotalCount;i++) { table.ImportRow(_view[i-1].Row); } return table; } } |
public abstract class AdapterBuilder { private object _source; private void CheckForNull() { if (_source == null) throw new NullReferenceException("必须提供一个合法的数据源"); } public virtual object Source { get { CheckForNull(); return _source;} set { _source = value; CheckForNull(); } } public abstract IDataSourceAdapter Adapter{get;} } |
public class DataTableAdapterBuilder:AdapterBuilder { private DataViewAdapter _adapter; private DataViewAdapter ViewAdapter { get { if (_adapter == null) { DataTable table = (DataTable)Source; _adapter = new DataViewAdapter(table.DefaultView); } return _adapter; } } public override IDataSourceAdapter Adapter { get { return ViewAdapter; } } } public class DataViewAdapterBuilder:AdapterBuilder { private DataViewAdapter _adapter; private DataViewAdapter ViewAdapter { get { // 延迟实例化 if (_adapter == null) { _adapter = new DataViewAdapter((DataView)Source); } return _adapter; } } public override IDataSourceAdapter Adapter { get{return ViewAdapter;} } } |
public class AdapterCollection:DictionaryBase { private string GetKey(Type key) { return key.FullName; } public AdapterCollection() {} publicvoid Add(Type key,AdapterBuilder value) { Dictionary.Add(GetKey(key),value); } publicbool Contains(Type key) { return Dictionary.Contains(GetKey(key)); }[page] publicvoid Remove(Type key) { Dictionary.Remove(GetKey(key)); } public AdapterBuilder this[Type key] { get{return (AdapterBuilder)Dictionary[GetKey(key)];} set{Dictionary[GetKey(key)]=value;} } } |
public AdapterCollection Adapters { get{return _adapters;} } private bool HasParentControlCalledDataBinding { get{return _builder != null;} } private void BoundControl_DataBound(object sender,System.EventArgs e) { if (HasParentControlCalledDataBinding) return; Type type = sender.GetType(); _datasource = type.GetProperty("DataSource"); if (_datasource == null) throw new NotSupportedException("分页控件要求表现控件必需包含一个DataSource。"); object data = _datasource.GetGetMethod().Invoke(sender,null); _builder = Adapters[data.GetType()]; if (_builder == null) throw new NullReferenceException("没有安装适当的适配器来处理下面的数据源类型:"+data.GetType()); _builder.Source = data; ApplyDataSensitivityRules(); BindParent(); RaiseEvent(DataUpdate,this); } |
public Pager() { SelectedPager=new System.Web.UI.WebControls.Style(); UnselectedPager = new System.Web.UI.WebControls.Style(); _adapters = new AdapterCollection(); _adapters.Add(typeof(DataTable),new DataTableAdapterBuilder()); _adapters.Add(typeof(DataView),new DataViewAdapterBuilder()); } |
private void BindParent() { _datasource.GetSetMethod().Invoke(BoundControl, new object[]{_builder.Adapter.GetPagedData(StartRow,ResultsToShow*CurrentPage)}); } |
public ImageButton FirstButton{get {return First;}} public ImageButton LastButton{get {return Last;}} public ImageButton PreviousButton{get {return Previous;}} public ImageButton NextButton{get {return Next;}} |
[Template Container(typeof(LayoutContainer))] public ITemplate Layout { get{return (_layout;} set{_layout =value;} } public class LayoutContainer:Control,INamingContainer { public LayoutContainer() {this.ID = "Page";} } |
<LAYOUT> <asp:ImageButton id="First" Runat="server" imageUrl="play2L_dis.gif" AlternateText="首页"></asp:ImageButton> <asp:ImageButton id="Previous" Runat="server" imageUrl="play2L.gif" AlternateText="上一页"></asp:ImageButton> <asp:ImageButton id="Next" Runat="server" imageUrl="play2.gif" AlternateText="下一页"></asp:ImageButton> <asp:ImageButton id="Last" Runat="server" imageUrl="play2_dis.gif" AlternateText="末页"></asp:ImageButton> <asp:Panel id="Pager" Runat="server"></asp:Panel> </LAYOUT> |
private void InstantiateTemplate() { _container = new LayoutContainer(); Layout.InstantiateIn(_container); First = (ImageButton)_container.FindControl("First"); Previous = (ImageButton)_container.FindControl("Previous"); Next = (ImageButton)_container.FindControl("Next"); Last = (ImageButton)_container.FindControl("Last"); Holder = (Panel)_container.FindControl("Pager"); this.First.Click += new System.Web.UI.ImageClickEventHandler(this.First_Click); this.Last.Click += new System.Web.UI.ImageClickEventHandler(this.Last_Click); this.Next.Click += new System.Web.UI.ImageClickEventHandler(this.Next_Click); this.Previous.Click += new System.Web.UI.ImageClickEventHandler(this.Previous_Click); } |
protected override void OnInit(EventArgs e) { _boundcontrol = Parent.FindControl(BindToControl); BoundControl.DataBinding += new EventHandler(BoundControl_DataBound); InstantiateTemplate(); Controls.Add(_container); base.OnInit(e); } |
public class DefaultPagerLayout:ITemplate { private ImageButton Next; private ImageButton First; private ImageButton Last; private ImageButton Previous; private Panel Pager; public DefaultPagerLayout() { Next = new ImageButton(); First = new ImageButton(); Last = new ImageButton(); Previous = new ImageButton(); Pager = new Panel(); Next.ID="Next"; Next.AlternateText="下一页";Next.ImageUrl="play2.gif"; First.ID="First"; First.AlternateText="首页";First.ImageUrl="play2L_dis.gif"; Last.ID = "Last"; Last.AlternateText ="末页";Last.ImageUrl="play2_dis.gif"; Previous.ID="Previous"; Previous.AlternateText="上一页";Previous.ImageUrl="play2L.gif"; Pager.ID="Pager"; } public void InstantiateIn(Control control) { control.Controls.Clear(); Table table = new Table(); table.BorderWidth = Unit.Pixel(0); table.CellSpacing= 1; table.CellPadding =0; TableRow row = new TableRow(); row.VerticalAlign = VerticalAlign.Top; table.Rows.Add(row); TableCell cell = new TableCell(); cell.HorizontalAlign = HorizontalAlign.Right; cell.VerticalAlign = VerticalAlign.Middle; cell.Controls.Add(First); cell.Controls.Add(Previous); row.Cells.Add(cell); cell = new TableCell(); cell.HorizontalAlign= HorizontalAlign.Center; cell.Controls.Add(Pager); row.Cells.Add(cell); cell = new TableCell(); cell.VerticalAlign = VerticalAlign.Middle; cell.Controls.Add(Next); cell.Controls.Add(Last); row.Cells.Add(cell); control.Controls.Add(table); } } |
[TemplateContainer(typeof(LayoutContainer))] public ITemplate Layout { get{return (_layout == null)? new DefaultPagerLayout():_layout;} set{_layout =value;} } |
public int CurrentPage { get { string cur = (string)ViewState["CurrentPage"]; return (cur == string.Empty || cur ==null)? 1 : int.Parse(cur); } set { ViewState["CurrentPage"] = value.ToString();} } public int PagersToShow { get{return _results;} set{_results = value;} } public int ResultsToShow { get{return _resultsperpage;} set{_resultsperpage = value;} } |
private int PagerSequence { get { return Convert.ToInt32 (Math.Ceiling((double)CurrentPage/(double)PagersToShow));} } private int NumberOfPagersToGenerate { get{return PagerSequence*PagersToShow;} } private int TotalPagesToShow { get{return Convert.ToInt32(Math.Ceiling((double)TotalResults/(double)_resultsperpage));} } public int TotalResults { get{return _builder.Adapter.TotalCount;} } |
public Style UnSelectedPagerStyle {get {return UnselectedPager;}} public Style SelectedPagerStyle {get {return SelectedPager;}} |
private void GeneratePagers(WebControl control) { control.Controls.Clear(); int pager = (PagerSequence-1)* PagersToShow +1; for (;pager<=NumberOfPagersToGenerate && pager<=TotalPagesToShow;pager++) { LinkButton link = new LinkButton(); link.Text = pager.ToString(); link.ID = pager.ToString(); link.Click += new EventHandler(this.Pager_Click); if (link.ID.Equals(CurrentPage.ToString())) link.MergeStyle(SelectedPagerStyle); else link.MergeStyle(UnSelectedPagerStyle); control.Controls.Add(link); control.Controls.Add(new LiteralControl(" ")); } } private void GeneratePagers() { GeneratePagers(Holder); } |
private void Pager_Click(object sender, System.EventArgs e) { LinkButton button = (LinkButton) sender; CurrentPage = int.Parse(button.ID); RaiseEvent(PageChanged, this,new PageChangedEventArgs(CurrentPage,PagedEventInvoker.Pager)); Update(); } private void Next_Click(object sender, System.Web.UI.ImageClickEventArgs e) { if (CurrentPage<TotalPagesToShow) CurrentPage++; RaiseEvent(PageChanged, this,new PageChangedEventArgs(CurrentPage,PagedEventInvoker.Next)); Update(); } private void Previous_Click(object sender, System.Web.UI.ImageClickEventArgs e) { if (CurrentPage > 1) CurrentPage--; RaiseEvent(PageChanged, this,new PageChangedEventArgs(CurrentPage,PagedEventInvoker.Previous)); Update(); } private void First_Click(object sender, System.Web.UI.ImageClickEventArgs e) { CurrentPage = 1; RaiseEvent(PageChanged, this,new PageChangedEventArgs(CurrentPage,PagedEventInvoker.First)); Update(); } private void Last_Click(object sender, System.Web.UI.ImageClickEventArgs e) { CurrentPage = TotalPagesToShow; RaiseEvent(PageChanged, this,new PageChangedEventArgs(CurrentPage,PagedEventInvoker.Last)); Update(); } |
private void Update() { if (!HasParentControlCalledDataBinding) return; ApplyDataSensitivityRules(); BindParent(); BoundControl.DataBind(); } |
public bool IsDataSensitive { get{return _isdatasensitive;} set{_isdatasensitive = value;} } private bool IsPagerVisible { get{return (TotalPagesToShow != 1) && IsDataSensitive;} } private bool IsPreviousVisible { get { return (!IsDataSensitive)? true: (CurrentPage != 1); } } private bool IsNextVisible { get { return (!IsDataSensitive)? true: (CurrentPage != TotalPagesToShow); } } private void ApplyDataSensitivityRules() { FirstButton.Visible = IsPreviousVisible; PreviousButton.Visible = IsPreviousVisible; LastButton.Visible = IsNextVisible; NextButton.Visible = IsNextVisible; if (IsPagerVisible) GeneratePagers(); } |
public delegate void PageDelegate(object sender,PageChangedEventArgs e); public enum PagedEventInvoker{Next,Previous,First,Last,Pager} public class PageChangedEventArgs:EventArgs { private int newpage; private Enum invoker; public PageChangedEventArgs(int newpage):base() { this.newpage = newpage; } public PageChangedEventArgs(int newpage,PagedEventInvoker invoker) { this.newpage = newpage; this.invoker = invoker; } public int NewPage {get{return newpage;}} public Enum EventInvoker{get{return invoker;}} } |
public event PageDelegate PageChanged; public event EventHandler DataUpdate; |
private void RaiseEvent(EventHandler e,object sender) { this.RaiseEvent(e,this,null); } private void RaiseEvent(EventHandler e,object sender, PageChangedEventArgs args) { if(e!=null) { e(sender,args); } } private void RaiseEvent(PageDelegate e,object sender) { this.RaiseEvent(e,this,null); } private void RaiseEvent(PageDelegate e,object sender, PageChangedEventArgs args) { if(e!=null) { e(sender,args); } } |
<asp:Repeater ID="repeater" Runat="server"> <ItemTemplate> 列1: <%# Convert.ToString(DataBinder.Eval(Container.DataItem,"Column1"))%> <br> 列2: <%# Convert.ToString(DataBinder.Eval(Container.DataItem,"Column2"))%> <br> 列3: <%# Convert.ToString(DataBinder.Eval(Container.DataItem,"Column3"))%> <br> <hr> </ItemTemplate> </asp:Repeater> <cc1:Pager id="pager" ResultsToShow="2" runat="server" BindToControl="repeater"> <SELECTEDPAGERSTYLE BackColor="Yellow" /> </cc1:Pager> |
<asp:DataGrid ID="Grid" Runat="server"></asp:DataGrid> <cc1:Pager id="PagerGrid" ResultsToShow="2" runat="server" BindToControl="Grid"> <SELECTEDPAGERSTYLE BackColor="Red"></SELECTEDPAGERSTYLE> <LAYOUT> <asp:ImageButton id="First" Runat="server" imageUrl="play2L_dis.gif" AlternateText="首页"></asp:ImageButton> <asp:ImageButton id="Previous" Runat="server" imageUrl="play2L.gif" AlternateText="上一页"></asp:ImageButton> <asp:ImageButton id="Next" Runat="server" imageUrl="play2.gif" AlternateText="下一页"></asp:ImageButton> <asp:ImageButton id="Last" Runat="server" imageUrl="play2_dis.gif" AlternateText="末页"></asp:ImageButton> <asp:Panel id="Pager" Runat="server"></asp:Panel> </LAYOUT> </cc1:Pager> |
测试表明,分页控件并不依赖于特定的表现控件,它可以方便地处理不同的数据源,而且很容易使用,请读者下载本文后面的源代码参见完整的例子。
虽然学习开发自定义Web控件不是一件轻松的事情,但掌握这项技能带来的好处不言而喻,只要稍微增加一些工作量,开发者就可以将普通的Web控件改换成多用途的通用控件,数十倍地提高工作效率,本文的分页控件只是创建通用控件来满足现有和将来表现需要的其中一个例子而已。
下载本文的代码:AspNetPagerControl_code.zip
上面的代码我也没找到,有找到的对我说一下把