公司最近的一个项目需要涉及到动态订单,即每位用户订单数据表的属性列是可以自定义的,数据表字段是动态的,所以使用GridView等控件对未知数据表进行操作时,需要使用动态模板。实现如下:
为GridView控件创建自定义模板
当使用模板控件时,可能直到运行时还不了解所需要的模板,或者模板中应该包括的文本或者控件。在这种情况下,可以在代码中动态创建模板。可以在代码中为所有使用模板的控件创建模板:DataList、Repeater、GridView、FormView、DetailsView等。对于GridView控件而言,使用模板可定义列,而不是其他控件那样的行布局模板。下面实例将介绍使用GridView控件自定义模板的应用程序。
GridView模板是实现ITemplate接口的类。该类定义了将在GridView列中显示的控件,以及数据如何绑定这些控件,同时还能够通过一些特定代码来处理页眉和页脚。就本例而言,将从零开始讲解一个简化的GridView示例,它使用模板格式化GridView的内容。虽然这个示例非常简单,但很多复杂的情况都可以通过扩展该示例实现。下面开始介绍自定义模板类的实现。
1.创建自定义模板类
自定义模板类(名称为CustomGridViewTemplate)包括的代码放置在GridView控件中,这些代码内的控件完成实际工作格式化控件,绑定数据的工作。由于CustomGridViewTemplate类实现ITemplate接口,所以该类提供了InstantiateIn()方法的实现。在该方法中定义了生成包括子控件的GridView控件的行为。示例一列举了该类的实现代码。
示例一:使用自定义模板格式化GridView
Code
1 public class CustomGridViewTemplate : ITemplate
2 {
3 private DataControlRowType _templateType;
4 private string _columnName;
5 private string _dataType;
6 public CustomGridViewTemplate(DataControlRowType templateType,
7 string columnName, string dataType)
8 {
9 _templateType = templateType;
10 _columnName = columnName;
11 _dataType = dataType;
12 }
13 /// <summary>
14 /// 此方法为 GridView执行DataBind方法后触发执行
15 /// 按行顺序向下执行(行->行中各列)
16 /// </summary>
17 /// <param name="container"></param>
18 public void InstantiateIn(System.Web.UI.Control container)
19 {
20 switch (_templateType)
21 {
22 case DataControlRowType.Header:
23 //创建当前列的标题
24 Literal literal = new Literal();
25 literal.Text = "<b><i><u>" + _columnName + "</u></i></b>";
26 container.Controls.Add(literal);
27 break;
28 case DataControlRowType.DataRow:
29 //创建当前列的一行
30 Label label = new Label();
31 switch (_dataType)
32 {
33 case "DateTime":
34 label.ForeColor = System.Drawing.Color.Blue;
35 break;
36 case "Double":
37 label.ForeColor = System.Drawing.Color.Violet;
38 break;
39 case "Int32":
40 label.ForeColor = System.Drawing.Color.Green; ;
41 break;
42 case "String":
43 label.ForeColor = System.Drawing.Color.Brown;
44 break;
45 default:
46 label.ForeColor = System.Drawing.Color.Green;
47 break;
48 }
49 // 注册用于数据绑定的事件处理程序
50 label.DataBinding += new EventHandler(this.label_DataBinding);
51 container.Controls.Add(label);
52 break;
53 default:
54 break;
55 }
56 }
57
58 /// <summary>
59 /// 当InstantiateIn执行完一行后,统一触发该绑定事件处理方法
60 /// </summary>
61 /// <param name="sender"></param>
62 /// <param name="e"></param>
63 private void label_DataBinding(Object sender, EventArgs e)
64 {
65 // 获取触发时间的控件
66 Label label = (Label)sender;
67 // 获取容器行
68 GridViewRow row = (GridViewRow)label.NamingContainer;
69 // 获取行数据值,并将其格式化
70 string rawValue = DataBinder.Eval(row.DataItem, _columnName).ToString();
71 switch (_dataType)
72 {
73 case "DateTime":
74 label.Text = String.Format("{0:d}", DateTime.Parse(rawValue));
75 break;
76 case "Double":
77 label.Text = String.Format("{0:###,###,##0.00}",
78 Double.Parse(rawValue));
79 break;
80 default:
81 label.Text = rawValue;
82 break;
83 }
84 }
85
本例仅使用了文本标签来显示数据,但是并不限于单个控件。该方法还通过注册事件处理程序来设置数据绑定:
// 为执行数据绑定注册事件处理程序
label.DataBinding += new EventHandler(this.label_DataBinding);
正如所期待的那样,当数据绑定到GridView时会调用数据绑定事件处理程序。在数据绑定事件处理程序中,获取了指向控件容器的引用,同时还格式化了数据。
2.使用模板
如果将CustomGridViewTemplate类存储到App_Code文件夹中,那么对于Web站点的所有ASP.NET页面而言,都可以使用该类。示例二列举了如何通过GridView控件使用CustomGridViewTemplate。
.CS文件
Code
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Collections;
using System.Data.SqlClient;
using System.Web.Configuration;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
string connectionString = WebConfigurationManager.ConnectionStrings["strDBConn"].ConnectionString;
DataTable deptTable = new DataTable();
using (SqlConnection connection = new SqlConnection(connectionString))
{
string sql = "select * from province";
SqlCommand command = new SqlCommand(sql);
command.CommandType = CommandType.Text;
command.Connection = connection;
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = command;
adapter.Fill(deptTable);
}
// 清除当前存在的列
//deptView.Columns.Clear();
// 递归DataTable,将列添加到GridView中
for (int i = 0; i < deptTable.Columns.Count; i++)
{
TemplateField templateField = new TemplateField();
// 创建数据行
templateField.ItemTemplate = new CustomGridViewTemplate
(DataControlRowType.DataRow,
deptTable.Columns[i].ColumnName,
deptTable.Columns[i].DataType.Name);
//创建标题
templateField.HeaderTemplate = new CustomGridViewTemplate
(DataControlRowType.Header, deptTable.Columns[i].ColumnName,
deptTable.Columns[i].DataType.Name);
// 将其添加到GridView
deptView.Columns.Add(templateField);
}
//绑定并显示数据
deptView.DataSource = deptTable;
deptView.DataBind();
ViewState["DbPrivance"] = deptTable;
}
}
protected void BtnDel_Click(object sender, EventArgs e)
{
DataTable deptTable = ViewState["DbPrivance"] as DataTable;
for (int i = deptView.Rows.Count-1; i >= 0; i--)
{
string strID = "";
CheckBox cbox = deptView.Rows[i].FindControl("CBoxSelected") as CheckBox;
if (cbox != null)
{
bool isChecked = cbox.Checked;
//调用删除操作方法
}
}
for (int i = 0; i < deptTable.Columns.Count; i++)
{
TemplateField templateField = new TemplateField();
// 创建数据行
templateField.ItemTemplate = new CustomGridViewTemplate
(DataControlRowType.DataRow,
deptTable.Columns[i].ColumnName,
deptTable.Columns[i].DataType.Name);
//创建标题
templateField.HeaderTemplate = new CustomGridViewTemplate
(DataControlRowType.Header, deptTable.Columns[i].ColumnName,
deptTable.Columns[i].DataType.Name);
// 将其添加到GridView
deptView.Columns.Add(templateField);
}
this.deptView.DataSource = deptTable;
this.deptView.DataBind();
}
}
public class CustomGridViewTemplate : ITemplate
{
private DataControlRowType _templateType;
private string _columnName;
private string _dataType;
public CustomGridViewTemplate(DataControlRowType templateType,
string columnName, string dataType)
{
_templateType = templateType;
_columnName = columnName;
_dataType = dataType;
}
/// <summary>
/// 此方法为 GridView执行DataBind方法后触发执行
/// 按行顺序向下执行(行->行中各列)
/// </summary>
/// <param name="container"></param>
public void InstantiateIn(System.Web.UI.Control container)
{
switch (_templateType)
{
case DataControlRowType.Header:
//创建当前列的标题
Literal literal = new Literal();
literal.Text = "<b><i><u>" + _columnName + "</u></i></b>";
container.Controls.Add(literal);
break;
case DataControlRowType.DataRow:
//创建当前列的一行
Label label = new Label();
switch (_dataType)
{
case "DateTime":
label.ForeColor = System.Drawing.Color.Blue;
break;
case "Double":
label.ForeColor = System.Drawing.Color.Violet;
break;
case "Int32":
label.ForeColor = System.Drawing.Color.Green; ;
break;
case "String":
label.ForeColor = System.Drawing.Color.Brown;
break;
default:
label.ForeColor = System.Drawing.Color.Green;
break;
}
// 注册用于数据绑定的事件处理程序
label.DataBinding += new EventHandler(this.label_DataBinding);
container.Controls.Add(label);
break;
default:
break;
}
}
/// <summary>
/// 当InstantiateIn执行完一行后,统一触发该绑定事件处理方法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void label_DataBinding(Object sender, EventArgs e)
{
// 获取触发时间的控件
Label label = (Label)sender;
// 获取容器行
GridViewRow row = (GridViewRow)label.NamingContainer;
// 获取行数据值,并将其格式化
string rawValue = DataBinder.Eval(row.DataItem, _columnName).ToString();
switch (_dataType)
{
case "DateTime":
label.Text = String.Format("{0:d}", DateTime.Parse(rawValue));
break;
case "Double":
label.Text = String.Format("{0:###,###,##0.00}",
Double.Parse(rawValue));
break;
default:
label.Text = rawValue;
break;
}
}
}
.ASPX文件
Code
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:GridView ID="deptView" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="CBoxSelected" runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<br />
<asp:Button ID="BtnDel" runat="server" Text="删除" OnClick="BtnDel_Click" />
<asp:Button ID="BtnModify" runat="server" Text="修改" /><br />
</div>
</form>
</body>
</html>
示例中唯一的技巧是将模板类关联到GridView。这是通过创建新的TemplateField对象,接着为ItemTemplate和HeaderTemplate将TemplateField与CustomGridViewTemplate关联起来实现的。注意,可以使用相同的方法来设置其他模板,例如AlternatingItemTemplate和FooterTemplate。