1. ListView控件的使用
Repeater一般只用来展示数据,如果要对数据进行增删改查则用ListView更方便。使用想到来使ListView自动生成很多模版,免去手写模版的麻烦,我们可以对生成的模版再进行手工的调整以满足具体需求。
首先设定数据源,然后点击智能提示中的“配置ListView”,选择一种布局方式,然后根据需要选择“启用编辑”、“启用插入”、“启用分页”、就会自动的生成常用的模版。注意:这样只是提高开发的效率,而不是唯一的途径。
LayoutTemplate为布局模版,布局模版中必须有一个id为itemPlaceholder的服务端控件,什么类型的控件都可以,不会被显示,只是作为一个填充内容区的标志。之上相当于Repeater中的HeaderTemplate,之下就相当于FooterTemplate。因此这是Header和Footer的结合。
ItemTemplate是每一项的模版,AlternatingItemTemplate是隔行显示的模版,和Repeater一样。EmptyDataTemplate为数据源没有数据的时候显示的内容,例如显示:没有查找结果。
InsertTemplate是插入数据界面的模版,EditItemTemplate为编辑数据的模版,SelectedItemTemplate为标记为selected的行的模版。
总结:自动生成的模版,我们需要做适当的调整:
1. 生成的样式要提到style中,不要内联样式。
2. ItemTemplate里面一般也没有必要用<asp:Label来展示只读数据,所以直接输出<%#Eval(“Name”)%>
3. LayoutTemplate中必须有一个itemplaceholder的服务端控件,之上为头,之下为尾。
4. LayoutTemplate表头内容要汉化,所有Template中的不必要显示的数据字段,比如id,都要删掉。
5.
编辑,插入模版中的数据绑定表达式为Text='<%# Bind("Sex") %>' 不是Eval()。Bind表示双向绑定,不但需要从数据库中呈现数据到控件,还需要从控件中更新数据到数据库中。
通过每行的Insert、Delete、Edit、Cancel等Command进行增删改,这几个CommandName被listView内部处理,因此自定义的CommandName不要和它们重复。ListView中可以像Repeater那样为行增加command按钮,处理方法和Repeater一样,ListView也支持Repeater那样的ItemDataBound事件。
ListView中可以使用Validator,只要将Validator放入相应的模版中,将Validator手动设置要验证的控件id,然后设置相应的控件、按钮、validator为同样的ValidationGroup组,防止不同模版中的validator互相干扰。将Cancel按钮的CausesValidation=“false”;
ItemCreated事件:每一行在页面上的创建都会触发这个事件。
可以通过该事件为新增数据行设置默认值:例如插入的数据中,性别默认都填写“男”。
就可以在此事件中处理: 当e.Item.ItemType为InsertItem的时候通过FindControl找到性别文本框,然后初始化。设置Text为“男”。
if (ddl != null && LogoURLTextBox != null)
{ //在服务端写一些客户端脚本。
ddl. ["onchange"] = "onLinkTypeChange(this,'"+LogoURLTextBox.ClientID+"')";
if (ddl.SelectedValue == "文本") //vs2010中取得的ClientID有错
{
LogoURLTextBox.Style["display"] = "none";
}
}
ItemInserting事件:数据在插入数据库之前会触发这个事件。
如果主键是Guid类型的,就可以在此事件内处理:生成一个Guid数据,然后赋值给e.Values[“Id”].
protected void ListView1_ItemInserting(object sender, ListViewInsertEventArgs e)
{
//e.Values["Sex"] = "男"; //在插入数据库之前,把性别改为男。则无论输入什么,最终都会是男”
//e.Values["Sex"]就是即将要插入的性别字段的值。
}
所以可以通过e.Values进行输入校验,如果不合法,可以通过e.Cancel=true来取消非法数据输入。但是一般不这样做,直接用验证控件。
ObjectDataSource绑定Id为Guid类型的表的时候会生成一个“DataObjectTypeName=”System.Guid””,有问题,删掉就行。
同样可以在数据更新之前对数据进行处理。ItemUpdating事件。
protected void ListView1_ItemUpdating(object sender, ListViewUpdateEventArgs e)
{
if (Convert.ToString(e.OldValues["Name"]) == "小小鸟")
{
e.Cancel = true; //无权更新名为小小鸟字段的信息
}
}
如果主键ID是Guid类型的,则通过
e.Values["Id"] = Guid.NewGuid();//很奇怪,每次产生的都是全0的序号
//我把入库类型用DropDownList展示,从另一个表中拿数据再此显示。但是插入时却用问题,待解决。
DropDownList ddList = (DropDownList)e.Item.FindControl("DropDownList1");
e.Values["ComeInType"] = ddList.SelectedValue;
ListView中的行命令:
ListView的行按钮和Repeater一样,不同的是取当前行数据的方式。
int index = e.Item.DisplayIndex;
protected void ListView1_ItemCommand(object sender, ListViewCommandEventArgs e)
{
if (e.CommandName == "IncAge")
{
int index = e.Item.DisplayIndex;
int userno = Convert.ToInt32(ListView1.DataKeys[index].Value);//取得当前行的主键
UserDataTableAdapter user = new UserDataTableAdapter();
user.IncAgeByUserNo(userno);
ListView1.DataBind();
}
}
ListView1.DataKeys[index].Value还有一个属性是values属性,这个是当多个字段都是主键的时候,用到的。比如id和name都是主键。引用的方法则是ListView1.DataKeys[index].Value[“Id”] .一般情况下只用id即可。
ListView内置的排序机制:
将LayoutTemplate中表头用,
<asp:Button runat="server" CommandName="Sort" CommandArgument="Age" Text="Age排序"></asp:Button>
只要是CommandName、CommandArgument对就行了。展现成什么,显示在哪里都可以。
CommandName="Sort"是命令名。CommandArgument=“要排序字段名”
DataPage分页:
ListView搭配DataPager控件实现分页。有两种使用方式,一种是将DataPager声明到ListView中;一种是DataPager、ListView没有嵌套关系,然后将DataPager的PagedControlID设定为要分页的ListView。没有什么区别,一般用“配置ListView”自动生成的内置方式即可。DataPager的PageSize数据为一页的条数。
.(*)实现了IpageableItemContainer接口的控件都可以使用DataPager进行分页,但是asp.net目前只有ListView实现了这个接口。
高效率分页:
ListView默认的分页是先从数据源取得所有数据,然后再截取当前页面请求显示的部分。在数据量非常大的情况下,效率非常低下,因此默认的分页基本上不能用。应该是从数据也取得要显示的数据。
所以分页的时候,我们要自己写sql语句。筛选出要显示的记录。
Sql语句中获得每一行序号的方法:
SELECT Id,UserName,UserType , row_number() over(order by id)行号
FROM UserManage。 Row_number()函数是SQL2005之后提供的一个计算结果集行的函数(不是表的行号),over中指定排序规则,Row_number()从1开始。
取得第11到15条数据的方法。用嵌套查询的方式,把含有结果集行号的集合做二次查询筛选:
select *
from(SELECT Id,UserName,UserType , row_number() over(order by id)行号
FROM UserManage)t where t.行号>10 and t.行号<=15
在强类型Dataset中增加取得所有数据条数的方法Querycount,增加取得指定行数范围数据的方法GetPagedData:
由于数据集编辑器不支持(不是运行的时候不支持,而是设计器不会自动帮我们生成一些东东)Row_Number(),所以创建完成后需要手动的在GetPagedData属性的Parmmeters中增加两个参数:startRowIndex、maximumRows(参数名必须是这两个,只是由ObjectDataSource的StartRowIndexParamterName、MaximumRowsParamterName确定的,一般不需要改。)都是Int32类型。
通过ObjectDataSource去执行写好的方法。GetPagedData: 和QueryCount方法。ObjectDataSource支持这种方式。所有要设置其属性EnablePaging="True"
SelectCountMethod="QueryCount" 数据源取得数据的方法是这个:SelectMethod="GetPagedData"