Free Programming

我的生活在一行又一行的代码中前行........

 

datagrid技巧大全


loading...
 
 

2006-3-30
当前行的背景色 [转]

Private Sub DataGrid1_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles DataGrid1.ItemDataBound
        If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then
            '添加自定义属性,当鼠标移过来时设置该行的背景色为"#eaeaea",并保存原背景色
            e.Item.Attributes.Add("onmouseover", "currentcolor=this.style.backgroundColor;this.style.backgroundColor='#eaeaea'"
            '添加自定义属性,当鼠标移走时还原该行的背景色
            e.Item.Attributes.Add("onmouseout", "this.style.backgroundColor=currentcolor"
        End If

    End Sub

loading...
 
 

2006-3-17
asp.net常用函数 [转]

Abs(number) 取得数值的绝对值。
Asc(String) 取得字符串表达式的第一个字符ASCII 码。
Atn(number) 取得一个角度的反正切值。
CallByName (object, procname, usecalltype,[args()]) 执行一个对象的方法、设定或传回对象的属性。
CBool(expression) 转换表达式为Boolean 型态。
CByte(expression) 转换表达式为Byte 型态。
CChar(expression) 转换表达式为字符型态。
CDate(expression) 转换表达式为Date 型态。
CDbl(expression) 转换表达式为Double 型态。
CDec(expression) 转换表达式为Decimal 型态。
CInt(expression) 转换表达式为Integer 型态。
CLng(expression) 转换表达式为Long 型态。
CObj(expression) 转换表达式为Object 型态。
CShort(expression) 转换表达式为Short 型态。
CSng(expression) 转换表达式为Single 型态。
CStr(expression) 转换表达式为String 型态。
Choose (index, choice-1[, choice-2, ... [, choice-n]]) 以索引值来选择并传回所设定的参数。
Chr(charcode) 以ASCII 码来取得字符内容。
Close(filenumberlist) 结束使用Open 开启的档案。
Cos(number) 取得一个角度的余弦值。
Ctype(expression, typename) 转换表达式的型态。
DateAdd(dateinterval, number, datetime) 对日期或时间作加减。
DateDiff(dateinterval, date1, date2) 计算两个日期或时间间的差值。
DatePart (dateinterval, date) 依接收的日期或时间参数传回年、月、日或时间。
DateSerial(year, month, day) 将接收的参数合并为一个只有日期的Date 型态的数据。
DateValue(datetime) 取得符合国别设定样式的日期值,并包含时间。
Day(datetime) 依接收的日期参数传回日。
Eof(filenumber) 当抵达一个被开启的档案结尾时会传回True。
Exp(number) 依接收的参数传回e 的次方值。
FileDateTime(pathname) 传回档案建立时的日期、时间。
FileLen(pathname) 传回档案的长度,单位是Byte。
Filter(sourcearray, match[, include[, compare]]) 搜寻字符串数组中的指定字符串,凡是数组元素中含有指定字符串,会将它们结合成新的字符串数组并传回。若是要传回不含指定字符串的数组元素,则include 参数设为False。compare 参数则是设定搜寻时是否区分大小写,此时只要给TextCompare 常数或1 即可。
Fix(number) 去掉参数的小数部分并传回。
Format(expression[, style[, firstdayofweek[, firstweekofyear]]]) 将日期、时间和数值资料转为每个国家都可以接受的格式。
FormatCurrency(expression[,numdigitsafterdecimal [,includeleadingdigit]]) 将数值输出为金额型态。numdigitsafterdecimal 参数为小数字数,includeleadingdigit 参数为当整数为0 时是否补至整数字数。
FormatDateTime(date[,namedformat]) 传回格式化的日期或时间数据。
FormatNumber(expression[,numdigitsafterdecimal [,includeleadingdigit]]) 传回格式化的数值数据。Numdigitsafterdecimal 参数为小数字数,includeleadingdigit 参数为当整数为0 时是否补至整数字数。
FormatPercent(expression[,numdigitsafterdecimal [,includeleadingdigit]]) 传回转换为百分比格式的数值数据。numdigitsafterdecimal 参数为小数字数,includeleadingdigit 参数为当整数为0 时是否补至整数字数。
GetAttr(filename) 传回档案或目录的属性值。
Hex(number) 将数值参数转换为16 进制值。
Hour(time) 传回时间的小时字段,型态是Integer。
Iif(expression, truepart, falsepart) 当表达式的传回值为True 时执行truepart 字段的程序,反之则执行falsepart 字段。
InStr([start, ]string1, string2) 搜寻string2 参数设定的字符出现在字符串的第几个字符,start 为由第几个字符开始寻找,string1 为欲搜寻的字符串,string2 为欲搜寻的字符。
Int(number) 传回小于或等于接收参数的最大整数值。
IsArray(varname) 判断一个变量是否为数组型态,若为数组则传回True,反之则为False。
IsDate(expression) 判断表达式内容是否为DateTime 型态,若是则传回True,反之则为False。
IsDbNull(expression) 判断表达式内容是否为Null,若是则传回True,反之则为False。
IsNumeric(expression) 判断表达式内容是否为数值型态,若是则传回True,反之则为False。
Join(sourcearray[, delimiter]) 将字符串数组合并唯一个字符串,delimiter 参数是设定在各个元素间加入新的字符串。
Lcase(string) 将字符串转换为小写字体。
Left(string, length) 由字符串左边开始取得length 参数设定长度的字符。
Len(string) 取得字符串的长度。
Log(number) 取得数值的自然对数。
Ltrim(string) 去掉字符串的左边空白部分。
Mid(string, start[, length]) 取出字符串中strat 参数设定的字符后length 长度的字符串,若length 参数没有设定,则取回start 以后全部的字符。
Minute(time) 取得时间内容的分部分,型态为Integer。
MkDir(path) 建立一个新的目录。
Month(date) 取得日期的月部分,型态为Integer。
MonthName(month) 依接收的月份数值取得该月份的完整写法。
Now() 取得目前的日期和时间。
Oct(number) 将数值参数转换为8 进制值。
Replace(expression, find, replace) 将字符串中find 参数指定的字符串转换为replace 参数指定的字符串。
Right(string,length) 由字符串右边开始取得length 参数设定长度的字符。
RmDir(path) 移除一个空的目录。
Rnd() 取得介于0 到1 之间的小数,如果每次都要取得不同的值,使用前需加上Randomize 叙述。
Rtrim(string) 去掉字符串的右边空白部分。
Second(time) 取得时间内容的秒部分,型态为Integer。
Sign(number) 取得数值内容是正数或负数,正数传回1,负数传回-1,0 传回0。
Sin(number) 取得一个角度的正弦值。
Space(number) 取得number 参数设定的空白字符串。
Split(expression[, delimiter]) 以delimiter 参数设定的条件字符串来将字符串分割为字符串数组。
Sqrt(number) 取得一数值得平方根。
Str(number) 将数字转为字符串后传回。
StrReverse(expression) 取得字符串内容反转后的结果。
Tan(number) 取得某个角度的正切值。
TimeOfDay() 取得目前不包含日期的时间。
Timer() 取得由0:00 到目前时间的秒数,型态为Double。
TimeSerial(hour, minute, second) 将接收的参数合并为一个只有时间Date 型态的数据。
TimaValue(time) 取得符合国别设定样式的时间值。
Today() 取得今天不包含时间的日期。
Trim(string) 去掉字符串开头和结尾的空白。
TypeName(varname) 取得变量或对象的型态。
Ubound(arrayname[, dimension]) 取得数组的最终索引值,dimension 参数是指定取得第几维度的最终索引值。
Ucase(string) 将字符串转换为大写。
Val(string) 将代表数字的字符串转换为数值型态,若字符串中含有非数字的内容则会将其去除后,合并为一数字。
Weekday(date) 取的参数中的日期是一个星期的第几天,星期天为1、星期一为2、星期二为3 依此类推。
WeekDayName(number) 依接收的参数取得星期的名称,可接收的参数为1 到7,星期天为1、星期一为2、星期二为3 依此类推。
loading...
 
 

2006-3-17
ASP.NET程序中常用的三十三种代码

 1. 打开新的窗口并传送参数:

  传送参数:

response.write("<script>window.open(’*.ASPx?id="+this.DropDownList1.SelectIndex+"&id1="+...+"’)</script>"

  接收参数:

string a = Request.QueryString("id";
string b = Request.QueryString("id1";

  2.为按钮添加对话框

Button1.Attributes.Add("onclick","return confirm(’确认?’)";
button.attributes.add("onclick","if(confirm(’are you sure...?’)){return true;}else{return false;}"

  3.删除表格选定记录

int intEmpID = (int)MyDataGrid.DataKeys[e.Item.ItemIndex];
string deleteCmd = "DELETE from Employee where emp_id = " + intEmpID.ToString()

  4.删除表格记录警告

private void DataGrid_ItemCreated(Object sender,DataGridItemEventArgs e)
{
 switch(e.Item.ItemType)
 {
  case ListItemType.Item :
  case ListItemType.AlternatingItem :
  case ListItemType.EditItem:
   TableCell myTableCell;
   myTableCell = e.Item.Cells[14];
   LinkButton myDeleteButton ;
   myDeleteButton = (LinkButton)myTableCell.Controls[0];
   myDeleteButton.Attributes.Add("onclick","return confirm(’您是否确定要删除这条信息’);";
   break;
  default:
   break;
 }

}

  5.点击表格行链接另一页

private void grdCustomer_ItemDataBound(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e)
{
 //点击表格打开
 if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
  e.Item.Attributes.Add("onclick","window.open(’Default.aspx?id=" + e.Item.Cells[0].Text + "’);";
}

  双击表格连接到另一页

  在itemDataBind事件中

if(e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
 string OrderItemID =e.item.cells[1].Text;
 ...
 e.item.Attributes.Add("ondblclick", "location.href=’../ShippedGrid.aspx?id=" + OrderItemID + "’";
}

  双击表格打开新一页

if(e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
 string OrderItemID =e.item.cells[1].Text;
 ...
 e.item.Attributes.Add("ondblclick", "open(’../ShippedGrid.aspx?id=" + OrderItemID + "’)";
}

  ★特别注意:【?id=】 处不能为 【?id =】


6.表格超连接列传递参数

<ASP:HyPerlinkColumn Target="_blank" headertext="ID号" DataTextField="id" NavigateUrl="aaa.aspx?id=’
 <%# DataBinder.Eval(Container.DataItem, "数据字段1"%>’ & name=’<%# DataBinder.Eval(Container.DataItem, "数据字段2"%>’ />

  7.表格点击改变颜色

if (e.Item.ItemType == ListItemType.Item ||e.Item.ItemType == ListItemType.AlternatingItem)
{
 e.Item.Attributes.Add("onclick","this.style.backgroundColor=’#99cc00’;
    this.style.color=’buttontext’;this.style.cursor=’default’;";

  写在DataGrid的_ItemDataBound里

if (e.Item.ItemType == ListItemType.Item ||e.Item.ItemType == ListItemType.AlternatingItem)
{
e.Item.Attributes.Add("onmouseover","this.style.backgroundColor=’#99cc00’;
   this.style.color=’buttontext’;this.style.cursor=’default’;";
e.Item.Attributes.Add("onmouseout","this.style.backgroundColor=’’;this.style.color=’’;";
}


  8.关于日期格式

  日期格式设定

DataFormatString="{0:yyyy-MM-dd}"

  我觉得应该在itembound事件中

e.items.cell["你的列"].text=DateTime.Parse(e.items.cell["你的列"].text.ToString("yyyy-MM-dd")

  9.获取错误信息并到指定页面

  不要使用Response.Redirect,而应该使用Server.Transfer

  e.g

// in global.asax
protected void Application_Error(Object sender, EventArgs e) {
if (Server.GetLastError() is HttpUnhandledException)
Server.Transfer("MyErrorPage.aspx";

//其余的非HttpUnhandledException异常交给ASP.NET自己处理就okay了
}

  Redirect会导致post-back的产生从而丢失了错误信息,所以页面导向应该直接在服务器端执行,这样就可以在错误处理页面得到出错信息并进行相应的处理

  10.清空Cookie

Cookie.Expires=[DateTime];
Response.Cookies("UserName".Expires = 0

  11.自定义异常处理

//自定义异常处理类
using System;
using System.Diagnostics;

namespace MyAppException
{
 /// <summary>
 /// 从系统异常类ApplicationException继承的应用程序异常处理类。
 /// 自动将异常内容记录到Windows NT/2000的应用程序日志
 /// </summary>
 public class AppException:System.ApplicationException
 {
  public AppException()
  {
   if (ApplicationConfiguration.EventLogEnabled)LogEvent("出现一个未知错误。";
  }

 public AppException(string message)
 {
  LogEvent(message);
 }

 public AppException(string message,Exception innerException)
 {
  LogEvent(message);
  if (innerException != null)
  {
   LogEvent(innerException.Message);
  }
 }

 //日志记录类
 using System;
 using System.Configuration;
 using System.Diagnostics;
 using System.IO;
 using System.Text;
 using System.Threading;

 namespace MyEventLog
 {
  /// <summary>
  /// 事件日志记录类,提供事件日志记录支持
  /// <remarks>
  /// 定义了4个日志记录方法 (error, warning, info, trace)
  /// </remarks>
  /// </summary>
  public class ApplicationLog
  {
   /// <summary>
   /// 将错误信息记录到Win2000/NT事件日志中
   /// <param name="message">需要记录的文本信息</param>
   /// </summary>
   public static void WriteError(String message)
   {
    WriteLog(TraceLevel.Error, message);
   }

   /// <summary>
   /// 将警告信息记录到Win2000/NT事件日志中
   /// <param name="message">需要记录的文本信息</param>
   /// </summary>
   public static void WriteWarning(String message)
   {
    WriteLog(TraceLevel.Warning, message);  
   }

   /// <summary>
   /// 将提示信息记录到Win2000/NT事件日志中
   /// <param name="message">需要记录的文本信息</param>
   /// </summary>
   public static void WriteInfo(String message)
   {
    WriteLog(TraceLevel.Info, message);
   }
   /// <summary>
   /// 将跟踪信息记录到Win2000/NT事件日志中
   /// <param name="message">需要记录的文本信息</param>
   /// </summary>
   public static void WriteTrace(String message)
   {
    WriteLog(TraceLevel.Verbose, message);
   }

   /// <summary>
   /// 格式化记录到事件日志的文本信息格式
   /// <param name="ex">需要格式化的异常对象</param>
   /// <param name="catchInfo">异常信息标题字符串.</param>
   /// <retvalue>
   /// <para>格式后的异常信息字符串,包括异常内容和跟踪堆栈.</para>
   /// </retvalue>
   /// </summary>
   public static String FormatException(Exception ex, String catchInfo)
   {
    StringBuilder strBuilder = new StringBuilder();
    if (catchInfo != String.Empty)
    {
     strBuilder.Append(catchInfo).Append("\r\n";
    }
    strBuilder.Append(ex.Message).Append("\r\n".Append(ex.StackTrace);
    return strBuilder.ToString();
   }

   /// <summary>
   /// 实际事件日志写入方法
   /// <param name="level">要记录信息的级别(error,warning,info,trace).</param>
   /// <param name="messageText">要记录的文本.</param>
   /// </summary>
   private static void WriteLog(TraceLevel level, String messageText)
   {
    try
    {
     EventLogEntryType LogEntryType;
     switch (level)
     {
      case TraceLevel.Error:
       LogEntryType = EventLogEntryType.Error;
       break;
      case TraceLevel.Warning:
       LogEntryType = EventLogEntryType.Warning;
       break;
      case TraceLevel.Info:
       LogEntryType = EventLogEntryType.Information;
       break;
      case TraceLevel.Verbose:
       LogEntryType = EventLogEntryType.SuccessAudit;
       break;
      default:
       LogEntryType = EventLogEntryType.SuccessAudit;
       break;
     }

     EventLog eventLog = new EventLog("Application", ApplicationConfiguration.EventLogMachineName, ApplicationConfiguration.EventLogSourceName ;
     //写入事件日志
     eventLog.WriteEntry(messageText, LogEntryType);

    }
   catch {} //忽略任何异常
  }
 } //class ApplicationLog
}


12.Panel 横向滚动,纵向自动扩展

<ASPanel style="overflow-x:scroll;overflow-y:auto;"></aspanel>

  13.回车转换成Tab

<script language="JavaScript" for="document" event="onkeydown">
 if(event.keyCode==13 && event.srcElement.type!=’button’ && event.srcElement.type!=’submit’ &&     event.srcElement.type!=’reset’ && event.srcElement.type!=’’&& event.srcElement.type!=’textarea’);
   event.keyCode=9;
</script>

onkeydown="if(event.keyCode==13) event.keyCode=9"
 

  14.DataGrid超级连接列

DataNavigateUrlField="字段名" DataNavigateUrlFormatString="http://xx/inc/delete.aspx?ID={0}" 

  15.DataGrid行随鼠标变色

private void DGzf_ItemDataBound(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e)
{
 if (e.Item.ItemType!=ListItemType.Header)
 {
  e.Item.Attributes.Add( "onmouseout","this.style.backgroundColor=\""+e.Item.Style["BACKGROUND-COLOR"]+"\"";
  e.Item.Attributes.Add( "onmouseover","this.style.backgroundColor=\""+ "#EFF3F7"+"\"";
 }
}

  16.模板列

<ASP:TEMPLATECOLUMN visible="False" sortexpression="demo" headertext="ID">
<ITEMTEMPLATE>
<ASP:LABEL text=’<%# DataBinder.Eval(Container.DataItem, "ArticleID"%>’ runat="server" width="80%" id="lblColumn" />
</ITEMTEMPLATE>
</ASP:TEMPLATECOLUMN>

<ASP:TEMPLATECOLUMN headertext="选中">
<HEADERSTYLE wrap="False" horizontalalign="Center"></HEADERSTYLE>
<ITEMTEMPLATE>
<ASP:CHECKBOX id="chkExport" runat="server" />
</ITEMTEMPLATE>
<EDITITEMTEMPLATE>
<ASP:CHECKBOX id="chkExportON" runat="server" enabled="true" />
</EDITITEMTEMPLATE>
</ASP:TEMPLATECOLUMN>

  后台代码

protected void CheckAll_CheckedChanged(object sender, System.EventArgs e)
{
 //改变列的选定,实现全选或全不选。
 CheckBox chkExport ;
 if( CheckAll.Checked)
 {
  foreach(DataGridItem oDataGridItem in MyDataGrid.Items)
  {
   chkExport = (CheckBox)oDataGridItem.FindControl("chkExport";
   chkExport.Checked = true;
  }
 }
 else
 {
  foreach(DataGridItem oDataGridItem in MyDataGrid.Items)
  {
   chkExport = (CheckBox)oDataGridItem.FindControl("chkExport";
   chkExport.Checked = false;
  }
 }
}

  17.数字格式化

  【<%#Container.DataItem("price"%>的结果是500.0000,怎样格式化为500.00?】

<%#Container.DataItem("price","{0:¥#,##0.00}"%>

int i=123456;
string s=i.ToString("###,###.00";

18.日期格式化

  【ASPx页面内:<%# DataBinder.Eval(Container.DataItem,"Company_Ureg_Date"%>

  显示为: 2004-8-11 19:44:28

  我只想要:2004-8-11 】

<%# DataBinder.Eval(Container.DataItem,"Company_Ureg_Date","{0:yyyy-M-d}"%>

  应该如何改?

  【格式化日期】

  取出来,一般是object((DateTime)objectFromDB).ToString("yyyy-MM-dd";

  【日期的验证表达式】

  A.以下正确的输入格式: [2004-2-29], [2004-02-29 10:29:39 pm], [2004/12/31]

^((\d{2}(([02468][048])|([13579][26]))[\-\/\s]?((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|([1-2][0-9])))))|(\d{2}(([02468][1235679])|([13579][01345789]))[\-\/\s]?((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\s(((0?[1-9])|(1[0-2]))\[0-5][0-9])((\s)|(\[0-5][0-9])\s))([AM|PM|am|pm]{2,2})))?$

  B.以下正确的输入格式:[0001-12-31], [9999 09 30], [2002/03/03]

^\d{4}[\-\/\s]?((((0[13578])|(1[02]))[\-\/\s]?(([0-2][0-9])|(3[01])))|(((0[469])|(11))[\-\/\s]?(([0-2][0-9])|(30)))|(02[\-\/\s]?[0-2][0-9]))$ 

  【大小写转换】

HttpUtility.HtmlEncode(string);
HttpUtility.HtmlDecode(string)

  19.如何设定全局变量

  Global.asax中

  Application_Start()事件中

  添加Application[属性名] = xxx;

  就是你的全局变量

  20.怎样作到HyPerlinkColumn生成的连接后,点击连接,打开新窗口?

  HyperLinkColumn有个属性Target,将器值设置成"_blank"即可.(Target="_blank"

  【ASPNETMENU】点击菜单项弹出新窗口

  在你的menuData.XML文件的菜单项中加入URLTarget="_blank",如:

<?XML version="1.0" encoding="GB2312"?>
<MenuData ImagesBaseURL="images/">
<MenuGroup>
<MenuItem Label="内参信息" URL="Infomation.aspx" >
<MenuGroup ID="BBC">
<MenuItem Label="公告信息" URL="Infomation.aspx" URLTarget="_blank" LeftIcon="file.gif"/>
<MenuItem Label="编制信息简报" URL="NewInfo.aspx" LeftIcon="file.gif" />
......

  最好将你的aspnetmenu升级到1.2版

  21.读取DataGrid控件TextBox值

foreach(DataGrid dgi in yourDataGrid.Items)
{
 TextBox tb = (TextBox)dgi.FindControl("yourTextBoxId";
 tb.Text....
}

  23.在DataGrid中有3个模板列包含Textbox分别为 DG_ShuLiang (数量) DG_DanJian(单价) DG_JinE(金额)分别在5.6.7列,要求在录入数量及单价的时候自动算出金额即:数量*单价=金额还要求录入时限制为 数值型.我如何用客户端脚本实现这个功能?

  〖思归〗

<asp:TemplateColumn HeaderText="数量">
<ItemTemplate>
<asp:TextBox id="ShuLiang" runat=’server’ Text=’<%# DataBinder.Eval(Container.DataItem,"DG_ShuLiang"%>’
onkeyup="JavaScriptoCal()"
/>

<asp:RegularExpressionValidator id="revS" runat="server" ControlToValidate="ShuLiang" ErrorMessage="must be integer" ValidationExpression="^\d+$" />
</ItemTemplate>
</asp:TemplateColumn>

<asp:TemplateColumn HeaderText="单价">
<ItemTemplate>
<asp:TextBox id="DanJian" runat=’server’ Text=’<%# DataBinder.Eval(Container.DataItem,"DG_DanJian"%>’
onkeyup="JavascriptoCal()"
/>

<asp:RegularExpressionValidator id="revS2" runat="server" ControlToValidate="DanJian" ErrorMessage="must be numeric" ValidationExpression="^\d+(\.\d*)?$" />

</ItemTemplate>
</asp:TemplateColumn>

<asp:TemplateColumn HeaderText="金额">
<ItemTemplate>
<asp:TextBox id="JinE" runat=’server’ Text=’<%# DataBinder.Eval(Container.DataItem,"DG_JinE"%>’ />
</ItemTemplate>
</asp:TemplateColumn><script language="javascript">
function DoCal()
{
 var e = event.srcElement;
 var row = e.parentNode.parentNode;
 var txts = row.all.tags("INPUT";
 if (!txts.length || txts.length < 3)
  return;

 var q = txts[txts.length-3].value;
 var p = txts[txts.length-2].value;

 if (isNaN(q) || isNaN(p))
  return;

 q = parseInt(q);
 p = parseFloat(p);

 txts[txts.length-1].value = (q * p).toFixed(2);
}
</script>

 24.DataGrid选定比较底下的行时,为什么总是刷新一下,然后就滚动到了最上面,刚才选定的行因屏幕的关系就看不到了。

page_load
page.smartNavigation=true

  25.在Datagrid中修改数据,当点击编辑键时,数据出现在文本框中,怎么控制文本框的大小 ?

private void DataGrid1_ItemDataBound(obj sender,DataGridItemEventArgs e)
{
 for(int i=0;i<e.Item.Cells.Count-1;i++)
  if(e.Item.ItemType==ListItemType.EditType)
  {
   e.Item.Cells[i].Attributes.Add("Width", "80px"
  }
}

  26.对话框

private static string ScriptBegin = "<script language=\"JavaScript\">";
private static string ScriptEnd = "</script>";

public static void ConfirmMessageBox(string PageTarget,string Content)
{
 string ConfirmContent="var retValue=window.confirm(’"+Content+"’);"+"if(retValue){window.location=’"+PageTarget+"’;}";

 ConfirmContent=ScriptBegin + ConfirmContent + ScriptEnd;

 Page ParametERPage = (Page)System.Web.HttpContext.Current.Handler;
 ParameterPage.ReGISterStartupScript("confirm",ConfirmContent);
 //Response.Write(strScript);
}

  27. 将时间格式化:string aa=DateTime.Now.ToString("yyyy年MM月dd日";

  1.1 取当前年月日时分秒

currentTime=System.DateTime.Now;

  1.2 取当前年

int 年= DateTime.Now.Year;

  1.3 取当前月

int 月= DateTime.Now.Month; 

  1.4 取当前日

int 日= DateTime.Now.Day; 

  1.5 取当前时

int 时= DateTime.Now.Hour; 

  1.6 取当前分

int 分= DateTime.Now.Minute; 

  1.7 取当前秒

int 秒= DateTime.Now.Second; 

  1.8 取当前毫秒

int 毫秒= DateTime.Now.Millisecond; 

  28.自定义分页代码:

  先定义变量 :

public static int pageCount; //总页面数
public static int curPageIndex=1; //当前页面 

  下一页:

if(DataGrid1.CurrentPageIndex < (DataGrid1.PageCount - 1))
{
 DataGrid1.CurrentPageIndex += 1;
 curPageIndex+=1;
}

bind(); // DataGrid1数据绑定函数 

  上一页:

if(DataGrid1.CurrentPageIndex >0)
{
 DataGrid1.CurrentPageIndex += 1;
 curPageIndex-=1;
}

bind(); // DataGrid1数据绑定函数 

  直接页面跳转:

int a=int.Parse(JumpPage.Value.Trim());//JumpPage.Value.Trim()为跳转值

if(a<DataGrid1.PageCount)
{
 this.DataGrid1.CurrentPageIndex=a;
}

bind(); 


29.DataGrid使用:

  添加删除确认:

private void DataGrid1_ItemCreated(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e)
{
 foreach(DataGridItem di in this.DataGrid1.Items)
 {
  if(di.ItemType==ListItemType.Item||di.ItemType==ListItemType.AlternatingItem)
  {
   ((LinkButton)di.Cells[8].Controls[0]).Attributes.Add("onclick","return confirm(’确认删除此项吗?’);";
  }
 }

  样式交替:

ListItemType itemType = e.Item.ItemType;

if (itemType == ListItemType.Item 
{
 e.Item.Attributes["onmouseout"] = "JavaScript:this.style.backgroundColor=’#FFFFFF’;";
 e.Item.Attributes["onmouseover"] = "Javascript:this.style.backgroundColor=’#d9ece1’;cursor=’hand’;" ;
}
else if( itemType == ListItemType.AlternatingItem)
{
 e.Item.Attributes["onmouseout"] = "javascript:this.style.backgroundColor=’#a0d7c4’;";
 e.Item.Attributes["onmouseover"] = "javascript:this.style.backgroundColor=’#d9ece1’;cursor=’hand’;" ;

  添加一个编号列:

DataTable dt= c.ExecuteRtnTableForAccess(sqltxt); //执行sql返回的DataTable
DataColumn dc=dt.Columns.Add("number",System.Type.GetType("System.String");

for(int i=0;i<dt.Rows.Count;i++)
{
 dt.Rows[i]["number"]=(i+1).ToString();
}

DataGrid1.DataSource=dt;
DataGrid1.DataBind(); 

  DataGrid1中添加一个CheckBox,页面中添加一个全选框

private void CheckBox2_CheckedChanged(object sender, System.EventArgs e)
{
 foreach(DataGridItem thisitem in DataGrid1.Items)
 {
  ((CheckBox)thisitem.Cells[0].Controls[1]).Checked=CheckBox2.Checked;
 }

  将当前页面中DataGrid1显示的数据全部删除

foreach(DataGridItem thisitem in DataGrid1.Items)
{
 if(((CheckBox)thisitem.Cells[0].Controls[1]).Checked)
 {
  string strloginid= DataGrid1.DataKeys[thisitem.ItemIndex].ToString();
  Del (strloginid); //删除函数
 }

  30.当文件在不同目录下,需要获取数据库连接字符串(如果连接字符串放在Web.config,然后在Global.asax中初始化)

  在Application_Start中添加以下代码:

Application["ConnStr"]=this.Context.Request.PhysicalApplicationPath+ConfigurationSettings.
   AppSettings["ConnStr"].ToString();

  31. 变量.ToString()

  字符型转换 转为字符串

12345.ToString("n"; //生成 12,345.00
12345.ToString("C"; //生成 ¥12,345.00
12345.ToString("e"; //生成 1.234500e+004
12345.ToString("f4"; //生成 12345.0000
12345.ToString("x"; //生成 3039 (16进制)
12345.ToString("p"; //生成 1,234,500.00% 

  32、变量.Substring(参数1,参数2);

  截取字串的一部分,参数1为左起始位数,参数2为截取几位。 如:string s1 = str.Substring(0,2);

  33.在自己的网站上登陆其他网站:(如果你的页面是通过嵌套方式的话,因为一个页面只能有一个FORM,这时可以导向另外一个页面再提交登陆信息)

<SCRIPT language="javascript">
<!--
 function gook(pws)
 {
  frm.submit();
 }
//-->

</SCRIPT> <body leftMargin="0" topMargin="0" onload="javascript:gook()" marginwidth="0" marginheight="0">
<form name="frm" action=" http://220.194.55.68:6080/login.PHP?retid=7259  " method="post">
<tr>
<td>
<input id="f_user" type="hidden" size="1" name="f_user" runat="server">
<input id="f_domain" type="hidden" size="1" name="f_domain" runat="server">
<input class="box" id="f_pass" type="hidden" size="1" name="pwshow" runat="server">

<INPUT id="lng" type="hidden" maxLength="20" size="1" value="5" name="lng">
<INPUT id="tem" type="hidden" size="1" value="2" name="tem">

</td>

</tr>

</form> 

  文本框的名称必须是你要登陆的网页上的名称,如果源码不行可以用vsniffer 看看。

  下面是获取用户输入的登陆信息的代码:

string name;
name=Request.QueryString["EmailName"];

try
{
 int a=name.IndexOf("@",0,name.Length);
 f_user.Value=name.Substring(0,a);
 f_domain.Value=name.Substring(a+1,name.Length-(a+1));
 f_pass.Value=Request.QueryString["Psw"];
}

catch
{
 Script.Alert("错误的邮箱!";
 Server.Transfer("index.ASPx";
}

loading...
 
 

2006-3-16
DataGrid操作小技巧 [转]

DataGrid将布尔值转换为“是”与“否”
<%# IIf(DataBinder.Eval(Container,"DataItem.sex","男","女" %>
上面是vb的写法c#的可以参照:http://www.chinaaspx.com/comm/dotnetbbs/5/70001.htm 

改变datagrid中行颜色

 Private Sub dgrid_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles dgrid.ItemDataBound

            If Not e.Item.ItemIndex = -1 Then
                e.Item.Attributes.Add("onmouseover", "this.setAttribute('BKC',this.style.backgroundColor);this.style.backgroundColor='#EEEEEE'"
                e.Item.Attributes.Add("onmouseout", "this.style.backgroundColor=this.getAttribute('BKC');"
            End If

            Dim FolderID As String = Request.QueryString("FolderID"
        End Sub
删除确认:   
   <asp:ButtonColumn Text="<div onclick="return confirm('确认要删除吗?')"><img src=../../images/shared/Delete.gif></div>"      HeaderText="删除" CommandName="Delete">            <HeaderStyle Wrap="False" HorizontalAlign="Center"></HeaderStyle>   <ItemStyle Wrap="False" Width="35" HorizontalAlign="Center"></ItemStyle>
   </asp:ButtonColumn>


在DataGrid新增一序号列......
在DataGrid新增一序号列,即类似Excel中的行号
添加模板列 
<Columns> 
                  <asp:TemplateColumn HeaderText="" ItemStyle-Width="50"> 
                     <ItemTemplate> 
                        <%# Container.ItemIndex+1 %> 
                     </ItemTemplate> 
                  </asp:TemplateColumn> 
</column> 


实现datagrid 多列求和......
实现datagrid 多列求和
 Sub DataGrid_DataBound(obj as object,e as DataGridItemEventArgs) 
    Dim intTotal as integer 
    Select Case e.Item.ItemType  
      Case ListItemType.Item, ListItemType.AlternatingItem 
       Dim lbl_id as label=e.item.findControl("lbl_id" 
       intTotal+=cDbl(lbl_id.text) 
      Case listItemType.footer 
       e.item.cells(0).text="总计:" & intTotal.tostring 
      e.item.cells(0).Attributes.add("Align","center" 
    End Select  
  End Sub  
一。其中e.item.findControl("lbl_id"的lbl_id是dataGrid中一行的一个文本框或标签; 
二。加在DataGrid中的OnItemDataBound="DataGrid_DataBound"事件中;


datagrid中根据不同的值......
datagrid中根据不同的值显示不同的颜色

Private Sub grdcheckequipment_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles grdcheckequipment.ItemDataBound 
        ' 确保处理的是数据行,而不是Header或者Footer  
        If e.Item.ItemType = ListItemType.Item OrElse e.Item.ItemType = ListItemType.AlternatingItem Then 
            '  得到Manager字段的值  
            Try 
                Dim isManager As DateTime = CType(DataBinder.Eval(e.Item.DataItem, "首次接入时间", DateTime) 
                If isManager = "1900-01-01" Then 
                  e.Item.Cells(6).ForeColor =color.red              
End If 
            Catch 
            End Try 


        End If 
    End Sub 

 


单击DataGrid的行,使这......
单击DataGrid的行,使这行的数据显示在这个页面的下面,有点像winform的一个列表,下面一个明细!!!^_^^_^^_^

用处:可以使一个页面显示更多的内容

*.cs文件
 private void DataGrid1_ItemDataBound(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e)
  {
   if(e.Item.ItemType==ListItemType.Item||e.Item.ItemType==ListItemType.AlternatingItem)
   {
    e.Item.Attributes.Add("onmouseover","this.style['cursor']='hand'";
    e.Item.Attributes.Add("onclick","javascript:itemclick('"+e.Item.Cells[2].Text+"','"+((Label)e.Item.FindControl("lblTime").Text+"')";
   }

*.aspx文件
function itemclick(time,obj)
 {
     document.form1.all("label1".innerText = time;
  document.form1.txt.value = obj; 
     }

 <DIV id="label1"   runat="server">统计时间</DIV>
 <INPUT id="txt" type="text" runat="server" value=入库时间>

<asp:BoundColumn DataField="time1" HeaderText="统计时间">
 </asp:BoundColumn>
 <asp:TemplateColumn HeaderText="入库时间">
     <ItemTemplate>
         <asp:Label ID=“lblTime” Runat=server Text='<%# DataBinder.Eval(Container.DataItem,"rukushijian"%>'>
         </asp:Label>
      </ItemTemplate>       
 </asp:TemplateColumn>


数据的绑定DataBinder......
数据的绑定DataBinder 

学习了一段时间.net后,发掘.net性能对于一个application至关重要,所以现在经常找一些可以提高性能的技巧,下面是有关DataBinder的一个小技巧。 

对于一般的绑定,我们使用<%# DataBinder.Eval(Container.DataItem, "字段名" %> 

用DataBinder.eval 绑定不必关心数据来源。不必关心数据的类型eval会把这个数据对象转换为一个字符串。在底层绑定做了很多工作,使用了反射性能。正因为使用方便了,但却影响了数据性能. 
来看下<%# DataBinder.Eval(Container.DataItem, "字段名" %>。当于dataset绑定时DataItem其实是一个DataRowView(如果绑定的是一个数据读取器datareader)它就是一个IdataRecord。)因此直接转换成DataRowView的话,将会给性能带来很大提升 <%# ctype(Container.DataItem,DataRowView).Row("字段名" %> 对数据的绑定建议使用<%# ctype(Container.DataItem,DataRowView).Row("字段名" %>。数据量大的时候可提高几百倍的速度。使用时注意2方面:1.需在页面添加<%@ Import namespace="System.Data"%>.2.注意字段名的大小写(要特别注意)。如果和查询的不一致,在某些情况下会导致比<%# DataBinder.Eval(Container.DataItem, "字段名" %>还要慢。如果想进一步提高速度,可采用<%# ctype(Container.DataItem,DataRowView).Row(0) %>的方法。不过其可读性不高 

loading...
 
 

2006-3-16
DataGrid使用技巧小总结-个性化分页及复杂表头 [转]

DataGrid 自定义分页导航
无需任何其他第三方控件,在DataGrid 自己分页的基础上再个性化一点.
效果: 
让DataGrid自己的分页实现这样的效果
[1][2][3][4][5][6]   

让DataGrid自己的分页实现这样的效果
[1][2][3][4][5][6]

private void grid_ItemCreated(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e)
  {
   if(e.Item.ItemType==ListItemType.Pager)
   {   
    foreach (Control c in e.Item.Cells[0].Controls)
    {
     if (c is Label)  //当前页数
     {
        Label lblpage=(Label)c;
//      lblpage.ForeColor= System.Drawing.ColorTranslator.FromHtml("#e78a29"; //#e78a29 ,#FF0000    
//      lblpage.Font.Bold=true;
        lblpage.Text="[<font color=#e78a29><b>"+lblpage.Text+"</b></font>]";    
      //((Label)c).ForeColor = System.Drawing.Color.Green;     
//      break;
     }
     if(c is LinkButton) //链接的其他页数
     {     
         LinkButton linkButton = (LinkButton)c;      
         linkButton.Text = "[" + linkButton.Text+"]";
     }
    }   
   }
  } 


DataGrid等控件中的自动编号:

添加一个模版列:

<asp:TemplateColumn HeaderText="No.">
    <ItemStyle HorizontalAlign="Center"></ItemStyle>
    <ItemTemplate>
        <asp:Label runat="server" Text='<%# dgCustomize.CurrentPageIndex*dgCustomize.PageSize+dgCustomize.Items.Count+1 %>'>
        </asp:Label>
    </ItemTemplate>
</asp:TemplateColumn>


DataGrid中创建复杂表头
方法一:用table实现

 

  <form id="Form1" method="post" runat="server">
   <TABLE id="Table1" runat="server" cellSpacing="1" cellPadding="2" width="580" border="1"
    bgcolor="#cc6633" bordercolor="#cc9966" style="FONT-SIZE:9pt;BORDER-BOTTOM:0px">
    <TR align="center">
     <TD colspan="2" width="380" style="HEIGHT: 21px"></TD>
     <TD width="200" colspan="2" style="HEIGHT: 21px"></TD>
    </TR>
    <TR align="center">
     <TD width="200" bgcolor="#66cc99"><FONT face="宋体"></FONT></TD>
     <TD width="180" bgcolor="white"><FONT face="宋体"></FONT></TD>
     <TD width="160" bgcolor="#99cccc"></TD>
     <TD width="40" bgcolor="#009999"></TD>
    </TR>
   </TABLE>
   <aspataGrid id="DataGrid1" width="580px" AlternatingItemStyle-BackColor="#6699ff" CellPadding="2"
    CellSpacing="1" BorderWidth="1" BorderColor="#cc9966" Font-Size="9pt" runat="server" ShowHeader="False"
    AutoGenerateColumns="False">
    <Columns>
     <asp:BoundColumn DataField="Title">
      <ItemStyle Width="200px"></ItemStyle>
     </asp:BoundColumn>
     <asp:BoundColumn DataField="CreateDate">
      <ItemStyle Width="180px"></ItemStyle>
     </asp:BoundColumn>
     <asp:BoundColumn DataField="pid">
      <ItemStyle Width="160px"></ItemStyle>
     </asp:BoundColumn>
     <asp:BoundColumn DataField="HitCount">
      <ItemStyle Width="40px"></ItemStyle>
     </asp:BoundColumn>
    </Columns>
   </aspataGrid>  
  </form> 

方法二:动态生成表头

生成双层表头:
  private void grid_ItemDataBound(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e)
  {
   if (e.Item.ItemType == ListItemType.Header)
   {
//    e.Item.Cells[0].ColumnSpan = 1;//这是第一列的跨列数
    StringBuilder strtext=new StringBuilder();
    strtext.Append("\\</td>";
    strtext.Append("<td colspan=4>生活照明</td>";
    strtext.Append("<td colspan=2>一般照明</td>";
    strtext.Append("<td colspan=2>工付业</td>";
    strtext.Append("<td colspan=2>农业</td>";
    strtext.Append("<td colspan=2>合计</td>";
    strtext.Append("</tr>";
    strtext.Append("<tr>";
    strtext.Append("<td>" + e.Item.Cells[0].Text);               
    e.Item.Cells[0].Text =strtext.ToString();

   }

}
整个表头内容:<tr><td>  e.Item.Cells[0].Text =的内容  </td></tr>

加起来就是表头的样式。


生活照明


 一般照明


 工付业


 农业


 合计 生成三层表头: if (e.Item.ItemType == ListItemType.Header)
   {   
    StringBuilder strtext=new StringBuilder();
    strtext.Append("</td>";
    strtext.Append("<td colspan= 6>当月</td>";
    strtext.Append("</tr>";


    strtext.Append("<tr>";
    strtext.Append("<td colspan=2>居民</td>";
    strtext.Append("<td colspan=2>一般</td>";
    strtext.Append("<td colspan=2>工付业</td>";
    strtext.Append("</tr>";


    strtext.Append("<tr>";
    strtext.Append("<td>" + e.Item.Cells[0].Text);               
    e.Item.Cells[0].Text =strtext.ToString();
   }

当月


居民


 一般


 工付业

loading...
 
 

2006-3-16
打造通用ASP.NET数据分页控件 [转]

对于几乎所有的数据表现Web应用来说,组织好数据的显示方式、避免给用户带来混乱的感觉就是最主要的目标之一。每个页面显示20条记录当然是可以接受的,但每页显示10000条记录就很容易给用户带来不便了。将数据分成多个页面显示,即对数据进行分页,是解决此类问题的最常见的办法。
  一、慨述

  ASP.NET本身只提供了一个支持数据分页的控件,即DataGrid分页控件,不过它比较适合Intranet环境使用,对于Internet环境来说,DataGrid分页控件提供的功能似乎不足以构造出灵活的Web应用。其中一个原因是,DataGrid控件对Web设计者放置分页控件的位置和分页控件的外观都有限制,例如,DataGrid控件不允许垂直放置分页控件。另一个能够发挥分页技术优势的控件是Repeater,Web开发者可以利用Repeater控件快速配置数据的显示方式,但分页功能却需要开发者自己实现。数据源在不断地变化,数据表现方式也千差万别,如果针对这些不断变动的条件分别定制分页控件,显然太浪费时间了,构造一个不限于特定表现控件的通用分页控件将极大地有利于节省时间。

  一个优秀的通用数据控件不仅提供常规的分页功能,而且还要能够:
  ⑴ 提供“首页”、“上一页”、“下一页”、“末页”分页导航按钮。

  ⑵ 根据数据显示情况调整自身的状态,即具有数据敏感性。如果分页控件被设置成每页显示10个记录,但实际上只有9个记录,那么分页控件不应该显示出来;在数据分成多页显示的情况下,第一个页面的“首页”、“上一页”按钮不应显示出来,最后一个页面的“下一页”、“末页”按钮也不应该显示出来。

  ⑶ 不能依赖于特定的数据显示控件。

  ⑷ 具有适应各种现有、将有数据源的能力。

  ⑸ 应当能够方便地配置显示方式,轻松地集成到各种应用之中。

  ⑹ 当分页就绪时,提醒其他控件。

  ⑺ 即使是缺乏经验的Web设计者,也要能够毫无困难地使用。

  ⑻ 提供有关分页信息的属性数据。

  目前市场上已经有一些提供上述功能的商业性控件,不过都价格不菲。对于许多开发者来说,自己构造一个通用的分页控件是最理想的选择。

  图一显示了本文通用分页控件的运行界面,其中用于显示的控件是一个Repeater控件。分页控件由两类部件构成:四个导航按钮,一组页面编号链接。

 

 


  用户可以方便地改换显示控件、改变分页控件本身的外观。例如,和分页控件协作的显示控件换成了一个DataGrid控件,页面编号链接和四个导航按钮分两行显示。

 


  ASP.NET支持创建定制Web控件的三种方式:用户控件,复合控件,自定义控件。第三种控件即自定义控件的名称很容易引起误解。实际上,所有这三种控件都应该算是自定义控件。复合控件和微软所谓的自定义控件的不同之处在于,前者要用到CreateChildControls()方法,CreateChildControls()方法允许控件根据某些事件重新绘制自身。对于本文的通用分页器,我们将使用复合控件。

  下面的UML序列图概括了通用分页控件的一般机制。

 


  虽然我们的目标是让通用分页控件不依赖于表现数据的控件,但很显然,总得有某种方法让分页控件访问数据。每一个从Control类继承的控件都提供一个DataBinding事件。我们把分页器本身注册成DataBinding事件的监听器,分页器就可以获知数据的情况并修改数据。由于所有从Control类继承的控件都有这个DataBinding事件,所以分页器控件达到了不依赖于特定数据表现控件的目标——换句话说,分页器控件可以绑定到所有从Control类派生的控件,即它能够绑定到几乎所有的Web控件。

 

  二、核心功能

  当表现控件触发DataBinding事件,分页控件就可以获取DataSource属性。遗憾的是,微软没有提供所有数据绑定类实现的接口,诸如IdataSourceProvider之类,而且并非所有从Control或WebControl类继承的控件都有一个DataSource属性,因此向上定型成Control类没有意义,唯一可行的办法是通过Reflection API直接操作DataSoruce属性。在讨论事件句柄方法之前,应该指出的是,为了注册事件句柄,首先必须获得一个表现控件的引用。分页控件显露了一个简单的字符串属性BindToControl:

 

public string BindToControl
{
get
{
if (_bindcontrol == null)
throw new NullReferenceException("在使用分页控件之前,请先通过设置BindToControl属性绑定到一个控件。";
return _bindcontrol;}
set{_bindcontrol=value;}
}

  这个方法非常重要,所以最好能够抛出一个含义更明确的信息,而不是抛出标准的NullReferenceException异常。在分页控件的OnInit方法中,我们解析了对表现控件的引用。本例应当用OnInit事件句柄(而不是构造函数)来确保JIT编译的aspx页面已经设置了BindToControl。

protected override void OnInit(EventArgs e)
{
_boundcontrol = Parent.FindControl(BindToControl);
BoundControl.DataBinding += new EventHandler(BoundControl_DataBound);
base.OnInit(e);
...

  搜索表现控件的操作通过搜索分页控件的Parent控件完成,在这里,Parent就是页面本身。按照这种方式使用Parent比较危险,举例来说,如果分页控件嵌入到了另一个控件之中,例如嵌入到了Table控件之中,则Parent引用实际上将是一个对Table控件的引用。由于FindControl方法只搜索当前的控件集合,除非表现控件就在该集合之中,否则不可能搜索到。一种比较安全的方法是递归地搜索各个控件集合,直至找到目标控件为止。
  找到BoundControl之后,我们将分页控件注册成为DataBinding事件的监听器。由于分页控件要操作数据源,所以该事件句柄应当是调用链中的最后一个,这一点很重要。不过,只要表现控件在OnInit事件句柄中注册DataBinding的事件句柄(默认行为),分页控件操作数据源时就不会出现问题。

  DataBound事件句柄负责获取表现控件的DataSource属性。

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);
}

 

  在DataBound中,我们尝试通过Reflection API获得DataSource属性,然后返回实际数据源的一个引用。现在虽然已经获知了数据源,但分页控件还必须知道如何操作该数据源。为了让分页控件不依赖于特定的表现控件,问题复杂了很多。不过,如果让分页控件依赖于特定的数据源,那就背离了设计一个灵活的分页控件的目标。我们要通过一个接插式的体系结构来确保分页控件能够处理各种数据源,无论是.NET提供的数据源,还是自定义的数据源。

  为了提供一个健壮的、可伸缩的接插式体系结构,我们将利用[GoF] Builder模式构造出一个解决方案。

 

 


图四

  IDataSourceAdapter接口定义了分页控件操作数据所需的最基本的元素,相当于“插头”。

 

publicinterface IDataSourceAdapter
{
int TotalCount{get;}
object GetPagedData(int start,int end);
}

  TotalCount属性返回在处理数据之前数据源所包含元素的总数,而GetPagedData方法返回原始数据的一个子集,例如:假设数据源是一个包含20个元素的数组,分页控件将数据显示成每页10个元素,则第一页的元素子集是数组元素0-9,第二页的元素子集是数组元素10-19。DataViewAdapter提供了一个DataView类型的插头:

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;
}
}

  DataViewAdapter实现了IDataSourceAdapter的GetPagedData方法,该GetPagedData克隆原始的DataTable,将原始DataTable中的数据导入到新的DataTable。该类的可见性有意地设置成internal,目的是为了向Web开发者隐藏实现细节,进而通过Builder类提供一个更简单的接口。

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;}

  AdapterBuilder抽象类为IdataSourceAdapter类型提供了一个更容易管理的接口,由于提高了抽象程度,我们不必再直接使用IdataSourceAdapter,同时AdapterBuilder还提供了在分页数据之前执行预处理的指令。另外,该Builder还使得实际的实现类,例如DataViewAdapter,对分页控件的用户透明:

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;}
}
}

  DataView类型和DataTable类型的关系是如此密切,所以构造一个通用性的DataAdapter可能是有意义的,其实只要加入另一个处理DataTable的构造函数就足够了。遗憾的是,当用户需要不同的功能来处理某个DataTable时,就必须替换或继承整个类。如果我们构造一个使用同一IdataSourceAdapter的新Builder,用户在选择如何实现适配器时就拥有更多的自由。

  在分页控件中,寻找适当Builder类的操作由一个类型安全的集合完成。

public class AdapterCollectionictionaryBase
{
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));
}
publicvoid Remove(Type key)
{
Dictionary.Remove(GetKey(key));
}
public AdapterBuilder this[Type key]
{
get{return (AdapterBuilder)Dictionary[GetKey(key)];}
set{Dictionary[GetKey(key)]=value;}
}
}

  AdapterCollection依赖于DataSource类型,DataSource通过BoundControl_DataBound巧妙地引入。这里使用的索引键是Type.FullName方法,确保了每一种类型索引键的唯一性,同时这也把保证每一种类型只有一个Builder的责任赋予了AdapterCollection。将Builder查找加入BoundControl_DataBound方法,结果如下:

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);
}

  BoundControl_DataBound方法利用HasParentControlCalledDataBinding检查是否已经创建了Builder,如果是,则不再执行寻找适当Builder的操作。Adapters表的初始化在构造函数中完成:

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());
}

  最后一个要实现的方法是BindParent,用来处理和返回数据。

private void BindParent()
{
_datasource.GetSetMethod().Invoke(BoundControl,
new object[]{_builder.Adapter.GetPagedData(StartRow,ResultsToShow*CurrentPage)});
}

  这个方法很简单,因为数据处理实际上是由Adapter完成的。这一过程结束后,我们还要用一次Reflection API,不过这一次是设置表现控件的DataSource属性。


  三、界面设计

  至此为止,分页控件的核心功能已经差不多实现,不过如果缺少适当的表现方式,分页控件不会很有用。

  为了有效地将表现方式与程序逻辑分离,最好的办法莫过于使用模板,或者说得更具体一点,使用Itemplate接口。实际上,微软清楚地了解模板的强大功能,几乎每一个地方都用到了模板,甚至页面解析器本身也不例外。遗憾的是,模板并不象有些人认为的那样是一个简单的概念,需要花些时间才能真正掌握它的精髓,好在这方面的资料比较多,所以这里就不再赘述了。返回来看分页控件,它有四个按钮:首页,前一页,后一页,末页,当然另外还有各个页面的编号。四个导航按钮选自ImageButton类,而不是LinkButton类,从专业的Web设计角度来看,图形按钮显然要比单调的链接更有用一些。

public ImageButton FirstButton{get {return First;}}
public ImageButton LastButton{get {return Last;}}
public ImageButton PreviousButton{get {return Previous;}}
public ImageButton NextButton{get {return Next;}} 

  页面编号是动态构造的,这是因为它们依赖于数据源中记录数量的多少、每个页面显示的记录数量。页面编号将加入到一个Panel,Web设计者可以通过Panel来指定要在哪里显示页面编号。有关创建页面编号的过程稍后再详细讨论,现在我们需要为分页控件提供一个模板,使得用户能够定制分页控件的外观。

[Template Container(typeof(LayoutContainer))]
public ITemplate Layout
{
get{return (_layout;}
set{_layout =value;}
}

public class LayoutContainer:Control,INamingContainer
{
public LayoutContainer()
{this.ID = "Page";}
}


  LayoutContainer类为模板提供了一个容器。一般而言,在模板容器中加入一个定制ID总是不会错的,它将避免处理事件和进行页面调用时出现的问题。下面的UML图描述了分页控件的表现机制。

 

 


图五

  创建模板的第一步是在aspx页面中定义布局:

 

<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>

  这个布局例子不包含任何格式元素,例如表格等,实际应用当然可以(而且应该)加入格式元素,请参见稍后的更多说明。

  Itemplate接口只提供了一个方法InstantiateIn,它解析模板并绑定容器。

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);
}

  控件的InstatiateTemplate方法要做的第一件事情是实例化模板,即调用Layout.InstantiateIn(_container)。容器其实也是一种控件,用法也和其他控件相似。InstantiateTemplate方法利用这一特点寻找四个导航按钮,以及用来容纳页面编号的Panel。导航按钮通过它们的ID找到,这是对分页控件的一点小小的限制:导航按钮必须有规定的ID,分别是First、Previous、Next、Last,另外,Panel的ID必须是Pager,否则就会找不到。遗憾的是,就我们选定的表现机制而言,这似乎是较好的处理方式了;但可以相信的是,只要提供适当的说明文档,这一小小限制不会带来什么问题。另外一种可选择使用的办法是:让每一个按钮从ImageButton类继承,从而也就定义了一个新的类型;由于每一个按钮是一种不同的类型,在容器中可以实现一个递归搜索来寻找各种特定的按钮,从而不必再用到按钮的ID属性。

  找到四个按钮之后,再把适当的事件句柄绑定到这些按钮。在这里必须做一个重要的决定,即何时调用InstantiateTemplate。一般地,这类方法应当在CreateChildControls方法中调用,因为CreateChildControls方法的主要用途就是这一类创建子控件的任务。由于分页控件永远不会修改其子控件,所以它不需要CreateChildControls提供的功能来根据某些事件修改显示状态。显示子控件的速度总是越快越好,因此调用InstantiateTemplate方法的比较理想的位置是在OnInit事件中。

protected override void OnInit(EventArgs e)
{
_boundcontrol = Parent.FindControl(BindToControl);
BoundControl.DataBinding += new EventHandler(BoundControl_DataBound);
InstantiateTemplate();
Controls.Add(_container);
base.OnInit(e);

  OnInit方法除了调用InstantiateTemplate方法,它的另一个重要任务是将容器加入分页控件。如果不将容器加入到分页器的控件集合,由于Render方法永远不会被调用,所以模板就不可能显示出来。

  模板还可以用编程的方式通过实现Itemplate接口定义,这一特性除了可作为提高灵活性的措施之外,还可以提供一个默认的模板,以便在用户没有通过aspx页面提供模板时使用。

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);
}
}

  DefaultPagerLayout通过编程的方式提供了所有的导航元素,并将它们加入到aspx页面,不过这一次导航元素用标准的HTML表格设置了格式。现在,如果用户没有提供一个表现模板,程序将自动提供一个默认的模板。

[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;}
}

  CurrentPage保存的实际上是页面编号的ViewState中的当前页面,PagersToShow方法定义的属性允许用户指定要显示多少页面,而ResultsToShow定义的属性则允许用户指定每页要显示多少记录,默认值是10。

  NumberofPagersToGenerate返回当前应当生成的页面编号的数量。

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;}
}

  TotalPagesToShow方法返回要显示的总页面数量,由用户预设的ResultsToShow属性调整。


  虽然ASP.NET定义了一些默认的样式,不过对于分页控件的用户它们可能不是很实用。用户可以通过自定义样式来调整分页控件的外观。

public Style UnSelectedPagerStyle {get {return UnselectedPager;}}
public Style SelectedPagerStyle {get {return SelectedPager;}}

  UnSelectedPagerStyle提供了页面编号未选中时所用的样式,而SelectedPagerStyle提供了页面编号被选中时所用的样式。

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("&nbsp;");
}
}

private void GeneratePagers()
{
GeneratePagers(Holder);
}
 

  GeneratePagers方法动态地创建所有页面编号,页面编号是LinkButton类型的按钮。各个页面编号的标签和ID属性通过循环赋值,同时,点击事件被绑定到适当的事件句柄。最后,页面编号被加入到一个容器控件——在本例中是一个Panel对象。按钮ID起到了标识哪一个按钮触发点击事件的作用。下面是事件句柄的定义:

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();
}

  首先,分页控件通过调用HasParentControlCalledDataBinding方法检查是否已经初始化了必要的适配器。如果是,则将前面指出的根据数据显示情况自动调整控件的规则应用到当前的控件,这些规则使得分页控件根据BoundControl中数据的不同情况表现出不同的行为。虽然这些规则由分页控件内部控制,但必要时可以用[GoF] State模式方便地移出到控件之外。

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();
}

  ApplyDataSensitivityRules方法实施预定义的规则,诸如IsPagerVisible、IsPreviousVisible和IsNextVisible。默认情况下,分页控件将启用这些规则,但用户可以通过设置IsDataSensitive属性来关闭这些规则。

  至此为止,分页控件的显示部分基本设计完毕。最后剩下的结束工作是提供几个事件句柄,使得用户能够在各种分页控件事件出现时进行必要的调整。

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;}}
}
 

  由于分页控件需要返回自定义的事件参数,所以我们定义了一个专用的PageChangedEventArgs类。PageChangedEventArgs类返回PagedEventInvoker类型,PagedEventInvoker类型是可能触发事件的控件的枚举量。为了处理自定义的事件参数,我们定义了一个新的delegate,即PageDelegate。事件按照下面的形式定义:

public event PageDelegate PageChanged;
public event EventHandler DataUpdate;

  当事件没有对应的事件监听器时,ASP.NET会抛出一个异常。分页控件定义了下列RaiseEvent方法。

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);
}
}

  现在事件句柄可以通过调用各个RaiseEvent方法来触发事件了。

  四、应用实例

  至此为止,分页控件的设计已经全部完成,可以正式使用了。要使用该分页控件,只要把它绑定到一个表现控件即可。

<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>

  上面的aspx页面将分页控件绑定到一个Repeater控件,设置每页显示的记录数量为2,选中的页面编号颜色为黄色,使用默认的布局,效果如图一。下面是另一个例子,它将分页控件绑定到一个DataGrid,效果如图二。

<aspataGrid ID="Grid" Runat="server"></aspataGrid>
<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控件改换成多用途的通用控件,数十倍地提高工作效率,本文的分页控件只是创建通用控件来满足现有和将来表现需要的其中一个例子而已。
loading...
 
 

2006-3-13
将DataGrid中数据倒出Excel文件并下载 [转]

Imports System
Imports System.Text
Namespace toExcel

'功能:将ASP.net中DataGrid生成Excel文件下载。
'Mountains改进:1、支持中文 2、隐藏列不显示
'日期:2002.10.30
Public Class DataGridToCSV

Public Function GenerateFile(ByRef Page As System.Web.UI.Page, ByVal MyDataGrid As System.Web.UI.WebControls.DataGrid, ByVal FileName As String) As String

Dim resp As HttpResponse
Dim colCount As Integer = MyDataGrid.Columns.Count - 1

resp = Page.Response

resp.ContentEncoding = System.Text.Encoding.GetEncoding("GB2312" '解决中文乱码之关键
'resp.Charset = "utf-8"
'resp.AddFileDependency(FileName)
'resp.ContentType = "Text/HTML"
'resp.AppendHeader("Content-Type", "text/html; charset=gb2312"

resp.AppendHeader("Content-Disposition", "attachment;filename=" + FileName) '必要,做成下载文件


Dim colHeaders As String = ""
Dim strItems As StringBuilder = New StringBuilder()

Dim myCol As DataGridColumn

Dim i As Integer

For i = 0 To colCount
myCol = MyDataGrid.Columns(i)
If myCol.Visible = True Then
colHeaders = colHeaders & myCol.HeaderText.ToString & ","
End If
Next

If colHeaders.Length > 0 Then
colHeaders = colHeaders.Substring(0, colHeaders.LastIndexOf(",")
End If

colHeaders = colHeaders & Chr(13) & Chr(10)


resp.Write(colHeaders)

Dim colRow As String

Dim item As DataGridItem

For Each item In MyDataGrid.Items
resp.Write(FormatExportRow(colCount, item, MyDataGrid))
Next item

resp.End()

End Function

Private Function FormatExportRow(ByVal colCount As Integer, ByVal Item As DataGridItem, ByVal MyDataGrid As System.Web.UI.WebControls.DataGrid) As String
Dim strItem As String
Dim i As Integer

For i = 0 To colCount
If MyDataGrid.Columns(i).Visible = True Then
If Item.Cells(i).Text Is System.DBNull.Value Then
Item.Cells(i).Text = ""
End If
If i = colCount Then
strItem += Item.Cells(i).Text.ToString & Chr(13) & Chr(10)
Else
strItem += Item.Cells(i).Text.ToString & ","
End If
End If
Next
strItem = Replace(strItem, " ", " "
Return strItem
End Function


End Class

End Namespace


loading...
 
 

2006-3-13
ASP.net中的Datagrid自定义分页功能 [转]

这里使用的是VB.net语言。

DataGridPaging.aspx

 

 参考下面我的回复中,这里帖不上代码。   
 

 

DataGridPaging.aspx.vb

ImportsSystem.Data.SqlClient
ImportsSystem.Data
ImportsSystem.Web.UI

PublicClassDataGridPaging
   InheritsSystem.Web.UI.Page

   ProtectedWithEventsbtnFirstAsSystem.Web.UI.WebControls.LinkButton
   ProtectedWithEventsbtnPrevAsSystem.Web.UI.WebControls.LinkButton
   ProtectedWithEventsbtnNextAsSystem.Web.UI.WebControls.LinkButton
   ProtectedWithEventsbtnLastAsSystem.Web.UI.WebControls.LinkButton
   ProtectedWithEventslblCurrentIndexAsSystem.Web.UI.WebControls.Label
   ProtectedWithEventslblPageCountAsSystem.Web.UI.WebControls.Label
   ProtectedWithEventslblRegisterCountAsSystem.Web.UI.WebControls.Label
   ProtectedWithEventsDataGridAsSystem.Web.UI.WebControls.DataGrid
   ProtectedWithEventsDataGrid1AsSystem.Web.UI.WebControls.DataGrid

#Region"WebFormDesignerGeneratedCode"

   'ThiscallisrequiredbytheWebFormDesigner.
   <System.Diagnostics.DebuggerStepThrough()>PrivateSubInitializeComponent()

   EndSub

   PrivateSubPage_Init(ByValsenderAsSystem.Object,ByValeAsSystem.EventArgs)HandlesMyBase.Init
       'CODEGEN:ThismethodcallisrequiredbytheWebFormDesigner
       'Donotmodifyitusingthecodeeditor.
       InitializeComponent()
   EndSub

#EndRegion

   DimcnnAsNewSqlConnection("Password=; UserID=sa;InitialCatalog=northwind;DataSource=localhost;ConnectTimeout=30"
   DimadpAsNewSqlDataAdapter
   DimcmdAsNewSqlCommand
   DimdsAsNewDataSet

   '  DimintStartIndexAsLong

   '定义全局静态变量,记录选中页面之前的总记录数
   PrivateSharedprecedingAsLong
   PrivateSharedgridPageSizeAsInt16

   PrivateSubPage_Load(ByValsenderAsSystem.Object,ByValeAsSystem.EventArgs)HandlesMyBase.Load

       btnFirst.Text="最首页"
       btnPrev.Text="前一页"
       btnNext.Text="下一页"
       btnLast.Text="最后页"

       IfNotIsPostBackThen
           Try
               DimcmdAsNewSqlCommand("selectcount(*)fromproducts",cnn)
               cnn.Open()
               '设置在使用自定义分页时DataGrid控件中的实际项数。
               'DimiAsInt16
               'i=cmd.ExecuteScalar()
               'MyDataGrid.VirtualItemCount=(i/MyDataGrid.PageSize)
               DataGrid1.VirtualItemCount=cmd.ExecuteScalar()
           CatchexAsException
               Response.Write("<scriptlanguage=javascript>alert('错误原因:'+exp.tostring())"
           Finally
               cnn.Close()
           EndTry
           preceding=DataGrid1.PageSize
           BindGrid()

       EndIf

   EndSub

   SubBindGrid()
       '使用DataSet方法填充DataGrid
       DimstrAsString="*"
       'DimgridPageSizeAsInt16=DataGrid1.PageSize
       gridPageSize=DataGrid1.PageSize

       DimcmdNumberAsNewSqlCommand("selectcount(*)fromproducts",cnn)

       Try
           cnn.Open()
           '设置在使用自定义分页时DataGrid控件中.VirtualItemCount存放总的实际项数。
           DataGrid1.VirtualItemCount=cmdNumber.ExecuteScalar()

           '使用求余保证最后一页的合理显示
           Ifpreceding>=DataGrid1.VirtualItemCountThen
               gridPageSize=DataGrid1.VirtualItemCountModDataGrid1.PageSize
               IfgridPageSize=0Then
                   gridPageSize=DataGrid1.PageSize
               EndIf
           EndIf

           str="select"+str+"from(selecttop"&gridPageSize.ToString+str+"from(select top"+CStr(preceding)+str+"fromproductswhereproductID>0orderbyproductID)asporderbyproductIDdesc)asporderbyproductID"

           Cmd.CommandText=str
           Cmd.Connection=cnn
           adp.SelectCommand=Cmd
           'adp=NewSqlDataAdapter(str,cnn)
           adp.Fill(ds,"products"
           DataGrid1.DataSource=ds.Tables("products".DefaultView
           DataGrid1.DataBind()
       CatchexAsException
           Response.Write("错误原因:"+ex.ToString())
           'Throwex
       Finally
           Ifcnn.State=ConnectionState.OpenThen
               cnn.Close()
           EndIf
       EndTry

       ShowStats()
       HideButton()


   EndSub

   '------------------------------------------- 下面是分页功能   -----------------------------------------------

   SubDataGrid1_Page(ByValsenderAsObject,ByValeAsDataGridPageChangedEventArgs)
       '点击GRID某一页时发生
       'GridXQ.aspx中DataGrid的OnPageIndexChanged="DataGrid1_Page"

       preceding=(e.NewPageIndex+1)*DataGrid1.PageSize
       DataGrid1.CurrentPageIndex=e.NewPageIndex
       BindGrid()
       ShowStats()
       HideButton()
   EndSub

   SubPagerButtonClick(ByValsenderAsObject,ByValeAsEventArgs)
       'usedbyexternalpagingUI

       '页面上Grid下方linkbutton的onclick="PagerButtonClick"CommandArgument="next/prev/last/……"
       DimargAsString=sender.CommandArgument

       SelectCasearg
           Case"next"
               If(DataGrid1.CurrentPageIndex<=(DataGrid1.PageCount-1))Then
                   DataGrid1.CurrentPageIndex+=1
                   IfDataGrid1.CurrentPageIndex=DataGrid1.PageCount-1Then
                       preceding=DataGrid1.VirtualItemCount
                   Else
                       preceding+=gridPageSize
                   EndIf
               EndIf
           Case"prev"
               If(DataGrid1.CurrentPageIndex>0)Then
                   IfDataGrid1.CurrentPageIndex=DataGrid1.PageCount-1Then
                       preceding=(DataGrid1.PageCount-1)*DataGrid1.PageSize
                   Else
                       preceding-=gridPageSize
                   EndIf
                   DataGrid1.CurrentPageIndex-=1
               EndIf
           Case"last"
               DataGrid1.CurrentPageIndex=(DataGrid1.PageCount-1)
               preceding=DataGrid1.VirtualItemCount
           CaseElse
               'pagenumber因为在button.commandArgument设置为0
               DataGrid1.CurrentPageIndex=System.Convert.ToInt32(arg)
               preceding=DataGrid1.PageSize
       EndSelect

       If(DataGrid1.CurrentPageIndex=(DataGrid1.PageCount-1))Then
           btnNext.Enabled=False
       Else
           btnNext.Enabled=True
       EndIf

       If(DataGrid1.CurrentPageIndex=0)Then
           btnPrev.Enabled=False
       Else
           btnPrev.Enabled=True
       EndIf

       BindGrid()
       ShowStats()
       HideButton()
   EndSub

   SubShowStats()

       lblCurrentIndex.Text="第"+(DataGrid1.CurrentPageIndex+1).ToString()+"页"
       lblPageCount.Text="总共"+DataGrid1.PageCount.ToString()+"页"
       lblRegisterCount.Text="共有"+DataGrid1.VirtualItemCount.ToString+"条记录"
   EndSub

   SubHideButton()
       If(DataGrid1.CurrentPageIndex=(DataGrid1.PageCount-1))Then
           btnNext.Enabled=False
           btnLast.Enabled=False
       Else
           btnNext.Enabled=True
           btnLast.Enabled=True
       EndIf

       If(DataGrid1.CurrentPageIndex=0)Then
           btnPrev.Enabled=False
           btnFirst.Enabled=False
       Else
           btnPrev.Enabled=True
           btnFirst.Enabled=True
       EndIf
   EndSub
EndClass


loading...
 
 

2005-12-21
网页图片交换JAVASCRIPT代码 [原] [转]
clongge
17:27 PM

 

<table>

<tr>
<td align="center" valign="middle">
<script language=JavaScript>
<!--
var bannerAD=new Array();
var bannerADlink=new Array();
var adNum=0;

bannerAD[0]="11/1.jpg";
bannerADlink[0]="http://ent.qq.com/a/20050720/000018.htm"; 
bannerAD[1]="11/2.jpg";
bannerADlink[1]="http://ent.qq.com/a/20050720/000010.htm"; 
bannerAD[2]="11/3.jpg";
bannerADlink[2]="http://ent.qq.com/a/20050720/000007.htm"; 
bannerAD[3]="11/4.jpg";
bannerADlink[3]="http://ent.qq.com/a/20050720/000042.htm"; 
bannerAD[4]="11/5.jpg";
bannerADlink[4]="http://ent.qq.com/a/20050720/000042.htm"; 
bannerAD[5]="11/6.jpg";
bannerADlink[5]="http://ent.qq.com/a/20050720/000042.htm"; 
bannerAD[6]="11/7.jpg";
bannerADlink[6]="http://ent.qq.com/a/20050720/000042.htm"; 
bannerAD[7]="11/8.jpg";
bannerADlink[7]="http://ent.qq.com/a/20050720/000042.htm"; 
bannerAD[8]="11/9.jpg";
bannerADlink[8]="http://ent.qq.com/a/20050720/000042.htm"; 
bannerAD[9]="11/10.jpg";
bannerADlink[9]="http://ent.qq.com/a/20050720/000042.htm"; 
bannerAD[10]="11/11.jpg";
bannerADlink[10]="http://ent.qq.com/a/20050720/000042.htm"; 
bannerAD[11]="11/12.jpg";
bannerADlink[11]="http://ent.qq.com/a/20050720/000042.htm"; 
bannerAD[12]="11/13.jpg";
bannerADlink[12]="http://ent.qq.com/a/20050720/000042.htm"; 
function setTransition(){
if (document.all){
bannerADrotator.filters.revealTrans.Transition=Math.floor(Math.random()*23);
bannerADrotator.filters.revealTrans.apply();
}
}

function playTransition(){
if (document.all)
bannerADrotator.filters.revealTrans.play()
}

function nextAd(){
if(adNum<bannerAD.length-1)adNum++ ;
else adNum=0;
setTransition();
document.images.bannerADrotator.src=bannerAD[adNum];
playTransition();
theTimer=setTimeout("nextAd()", 4000);
}

function jump2url(){
jumpUrl=bannerADlink[adNum];
jumpTarget='_blank';
if (jumpUrl != '){
if (jumpTarget != ')window.open(jumpUrl,jumpTarget);
else location.href=jumpUrl;
}
}
function displayStatusMsg() {
status=bannerADlink[adNum];
document.returnValue = true;
}
//-->

<a onMouseOver="displayStatusMsg();return document.returnValue"
href="javascript:jump2url()" target="_self"><img
src="javascript:nextAd()"
name=bannerADrotator width=223 height=300 border=0 class="unnamed1"
style="FILTER: revealTrans(duration=2,transition=20)"></a></td>
</tr>
</table>
 
 



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=695675

posted on 2007-04-25 12:27  sharewind  阅读(2591)  评论(0编辑  收藏  举报

导航