6.1 导航和登录
导航控件主要包括TreeView控件、Menu控件和SiteMapPath 3个控件,在此仅介绍TreeView控件和Menu控件的使用方法。登录控件包含的控件比较多,在此仅介绍Login控件的使用方法。
6.1.1
使用Menu创建菜单
使用ASP.NET Menu控件可以开发ASP.NET网页的静态和动态显示菜单,可以用来以菜单形式显示站点的结构。ASP.NET Menu控件支持静态显示和动态显示两种显示方式。
l 静态显示意味着ASP.NET Menu控件始终是完全展开的,控件的整个结构都是可视的,用户可以单击任何部位。
l 动态显示意味着只有菜单中指定的部分是静态的,而只有用户将鼠标指针放置在父节点上时才会显示其子菜单项。
其中,ASP.NET Menu控件的MaximumDynamicDisplayLevels属性指定在静态显示层后应显示的动态显示菜单节点层数。
工程Example_6_1中的页面UsingManu.aspx介绍了Menu控件的使用方法。
1.界面设计
在页面UsingManu.aspx上添加一个Menu控件,名称为MyMenu。控件MyMenu用来创建导航菜单,它包含两个子菜单,一个是“TreeView控件”,导向页面UsingTreeView.aspx;另外一个是“用户Login控件”,导向页面UsingLogin.aspx。页面UsingManu.aspx的设计界面如图6-1所示。
页面UsingManu.aspx的部分HTML设计代码如下:
<asp:Menu ID="MyMenu" runat="server" BackColor="#FFFBD6"
DynamicHoriz Font-Names="Verdana" Font-Size="0.8em"
ForeColor="#990000" StaticSubMenuIndent="10px">
<Items>
<asp:MenuItem Text="根" Value="-1">
<asp:MenuItem Text="TreeView控件" Value="0"
NavigateUrl="~/UsingTreeView.aspx"></asp:MenuItem>
<asp:MenuItem Text="用户Login控件" Value="1"
NavigateUrl="~/UsingLogin.aspx"></asp:MenuItem>
</asp:MenuItem>
</Items>
</asp:Menu>
2.运行效果
运行工程Example_6_1,展开页面UsingManu.aspx中的MyMenu控件,如图6-2所示。
图6-1 页面UsingManu.aspx的设计界面
图6-2 展开页面UsingManu.aspx中的MyMenu控件
6.1.2
使用TreeView
ASP.NET TreeView Web服务器控件用于以树形结构显示分层数据,如目录或文件目录等。该控件可以显示下面几个功能:
(1)可以显示为可选择文本或超链接的节点文本。
(2)能够自动数据绑定,还可以绑定到分层数据。
(3)能够在节点显示复选框。
(4)可以动态创建TreeView控件。
(5)可以使用主题、用户定义的图像和样式自定义外观。
工程Example_6_1中的页面UsingTreeView.aspx介绍了ASP.NET TreeView Web服务器控件的使用方法。
1.界面设计
在页面UsingTreeView.aspx上添加一个TreeView控件,名称为CategoryView。该控件以树形形式显示商品种类表Category的数据,其中,表Category存放在数据库ShoppingDB中。页面UsingTreeView.aspx的设计界面如图6-3所示。
页面UsingTreeView.aspx的部分HTML设计代码如下:
<asp:TreeView ID="CategoryView" runat="server" Width="100%"
ShowLines="True" CssClass="Text" BackColor="#5A7DD1" ForeColor="White"
EnableClientScript="False">
<NodeStyle BackColor="#5A7DD1" ForeColor="White" Font-Bold="True"
CssClass="Text" />
<RootNodeStyle BackColor="Transparent" Font-Bold="True"
ForeColor="White" />
<SelectedNodeStyle BackColor="#5A7DD1" CssClass="Text"
Font-Bold="True" ForeColor="DarkRed" />
</asp:TreeView>
2.显示TreeView控件
页面UsingTreeView.aspx显示页面TreeView控件CategoryView有如下4个步骤:
(1)调用函数DataSet GetCategorys()从数据库ShoppingDB中获取商品种类表Category的数据。
(2)创建控件CategoryView的根节点。
(3)递归创建控件CategoryView的其他节点。
(4)调用函数Page_Load(object sender,EventArgs e)完成控件CategoryView的初始化过程。
在步骤(1)中,函数GetCategorys()从数据库ShoppingDB中获取商品种类表Category的数据,并使用DataSet对象保存数据。函数GetCategorys()的程序代码如下:
public DataSet GetCategorys()
{ //创建链接
SqlConnection myConnection = new SqlConnection(
ConfigurationManager.ConnectionStrings[
"SQLCONNECTIONSTRING"].ConnectionString);
//定义SQL语句
string cmdText = "SELECT * FROM Category";
//创建Command
SqlDataAdapter da = new SqlDataAdapter(cmdText,myConnection);
//定义DataSet
DataSet ds = new DataSet();
try
{ //打开链接
myConnection.Open();
//读取数据
da.Fill(ds);
}
catch(SqlException ex)
{ //抛出异常
throw new Exception(ex.Message,ex);
}
finally{myConnection.Close();}
//返回DataSet
return ds;
}
在步骤(2)中,函数void BindCategoryTreeView(TreeView treeView,bool isExpanded, string sSelectedData)首先调用函数GetCategorys()获取数据,然后创建控件CategoryView的根节点,最后调用函数CreateChildNode(TreeNode parentNode,DataTable dataTable, bool isExpanded, string sSelectedData)创建根节点的所有孩子节点。
函数void BindCategoryTreeView(TreeView treeView,bool isExpanded, string sSelectedData)的程序代码如下:
public void BindCategoryTreeView(TreeView treeView,bool isExpanded,
string sSelectedData)
{
DataTable dataTable = GetCategorys().Tables[0];
treeView.Nodes.Clear(); //清空树的所有节点
DataRow[] rowList = dataTable.Select("ParentID='-1'");
if(rowList.Length <= 0) return;
//创建根节点
TreeNode rootNode = new TreeNode();
//设置根节点属性
rootNode.Text = rowList[0]["Desn"].ToString();
//设置根节点的Key值
rootNode.Value = rowList[0]["CategoryID"].ToString();
rootNode.Expanded = isExpanded;
rootNode.Selected = true;
//添加根节点
treeView.Nodes.Add(rootNode);
//创建其他节点
CreateChildNode(rootNode,dataTable,isExpanded,sSelectedData);
}
在步骤(3)中,函数void CreateChildNode(TreeNode parentNode,DataTable dataTable, bool isExpanded, string sSelectedData)递归调用自己创建控件CategoryView根节点的所有孩子节点,在创建孩子节点时,对同一个层次的孩子节点进行排序。
函数void CreateChildNode(TreeNode parentNode,DataTable dataTable, bool isExpanded, string sSelectedData)的程序代码如下:
private void CreateChildNode(TreeNode parentNode,DataTable dataTable,
bool isExpanded,string sSelectedData)
{ //选择数据时,添加了排序表达式OrderBy
DataRow[] rowList = dataTable.Select("ParentID='"
+ parentNode.Value + "'","OrderBy");
foreach(DataRow row in rowList)
{ //创建新节点
TreeNode node = new TreeNode();
//设置节点的属性
node.Text = row["Desn"].ToString();
node.Value = row["CategoryID"].ToString();
node.Expanded = isExpanded;
if(node.Value == sSelectedData)
{
node.Selected = true;
}
parentNode.ChildNodes.Add(node);
//递归调用,创建其他节点
CreateChildNode(node,dataTable,isExpanded,sSelectedData);
}
}
在步骤(4)中,函数Page_Load(object sender,EventArgs e)调用函数void BindCategoryTreeView (TreeView treeView,bool isExpanded, string sSelectedData)完成控件CategoryView的初始化过程。函数Page_Load(object sender,EventArgs e)的程序代码如下:
protected void Page_Load(object sender,EventArgs e)
{ //显示数据
if(!Page.IsPostBack){BindCategoryTreeView(CategoryView,true,"-1");}
}
3.运行效果
运行工程Example_6_1,展开页面UsingTreeView.aspx中的控件CategoryView,如图6-4所示。
图6-4 展开页面UsingTreeView.aspx中的控件CategoryView
6.1.3
实现站点登录
ASP.NET Login Web服务器控件显示用于执行用户身份验证的用户界面。Login控件包含用于用户名和密码的文本框和一个复选框,该复选框让用户指示是否需要服务器使用ASP.NET成员资格存储他们的标识并且当他们下次访问该站点时自动进行身份验证。
Login控件有用于自定义显示、自定义消息的属性和指向其他页的链接,在那些页面中用户可以更改密码或找回忘记的密码。Login控件可用作主页上的独立控件,或者您还可以在专门的登录页上使用它。
如果您一同使用Login控件和ASP.NET成员资格,将不需要编写执行身份验证的代码。然而,如果您想创建自己的身份验证逻辑,则可以处理Login控件的Authenticate事件并添加自定义身份验证代码。
工程Example_6_1中的页面UsingLogin.aspx介绍了ASP.NET Login Web服务器控件的使用方法。
1.界面设计
在页面UsingLogin.aspx上添加一个Login控件,名称为MyLogin。该控件实现用户登录系统的功能,其中用户还可以记住这次的登录。页面UsingLogin.aspx的设计界面如图6-5所示。
页面UsingLogin.aspx的部分HTML设计代码如下:
<asp:Login ID="MyLogin" runat="server" BackColor="#F7F7DE"
BorderColor="#CCCC99" BorderStyle="Solid" BorderWidth="1px"
Font-Names="Verdana" Font-Size="10pt"
>
<TitleTextStyle BackColor="#6B696B" Font-Bold="True"
ForeColor="#FFFFFF" />
</asp:Login>
2.用户登录
当用户输入用户名称和密码之后,并单击页面UsingLogin.aspx中的【登录】按钮时,触发事件MyLogin_LoggingIn(object sender,LoginCancelEventArgs e)实现用户登录功能。其中,函数SqlDataReader GetUserLogin(string sUserName,string sPassword)根据用户名称和密码从数据库ShoppingDB中获取用户登录信息。
函数SqlDataReader GetUserLogin(string sUserName,string sPassword)的程序代码如下:
public SqlDataReader GetUserLogin(string sUserName,string sPassword)
{ //创建链接
SqlConnection myConnection = new SqlConnection(
ConfigurationManager.ConnectionStrings[
"SQLCONNECTIONSTRING"].ConnectionString);
//定义SQL语句
string cmdText = "SELECT UserID FROM Users WHERE UserName ="
+ "'" + sUserName.ToString() + "'"
+ " AND Password ="
+ "'" + sPassword.ToString() + "'";
//创建Command
SqlCommand myCommand = new SqlCommand(cmdText,myConnection);
//定义DataReader
SqlDataReader dr = null;
try
{ //打开链接
myConnection.Open();
//读取数据
dr = myCommand.ExecuteReader(CommandBehavior.CloseConnection);
}
catch(SqlException ex)
{ //抛出异常
throw new Exception(ex.Message,ex);
}
//返回DataReader
return dr;
}
事件MyLogin_LoggingIn(object sender,LoginCancelEventArgs e)首先调用函数SqlDataReader GetUserLogin (string sUserName,string sPassword)根据用户名称和密码从数据库ShoppingDB中获取用户登录信息。如果登录信息为空,则用户登录失败;否则用户登录成功,并跳转到页面UsingTreeView.aspx。
事件MyLogin_LoggingIn(object sender,LoginCancelEventArgs e)的程序代码如下:
protected void MyLogin_LoggingIn(object sender,LoginCancelEventArgs e)
{
SqlDataReader dr = GetUserLogin(MyLogin.UserName,MyLogin.Password);
string sUserID = "";
if(dr.Read())
{ //获取登录信息
sUserID = dr["UserID"].ToString();
}
dr.Close();
if(sUserID.Length > 0)
{ //登录成功
Response.Redirect("~/UsingTreeView.aspx");
}
}
3.运行效果
运行工程Example_6_1,页面UsingLogin.aspx的初始化界面如图6-6所示,此时输入框的内容为空。
6.3 统一站点主题
在ASP.NET 2.0中,主题是属性设置的集合,它由一组元素组成,如外观、级联样式表、图像和其他资源。主题至少包含外观,且主题是在网站或Web服务器上的特殊目录中定义的。使用这些设置可以定义页面和控件的外观,然后在某个Web应用程序中的所有页、整个Web应用程序或服务器上的所有Web应用程序中一致地应用此外观。
工程Example_6_3中的页面Default.aspx介绍了ASP.NET主题的使用方法。在该工程中添加ASP.NET文件夹App_Themes,该文件夹专门用来存放主题信息。
6.3.1
主题设计
在工程Example_6_3中添加一个主题,名称为Control,主题文件存放在ASP.NET文件夹App_Themes中。主题Control的具体内容为:
<asp:GridView runat="server" SkinId="gridviewSkin" BackColor="White"
BorderColor="#336666" BorderStyle="Double" BorderWidth="3px"
CellPadding="4" GridLines="Horizontal">
<FooterStyle BackColor="White" ForeColor="#333333" />
<RowStyle BackColor="White" ForeColor="#333333" />
<SelectedRowStyle BackColor="#339966" Font-Bold="True"
ForeColor="White" />
<PagerStyle BackColor="#336666" ForeColor="White"
Horiz />
<HeaderStyle BackColor="#336666" Font-Bold="True" ForeColor="White" />
</asp:GridView>
6.3.2
界面设计
在页面Default.aspx上添加一个GridView控件,名称为GridView1。该控件以列表形式显示用户表Users的数据,其中,用户表Users存放在数据库ShoppingDB中。控件GridView1的属性SkinID的值设置为主题Control中创建的名称为gridviewSkin的Skin。页面Default.aspx的设计界面如图6-14所示。
图6-14 页面Default.aspx的设计界面
页面Default.aspx的部分HTML设计代码如下:
<%@ Page Language="C#" Theme="Control" %>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="CategoryID" DataSourceID="MySqlDS"
SkinID="gridviewSkin">
<Columns>
<asp:BoundField DataField="CategoryID" HeaderText="CategoryID"
InsertVisible="False" ReadOnly="True"
SortExpression="CategoryID" />
<asp:BoundField DataField="Desn" HeaderText="Desn"
SortExpression="Desn" />
<asp:BoundField DataField="ParentID" HeaderText="ParentID"
SortExpression="ParentID" />
<asp:BoundField DataField="OrderBy" HeaderText="OrderBy"
SortExpression="OrderBy" />
<asp:BoundField DataField="Remark" HeaderText="Remark"
SortExpression="Remark" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="MySqlDS" runat="server" CBACKGROUND: #f9fcfe; MARGIN: 0cm 0cm 0pt; WORD-BREAK: break-all; TEXT-INDENT: 40.5pt; LINE-HEIGHT: 160%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left>ConnectionStrings:SQLCONNECTIONSTRING %>"
SelectCommand="SELECT * FROM [Category]"></asp:SqlDataSource>
6.3.3
运行效果
设置页面Default.aspx为起始页面,运行工程Example_6_3之后,页面Default.aspx的初始化界面如图6-15所示。
6.4 创建用户控件
ASP.NET Web用户控件能够在其中放置标记和Web服务器控件的容器,并且可以将用户控件作为一个单元对待,为其定义属性和方法。它与ASP.NET网页有以下几点不同:
(1)用户控件的文件扩展名为 .ascx。
(2)用户控件中包含@Control指令,而不再使用@Page指令。其中@Control指令对配置及其他属性进行定义。
(3)用户控件不能作为独立文件运行。
(4)用户控件中不包含html、body或form元素。
工程Example_6_4中的页面Default.aspx和用户控件UserLoginUC.ascx介绍了用户控件的创建和使用方法。
6.4.1
用户控件设计
在工程Example_6_4中创建一个用户控件,名称为UserLoginUC.ascx,该控件实现用户登录功能。在用户控件UserLoginUC.ascx上添加两个TextBox控件、一个Button控件,名称分别为UserName、Password、LoginBtn。控件UserName和控件Password分别用来输入用户名称和用户密码;控件LoginBtn实现用户登录功能。用户控件UserLoginUC.ascx的设计界面如图6-16所示。
用户控件UserLoginUC.ascx的部分HTML设计代码如下:
<%@ Control Language="C#" AutoEventWireup="true"
CodeFile="UserLoginUC.ascx.cs" Inherits="UserLoginUC" %>
名称:</font><asp:textbox id="UserName" runat="server" cssclass="InputCss"
width="150px"></asp:textbox>
密码:</font><asp:textbox id="Password" runat="server" cssclass="InputCss"
width="150px" textmode="password"></asp:textbox>
<asp:Button ID="LoginBtn" runat="server" Text="用户登录"
CssClass="ButtonCss"
Width="80px"></asp:Button>
6.4.2
界面设计
在页面Default.aspx上添加在6.4.1小节用户控件设计中创建的名称为MyUserLoginUC的用户控件UserLoginUC.ascx。其中,注册用户控件UserLoginUC.ascx的程序代码为:
<%@ Register Src="UserLoginUC.ascx" TagName="UserLoginUC"
TagPrefix="ucUserLogin" %>
页面Default.aspx的设计界面如图6-17所示。
页面Default.aspx的部分HTML设计代码如下:
<%@ Register Src="UserLoginUC.ascx" TagName="UserLoginUC"
TagPrefix="ucUserLogin" %>
<ucUserLogin:UserLoginUC ID="MyUserLoginUC" runat="server" />
图6-17 页面Default.aspx的设计界面
6.4.3
事件设计
函数SqlDataReader GetUserLogin(string sUserName,string sPassword)根据用户名称和密码从数据库ShoppingDB中获取用户登录信息,它的程序代码如下:
public SqlDataReader GetUserLogin(string sUserName,string sPassword)
{ //创建链接
SqlConnection myConnection = new SqlConnection(
ConfigurationManager.ConnectionStrings[
"SQLCONNECTIONSTRING"].ConnectionString);
//定义SQL语句
string cmdText = "SELECT UserID FROM Users WHERE UserName ="
+ "'" + sUserName.ToString() + "'"
+ " AND Password ="
+ "'" + sPassword.ToString() + "'";
//创建Command
SqlCommand myCommand = new SqlCommand(cmdText,myConnection);
//定义DataReader
SqlDataReader dr = null;
try
{ //打开链接
myConnection.Open();
//读取数据
dr = myCommand.ExecuteReader(CommandBehavior.CloseConnection);
}
catch(SqlException ex)
{ //抛出异常
throw new Exception(ex.Message,ex);
}
//返回DataReader
return dr;
}
当用户输入用户名称和密码之后,并单击页面Default.aspx中的【登录】按钮时,触发事件LoginBtn_Click1(object sender,EventArgs e)实现用户登录功能。其中,函数SqlDataReader GetUserLogin (string sUserName,string sPassword)根据用户名称和密码从数据库ShoppingDB中获取用户登录信息。事件LoginBtn_Click1(object sender,EventArgs e)的程序代码如下:
protected void LoginBtn_Click1(object sender,EventArgs e)
{
if(UserName.Text == null || UserName.Text == ""
|| UserName.Text.Length <= 0)
{
ShowMessage("用户名称为空,请输入用户名称!");
return;
}
if(Password.Text == null || Password.Text == ""
|| Password.Text.Length <= 0)
{
ShowMessage("用户密码为空,请输入用户密码!");
return;
}
String userId = "";
//定义类并获取用户的登录信息
SqlDataReader recu
= GetUserLogin(UserName.Text.Trim(),Password.Text.Trim());
//判断用户是否合法
if(recu.Read()){userId = recu["UserID"].ToString();}
recu.Close();
//验证用户合法性,并跳转到系统平台
if((userId != null) && (userId != ""))
{
Session["UserID"] = userId;
//显示登录之后的消息
ShowMessage("用户登录成功!!!");
}
else
{ //显示错误信息
ShowMessage("你输入的用户名称/密码有误,请重新输入!");
}
}
函数ShowMessage(string sMsg)向页面显示操作结果信息,它的程序代码如下:
private void ShowMessage(string sMsg)
{ //显示操作结果信息
Response.Write("<script>window.alert('" + sMsg + "')</script>");
}
6.4.4
运行效果
设置页面Default.aspx为起始页面,运行工程Example_6_4之后,页面Default.aspx的初始化界面如图6-18所示。如果用户登录成功,则弹出信息提示对话框,如图6-19所示。
图6-18 页面Default.aspx的初始化界面
图6-19 登录成功信息提示对话框
6.5 创建自定义控件
ASP.NET自定义控件是编写的一个类,此类从Control或WebControl派生。使用自定义控件可以提供程序代码的重用性,即一个自定义控件可以在网页、自定义控件或控件的内部都可以再次使用。
工程Example_6_5中的页面Default.aspx和自定义控件MyCalendar介绍了自定义控件的创建和使用方法。
6.5.1 自定义控件MyCalendar设计
设计自定义控件MyCalendar是一个比较复杂的过程,在此,笔者把创建自定义控件MyCalendar的过程分为如下6个步骤:
(1)引入命名空间CustomControls;
(2)定义类CalendarItem作为自定义控件的子项;
(3)定义类MyCalendar作为自定义控件;
(4)设计自定义控件MyCalendar的属性;
(5)设计自定义控件MyCalendar的事件和方法;
(6)设计自定义控件MyCalendar的Render()方法。
下面将介绍上述几个设计步骤的详细实现方法。
步骤(1)引入命名空间CustomControls,步骤(2)定义类CalendarItem作为自定义控件的子项,并在类CalendarItem定义了属性DataItem。步骤(1)和步骤(2)的程序代码如下:
namespace CustomControls
{
// <summary>
// 定义CalendarItem
// </summary>
public class CalendarItem:Control,INamingContainer
{
// <summary>
// 数据行
// </summary>
private DataRow m_dataItem;
// <summary>
// 构造函数
// </summary>
// <param name="dr"></param>
public CalendarItem(DataRow dr)
{
m_dataItem = dr;
}
// <summary>
// 属性DataItem
// </summary>
public DataRow DataItem
{
get { return m_dataItem; }
set { m_dataItem = value; }
}
}
步骤(3)定义类MyCalendar作为自定义控件,继承于类INamingContainer和类Calendar,并还定义了几个私有成员变量,程序代码如下:
// <summary>
// 定义MyCalendar控件
// </summary>
public class MyCalendar:Calendar,INamingContainer
{
// <summary>
// 数据源
// </summary>
private object m_dataSource;
// <summary>
// 数据成员
// </summary>
private string m_dataMember;
// <summary>
// 域
// </summary>
private string m_dayField;
// <summary>
// 模板
// </summary>
private ITemplate m_itemTemplate;
// <summary>
// 模板
// </summary>
private ITemplate m_noEventsTemplate;
// <summary>
// 样式
// </summary>
private TableItemStyle m_dayWithEventsStyle;
// <summary>
// 数据源
// </summary>
private DataTable m_dtSource;
步骤(4)定义了自定义控件MyCalendar的属性DataSource、属性DataMember、属性DayField、属性DayWithEventsStyle、属性ItemTemplate和属性NoEventsTemplate。
属性DataSource是自定义控件MyCalendar的数据源;属性DataMember是自定义控件MyCalendar的数据成员;属性DayField是自定义控件MyCalendar数据域的名称;属性DayWithEventsStyle是自定义控件MyCalendar的事件风格;属性ItemTemplate是自定义控件MyCalendar定义的一种模板;属性NoEventsTemplate是自定义控件MyCalendar定义的一种不包含事件的模板。定义上述属性的程序代码如下:
// <summary>
// 属性DataSource
// </summary>
public object DataSource
{
get { return m_dataSource; }
set
{ //设置数据源
if(value is DataTable || value is DataSet){m_dataSource = value;}
else
{
throw new Exception("数据源必须为DataTable对象或者DataSet对象。");
}
}
}
// <summary>
// 属性DataMember
// </summary>
public string DataMember
{
get { return m_dataMember; }
set { m_dataMember = value; }
}
// <summary>
// 属性DayField
// </summary>
public string DayField
{
get { return m_dayField; }
set { m_dayField = value; }
}
// <summary>
// 属性DayWithEventsStyle
// </summary>
public TableItemStyle DayWithEventsStyle
{
get { return m_dayWithEventsStyle; }
set { m_dayWithEventsStyle = value; }
}
// <summary>
// 属性ItemTemplate
// </summary>
[TemplateContainer(typeof(CalendarItem))]
public ITemplate ItemTemplate
{
get { return m_itemTemplate; }
set { m_itemTemplate = value; }
}
// <summary>
// 属性NoEventsTemplate
// </summary>
[TemplateContainer(typeof(CalendarItem))]
public ITemplate NoEventsTemplate
{
get { return m_noEventsTemplate; }
set { m_noEventsTemplate = value; }
}
步骤(5)设计自定义控件MyCalendar的事件和方法,自定义控件MyCalendar的构造函数MyCalendar()继承于函数base(),它设置自定义控件MyCalendar的选择模式和显示网格。构造函数MyCalendar()的程序代码如下:
// <summary>
// 构造函数
// </summary>
public MyCalendar(): base()
{
this.SelectionMode = CalendarSelectionMode.None;
this.ShowGridLines = true;
}
方法SetupCalendarItem(TableCell cell,DataRow r,ITemplate t)构建一个日历表格。如果日历表格存在模板,则需要添加该模板到日历表格中。方法SetupCalendarItem(TableCell cell, DataRow r,ITemplate t)的程序代码如下:
// <summary>
// 重新构建每一个日历表格
// </summary>
// <param name="cell"></param>
// <param name="r"></param>
// <param name="t"></param>
private void SetupCalendarItem(TableCell cell,DataRow r,ITemplate t)
{
CalendarItem dti = new CalendarItem(r);
t.InstantiateIn(dti);
//数据绑定
dti.DataBind();
//添加数据
cell.Controls.Add(dti);
}
步骤(6)设计自定义控件MyCalendar的Render()方法。自定义控件MyCalendar重写了方法void OnDayRender (TableCell cell,CalendarDay day),即重新构建日历日(天)表格,并调用方法SetupCalendarItem (TableCell cell,DataRow r, ITemplate t)添加模板中的控件。方法void OnDayRender (TableCell cell,CalendarDay day)的程序代码如下:
// <summary>
// 重新构建DayReader
// </summary>
// <param name="cell"></param>
// <param name="day"></param>
protected override void OnDayRender(TableCell cell,CalendarDay day)
{
if(m_dtSource != null)
{ //格式化
DataView dv = new DataView(m_dtSource);
dv.RowFilter = string.Format("{0} >= #{1}# and {0} < #{2}#",
this.DayField,day.Date.ToString("MM/dd/yyyy"),
day.Date.AddDays(1).ToString("MM/dd/yyyy"));
if(dv.Count > 0)
{ //添加样式
if(this.DayWithEventsStyle != null)
{
cell.ApplyStyle(this.DayWithEventsStyle);
}
//加载模板
if(this.ItemTemplate != null)
{ //加载模板的控件
for(int i = 0; i < dv.Count; i++)
{
SetupCalendarItem(cell,dv.Row,this.ItemTemplate);
}
}
}
else
{ //加载模板
if(this.NoEventsTemplate != null)
{
SetupCalendarItem(cell,null,this.NoEventsTemplate);
}
}
}
base.OnDayRender(cell,day);
}
自定义控件MyCalendar重写了方法Render(HtmlTextWriter html),即自定义控件MyCalendar在页面上呈现的方式。方法Render(HtmlTextWriter html)的程序代码如下:
// <summary>
// 重新构建Reader
// </summary>
// <param name="html"></param>
protected override void Render(HtmlTextWriter html)
{ //定义数据源
m_dtSource = null;
if(this.DataSource != null && this.DayField != null)
{ //设置数据源
if(this.DataSource is DataTable)
{
m_dtSource = (DataTable)this.DataSource;
}
if(this.DataSource is DataSet)
{ //数据源为DataSet对象
DataSet ds = (DataSet)this.DataSource;
if(this.DataMember == null || this.DataMember == "")
{
m_dtSource = ds.Tables[0];
}
else{m_dtSource = ds.Tables[this.DataMember];}
}
if(m_dtSource == null){throw new Exception("数据源错误。");}
}
base.Render(html);
}
6.5.2 界面设计
在页面Default.aspx上添加在6.5.1小节自定义控件MyCalendar设计中创建的自定义控件MyCalendar,名称为cal1。其中,注册自定义控件MyCalendar的程序代码如下:
<%@ Register Namespace="CustomControls" tagprefix="cc" %>
注册自定义控件MyCalendar成功之后,在控件中添加一个<ItemTemplate >模板。页面Default.aspx的设计界面如图6-20所示。
页面Default.aspx的部分HTML设计代码如下:
<%@ Register Namespace="CustomControls" tagprefix="cc" %>
<cc:MyCalendar id="cal1" runat="server" width="100%" DayField="Day"
BackColor="#FFFFCC" BorderColor="#FFCC66" BorderWidth="1px"
DayNameFormat="Shortest" Font-Names="Verdana" Font-Size="8pt"
ForeColor="#663399" Height="200px" Selecti
ShowGridLines="True">
<SelectedDayStyle BackColor="#CCCCFF" Font-Bold="True" />
<TodayDayStyle BackColor="#FFCC66" ForeColor="White" />
<SelectorStyle BackColor="#FFCC66" />
<OtherMonthDayStyle ForeColor="#CC9966" />
<NextPrevStyle Font-Size="9pt" ForeColor="#FFFFCC" />
<DayHeaderStyle BackColor="#FFCC66" Font-Bold="True" Height="1px" />
<TitleStyle BackColor="#990000" Font-Bold="True" Font-Size="9pt"
ForeColor="#FFFFCC" />
<ItemTemplate>
<br />
<a href='Event.aspx?Eventid=<%# Container.DataItem["EventID"] %>'>
<font color='<%# Container.DataItem["Color"] %>'>
<%# Container.DataItem["Title"] %></font>
</a>
</ItemTemplate>
</cc:MyCalendar>
6.5.3 事件设计
函数DataTable GetEventData()创建自定义控件cal1的数据源——DataTable对象,并且在数据源中添加了4个事件,如“今天的事情”、“明天的事情”、“明天的事情 002”和“下一周的事情”。函数Page_Load(Object o,EventArgs e)设置自定义控件cal1的数据源为函数GetEventData()的返回值。
函数Page_Load(Object o,EventArgs e)和函数GetEventData()的程序代码如下:
protected void Page_Load(Object o,EventArgs e)
{
cal1.DataSource = GetEventData();
}
private DataTable GetEventData()
{
DataTable dt = new DataTable();
dt.Columns.Add("EventID",typeof(int));
dt.Columns.Add("Title",typeof(String));
dt.Columns.Add("Day",typeof(DateTime));
dt.Columns.Add("Color",typeof(System.Drawing.Color));
DataRow r = dt.NewRow();
r["EventID"] = 1;
r["Title"] = "今天的事情";
r["Day"] = System.DateTime.Today;
r["Color"] = System.Drawing.Color.Black;
dt.Rows.Add(r);
r = dt.NewRow();
r["EventID"] = 2;
r["Title"] = "明天的事情";
r["Day"] = System.DateTime.Today.AddDays(1);
r["Color"] = System.Drawing.Color.Red;
dt.Rows.Add(r);
r = dt.NewRow();
r["EventID"] = 3;
r["Title"] = "明天的事情 002";
r["Day"] = System.DateTime.Today.AddDays(1);
r["Color"] = System.Drawing.Color.Blue;
dt.Rows.Add(r);
r = dt.NewRow();
r["EventID"] = 4;
r["Title"] = "下一周的事情";
r["Day"] = System.DateTime.Today.AddDays(7);
r["Color"] = System.Drawing.Color.Green;
dt.Rows.Add(r);
return dt;
}
单击自定义控件cal1控件的链接,将跳转到页面Event.aspx,该页面首先从地址栏中获取参数EventID的值,然后根据参数EventID的值输出并显示不同的内容。这一功能由函数Page_Load(object sender, EventArgs e)实现,它的程序代码如下:
private string EventID = "";
protected void Page_Load(object sender, EventArgs e)
{
if(Request.Params["EventID"] != null)
{
EventID = Request.Params["EventID"].ToString();
}
switch(EventID)
{
case "1": Response.Write("今天的事情"); break;
case "2": Response.Write("明天的事情"); break;
case "3": Response.Write("明天的事情 002"); break;
case "4": Response.Write("下一周的事情"); break;
default: break;
}
Response.End();
}
本文来自: ASP.NET学习门户(http://www.aspx1.com) 详细出处参考:http://i.aspx1.com/showtopic-415-1.aspx