很多朋友都在问.NET控件开发 到底有多难,其实可以轻松的告诉大家有恒心就能成绩来着,最好的控件全部在你身边,想开发高效好用的空间那就必须参考微软本身优秀的控件.为此我们手头要有一个好的工具Reflector.exe,这个大名鼎鼎的Reflector 你还不知道的话,只能被笑话了,对于控件的使用我初略的给.NET 控件使用开发人员分了一个等级: 1. 会使用ASP.NET 控件(简单的自定义控件,还有服务器控件),对事件=其他知识完全没有概念 2. 掌握了页面事件的初步框架,能在不同事件中处理控件逻辑 3. 开发控件,运用属性以及理解HtmlTextWriter 输出的基本特性 4. 开发复杂控件,整合CSS,JS 以及缓存,主题==各种功能的 综合性控件 看看你自己处于那个阶段,是不是还停留在只会用用GridView ==控件的一些初级阶段呢?其实想摆脱现状就必须从整个页面事件去了解,对于页面事件我会在接下来的文章好好给大家分析来着. 通过本文希望大家从控件开发中,深入理解 .NET 页面事件,以及各种控件开发中的设计模式(其实透过.NET FRAMEWORK中的Controls类的设计就能明白微软的意图),以及委托在事件中的使用,和一些基本的正则使用.当然最后是控件的完美开发咯 废话不多说.先给大家分析一个 我们经常用到的控件ASP.NET Button 控件 我们打开Reflector找到 System.Web.UI.WebControls这个命名控件,然后找到Button控件,我们展开 我这里和大家讲讲分别是什么意思就好了 其他的大家自己去看了 不过不理解的 我们可以一起讨论,还可以为你解释一下,那些控件我基本通看了一下 嘿嘿 Base Types 是他的基本类型,Derived Types 是他的派生类,红色的那些图标是她的 方法,带有手的图标是 属性,闪电的图标是 事件 ,.ctor() 就是构造函数 cctor 就是静态构造函数,EventClick ,和 EventCommand 是类成员 .好了 基本就这样了 大家有什么不明白的可以在这里提问,我也会及时回答的.其实 Button 控件包含的意义很深,看明白了 对以后的控件开发有很大的帮助 比如他的
找到Button 控件, 然后继续展开Button,
|
|
这个方法 就很好的展示给大家 ASP.NET 只如何处理INPUT 各种属性的呢.
这个控件是支持Url 分页的
当然 原理 是利用IList 的索引 取不同”页”的数据 对于偷懒和后台管理很方便,至于前台的分页我想你更喜欢用存储过程 的ROW_NUMBER() 和 IDENTITY 方案来分页吧
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Text.RegularExpressions;
using System.Collections;
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:YsmvRepeater runat=\"server\" AllowPage=\"true\" PageSize=\"10\" ShowPage=\"true\"></{0}:YsmvRepeater>")]
public class YsmvRepeater : Repeater
{
//Static param
private static readonly Regex RX;
private static readonly object EventPageChanged;
{
RX = new Regex(@"^&page=\d+", RegexOptions.Compiled);
EventPageChanged = new object();
}
protected const string HTML1 = "<table cellpadding=0 cellspacing=0 class='inputTable'><tr><td colspan=2>";
protected const string HTML2 = "</td></tr><tr><td class=paging align=left>";
protected const string HTML3 = "</td><td align=right class=paging>";
protected const string HTML4 = "</td></tr></table>";
private const string LINK_PREV = "<a href=?page={0}>< Previous</a>";
private const string LINK_MORE = "<a href=?page={0}>More ></a>";
private const string KEY_PAGE = "page";
private const string COMMA = "?";
private const string AMP = "&";
private IList dataSource;
private int pageSize = 10;
private int currentPageIndex;
private int itemCount;
private bool allowPage = false;
private bool showPage = true;
, Category("Appearance"),
DefaultValue(true),
Description("是否显示翻页链接")
]
public bool ShowPage
{
get { return showPage; }
set { showPage = value; }
}
[Browsable(true),
Category("Appearance"),
DefaultValue(true),
Description("是否允许分页")]
public bool AllowPage
{
get { return allowPage; }
set { allowPage = value; }
}
[Browsable(true),
Category("Appearance"),
DefaultValue(10),
Description("每页显示的数量")
]
public int PageSize
{
get { return pageSize; }
set { pageSize = value; }
}
[Browsable(true),
Category("Appearance"),
DefaultValue(""),
Description("无记录时候显示的内容")]
public string EmptyText
{
set { emptyText = value; }
}
override public object DataSource
{
set
{
//This try catch block is to avoid issues with the VS.NET designer
//The designer will try and bind a datasource which does not derive from ILIST
try
{
dataSource = (IList)value;
ItemCount = dataSource.Count;
}
catch
{
dataSource = null;
ItemCount = 0;
}
}
}
protected int PageCount
{
get { return (ItemCount - 1) / pageSize; }
}
{
get { return itemCount; }
set
{itemCount = value;}
}
{
get { return currentPageIndex; }
set { currentPageIndex = value; }
}
{
//OnPageIndexChanged(new DataGridPageChangedEventArgs(null, index));
OnPageIndexChanged(new GridViewPageEventArgs(index));
}
{
if (Visible)
{
string page = Context.Request[KEY_PAGE];
int index = (page != null) ? int.Parse(page) : 0;
SetPage(index);
}
}
/// Overriden method to control how the page is rendered
/// </summary>
/// <param name="writer"></param>
override protected void Render(HtmlTextWriter writer)
{
string page = Context.Request[KEY_PAGE];
int index = (page != null) ? int.Parse(page) : 0;
if (ItemCount == 0)
{
writer.Write(emptyText);
return;
}
//Mask the query
string query = Context.Request.Url.Query.Replace(COMMA, AMP);
query = RX.Replace(query, string.Empty);
writer.Write(HTML1);
base.Render(writer);
writer.Write(HTML2);
//Previous button?
if (currentPageIndex > 0)
{
if (ShowPage)
writer.Write(string.Format(LINK_PREV, (currentPageIndex - 1) + query));
}
writer.Write(HTML3);
if (currentPageIndex < PageCount)
{
if (ShowPage)
writer.Write(string.Format(LINK_MORE, (currentPageIndex + 1) + query));
}
writer.Write(HTML4);
}
{
if (!allowPage)
{
base.DataSource = dataSource;
base.OnDataBinding(e);
return;
}
//Work out which items we want to render to the page
int start = CurrentPageIndex * pageSize;
int size = Math.Min(pageSize, ItemCount - start);
for (int i = 0; i < size; i++)
page.Add(dataSource[start + i]);
base.DataSource = page;
base.OnDataBinding(e);
public event GridViewPageEventHandler PageIndexChanged
{
add
{
Events.AddHandler(EventPageChanged, value);
}
remove
{
Events.RemoveHandler(EventPageChanged, value);
}
}
virtual protected void OnPageIndexChanged(GridViewPageEventArgs e)
{
GridViewPageEventHandler pagehandler = (GridViewPageEventHandler)Events[EventPageChanged];
if (pagehandler != null)
pagehandler(this, e);
}
}
}
代码已经加了注释,细心的朋友 可能发现和 PETSHOP 中的控件很相似 ,对,我是用那个修改的,我优化了他的事件private static readonly object EventPageChanged; 呵呵.
下面分享我开发工程中的一个控件 namespace YSMV.XWShop1B2C.Control static YsmvRepeater() //Static constants protected string emptyText; [Browsable(true) virtual public int ItemCount virtual public int CurrentPageIndex public void SetPage(int index) override protected void OnLoad(EventArgs e) /// <summary> //Check there is some data attached // Write out the first part of the control, the table header // Call the inherited method // Write out a table row closure //Determin whether next and previous buttons are required //Close the table data tag //Next button? //Close the table override protected void OnDataBinding(EventArgs e) IList page = new ArrayList(); //Add the relevant items from the datasource //set the base objects datasource } //public event DataGridPageChangedEventHandler PageIndexChanged;