ASP.NET DataGrid 高级使用技巧
传统ASP与ASP.NET在数据呈现方面的比较
ASP | |
建立数据库连接 代码 | 缺点
|
ASP.NET | |
转载数据到Dataset
|
|
三种数据绑定控件的使用领及选择
DataGrid优缺点
优点:
灵活性强,内置事件丰富
提供分页、编辑、排序等特性
功能强大的DataGrid编辑器以及模版列
快速开发、容易部署
对于表格的操作非常方便
内置多种布局风格
缺点:
性能不高(因为每次操作必须postback回服务器)
个性化输出数据有限(只能输出html表格)
DataList优缺点
拥有强大的模版特性,灵活性高
支持数据的编辑状态
性能优于DataGrid
开发周期略比Datagrid高
没有Datagrid编辑器
不容易实现分页和排序功能
Repeater优缺点
控件完全以HTML方式呈现,更加个性化
不支持编辑、分页、排序功能
开发周期最长
不提供默认的风格,须手工编写
性能最好,但特性最少
三者使用范围
Datagrid: 主要用在含有数据的表格中,一般数据源是一个dataset。对于有排序、分页、多列显示、对性能要求不是很高一般选用Datagrid。
DataList: 主要用于单列的数据列表、高性能的自定义的数据表、每行多条记录,如:电子相册(含分页)
Repeater:主要应用一些灵活性、性能更高的一些数据展现
性能比较(压力测试)
注意事项:
Datagrid生成过大的ViewState(Base64),导致性能最差
处在WebForm节点下的控件性能要优于无WebForm下的控件
DataGrid 整体介绍
要点:
Datagrid类似于数据库的表格
记录集由行集(items)和列集(columns)组成
行集由多个datagridColumn组成
列集由多个datagriditem组成
DataGrid Column的介绍
BoundColumn:文本字段标准显示,当处于编辑状态,将显示为TextBox
HyperLinkColumn:显示文本数据,同时是一个URL超链接
ButtonColumn:按钮列,包括:
选择按钮 | 无后台事件,可改变选中行的颜色 |
删除按钮 | DeleteCommand事件 |
更新按钮 | UpdateCommand事件 |
编辑按钮 | EditCommand事件 |
普通按钮 | ItemCommand事件 |
风格:LinkButton、PushButton;
TemplateColumn:模版列,完全控制哪些控件显示给用户;分为多种模版,如图
HeaderTemplate | 用于对页眉的自定义操作 |
ItemTemplate | 项模版,用于显示自定义数据 |
EditItemTemplate | 编辑模版,即:当控件处于编辑状态时,该单元处于哪种状态。 |
FooterTemplate | 用于对页脚的自定义操作 |
注意事项:非模版列均可以转换为模版列来增加更灵活的功能
使用DataGrid注意事项
需要更大的灵活性时,建议不要使用自动生成的列。
如果设置了自动生成列,并且在 Datagrid 中指定了列,那么最终将得到对列的重复设置。系统将首先显示特别声明的列,随后是所有自动生成的列。
切忌不可仅使用控件 ID 来引用 Datagrid 项目中的控件
例如: 定义了一个textbox1的textbox控件,事实上,为了确保id在html里不重复,每行的textbox前都加上了不同的前缀,
如:DataGrid1:_ctl2:MyTextBox _ctl2: 代表textbox1的当前行。
须用FindControl 来指明
DataGrid Item 介绍
注意事项:
对于非模版列:datagriditem.Cells[第几个单元格].Controls[第几个控件]
下标从0开始
可以转换成相应的控件,如:
boundColumn: Label EditColumn: TextBox LinkColumn:DataGridLinkButton …
当模版列时,Control的index必须都加一,因为Control[0]:LiteralControl=“ ”
建议:
当知道控件ID值,建议采用datagriditem.findcontrol[“控件名称”] 来获得
DataGrid Item 构建行的流程(itemcreated)
DataGrid绑定事件的触发流程
注意事项
DataBinding:只要执行了DataBind方法,就会马上激发这个事件。
ItemCreated主要是创建行(行容器),ItemDataBound将数据存放于该“行容器”中(数据绑定)。依次循环
如要在创建时手工添加自定义控件(不使用模版列),则需要在ItemCreated事件中绑定
DataGrid绑定事件的常见问题
引用e.Item.DataItem 报错“对象不能为null ”
原因:没有在itemcreated和itemdatabound下判断行类型.
(DataRowView)(e.Item .DataItem) 只有在: item行、AlternatingItem行、selecteditem行、edititem行才有值
数据绑定完之后如何访问某行数据?
可以使用datagriditem来搜索,代码结构如下:
for each (datagriditem dgi in Datagrid1.items)
{
}
切记:不可用dgi.dataitem 来访问,因为在itembound之后已重新为null
使用ItemCreated事件注意事项
private void DataGrid1_ItemCreated(object sender,DataGridItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item)
{
//此处添加对类型为Item的代码,
}
}
当加载、修改行属性或者行内的控件属性时,应该判断ItemType类型,因为每个单元格均有不同的项类型的呈现方式,如下表
数据绑定浅谈
简单属性 | <%# custID %> |
集合 | <asp:ListBox id="List1" datasource='<%# myArray %>' runat="server"> |
表达式 | <%# ( customer.First Name + " " + customer.LastName ) %> |
方法结果 | <%# GetBalance(custID) %> |
注意:
ASP.NET 数据绑定语法仅在调用 DataBind 方法时计算
模版列的数据绑定1
Container.DataItem容器方法:
DataItem指的是Datagrid某一行(可通过类型转换成DataRowView,并可以获取该行中的每个单元),即DatagridItem和Container.DataItem 功能相同。
例如:
1)循环获取已绑定的datagrid中列名为CustomerID(后期)
string str="" ;
foreach(DataGridItem dgi in DataGrid1.Items)
{
str +=((DataRowView)dgi.DataItem).Row["CustomerID"];
}
模版列的数据绑定2
2)在绑定datagrid数据的过程中获取CustomerID(ItemDataBound事件)
private void DataGrid1_ItemDataBound (object sender, System.Web.UI.WebControls.DataGridItemEventArgs e)
{ string str="";
if(e.Item.ItemType==ListItemType.Item)
{
str +=((DataRowView)e.Item.DataItem).Row["CustomerID"];
}
}
注意:DataItem仅适用于 DataGrid 控件中的数据项。即ListItemType必须是Item、AlternatingItem、SelectedItem 或 EditItem 才能访问,所以要加判断。
模版列的数据绑定3
DataBinder.Eval
<%# DataBinder.Eval(数据项的命名容器 ,数据字段名 ,格式字符串 )%>
对于Datagrid、DataList、Repeater的命名容器:Container.DataItem
缺点:性能不高(由于Eval采用反射机制)
DEMO: 实现有序的编号,体现数据绑定的强大
ItemCommand事件
模版列中的子控件的事件--“冒泡事件 ”
参见MSDN
EditCommand、DeleteCommand 和 UpdateCommand,它们是冒泡事件的特殊事例。
好处:它的参数使您可以发现是哪个控件引发了该事件,从而避免了为子控件编写事件模型
提问:如果子控件没有commandName属性怎么办(dropdownlist)?
个性化分页技巧
分页栏 |
Label |
LiteralControl |
DataGridLinkButton |
Label:负责显示当前页,也就是选择页.
LiteralControl:负责显示一个空格,用来间隔它们之间的距离
DataGridLinkButton:显示连接,用来连接到其它页,如下一页.
DataGridLinkButton |
LiteralControl |
默认的只有数字,可以在ItemCreated事件中的ItemType==ListItemType.Pager修改默认的呈现
【实例代码】
制作个性化的分页
对于DataList分页,必须利用sqlDataAdapter填充方法来实现分页
Datagrid的点击列头之后的升降序技巧
主要步骤:
设置“允许排序”
设置每个列的排序表达式
调用事件SortCommand,当点击header的连接将触发该事件
【实例代码】
private void DataGrid1_SortCommand(object source, DataGridSortCommandEventArgs e)
{
ViewState[“Sort”]=e.SortExpression;获取表达式
if ((string)ViewState["orderby"]=="asc")
ViewState["orderby"]="desc";
else
ViewState["orderby"]="asc";
bindDate();
}
if (e.Item.ItemType==ListItemType.Header)
{
foreach(TableCell c in e.Item.Cells)
{
if (c.Controls.Count >0 && c.Controls[0].GetType().ToString()=="System.Web.UI.WebControls.DataGridLinkButton")
{
if (((LinkButton)c.Controls[0]).Text==(string)ViewState["Sort"])
{
Label l=new Label();
l.Font.Name="Webdings";
if ((string)ViewState["orderby"]=="asc")
l.Text="5";
else
l.Text="6";
c.Controls.Add(l); //添加标记到header
}
}
}
}
void bindDate()
{
sqlDataAdapter1.Fill(dsCustomers1,"Customers");
DataView dv=new DataView(dsCustomers1.Customers);
if ((string)(ViewState["Sort"])!="")
{
dv.Sort=(string)ViewState[“Sort”]+“ ”+ViewState[“orderby”]; //设置dataview的排序
}
DataGrid1.DataSource=dv;
DataGrid1.DataBind();
}
DataGrid插入空行
思路:
采用在页脚处插入空行的做法
主要步骤:
1) 在itemcreated事件中插入新行及按钮
2) 设置按钮的comandname
3) 在itemCommand事件中编写插入代码
DataGrid自定义列的封装
为什么要实现封装?-- 提高灵活性、可复用性
继承DatagridColumn类
DatagridColumn属性: |
FootStyle |
FootText |
HeaderImageURL |
HeadStyle |
HeadText |
ItemStyle |
SortExpression |
Overrides |
DataGrid自定义列的方法
Initialize
InitializeCell (=Datagrid中的itemcreated)
LoadViewState
OnColumnChanged
SaveViewState
TrackViewState
【实例代码】
构建自定义列
DataGrid封装成自定义组件
最主要的重载函数InitializeItem
protected virtual void InitializeItem( DataGridItem item, DataGridColumn[] columns );
Columns:该行的所有列
TableCell |
列的InitializeCell |
Datagriditem.cells集合中 |
【实例代码】
构建自定义的Datagrid
小结
Itemcreated绑定行控件,itemdatabound绑定行数据
必需要判断ListItemType的类型
可以通过Itemdatabound或者后期循环获取的方式来获取数据或控件
采用datagriditem.findcontrol[“控件名称”]来获取控件
通过itemcreated可以修改控件、加载控件等
当datagrid代码过多或使用次数过多时,尽量编写自定义的datagrid或者自定义列
自定义列中一般重载InitializeCell(itemcreated)
自定义datagrid中一般重载InitializeItem