listView用法详解
ListView详解(一)
(原创:灰灰虫的家http://hi.baidu.com/grayworm) 在VS2008中新增了两个非常好用的两个数据控件:ListView和DataPager。使用这两个控件可以很灵活地实现数据的显示、分组、分页、排序、编辑、插入、删除等功能。 在VS2008之前,要显示集合型数据,我们一般会采用Repeater、DataList或GridView等控件来实现。GridView为我们提供了强大的数据显示功能,但是它把界面限制在一个标准的行列Table表格中,比如难以实现在一行显示多条数据的功能;DataList的界面灵活度比GridView要强一些,但使用起来远没有GridView那样简单方便;而Repeater一般是用来显示数据,它内存的事件与模板太少,功能不如DataList强大。ListView兼有GridView的易用性,又拥有DataList的灵活性,是我们DotNew开发的好工具。 签于网上介绍此控件的中文文章太少、太肤浅,在这篇文章中我们来深入研究一下ListView+DataPager的强大功能。
一、ListView初登场 像GridView和DataList等控件都会在显示数据的时候,会自动我们添加一些额外的标记,如:GridView会在未经我们同意的情况下,自动生成<table><tr><td>等元素,并把数据绑定显示在<td>中,虽然可以使用模板列来自定义列的显示,但模板列仍逃不出GridView强行加入的<table>标记,所以GridView做出来的办面往往是规规正正的二维表格,要应对企业开发中的各种表格化界面显得为不从心(虽然GridView也可以实现单元格的合并、GridView的嵌套,但工作量很大,自由度也很受限制)。 而ListView在显示数据的时候不会为我们强行添加任何额外的HTML标记,ListView界面的HTML代码完全由开发人员通过以下11个模板来自行控制的。 AlternatingItemTemplate EditItemTemplate EmptyDataTemplate EmptyItemTemplate GroupSeparatorTemplate GroupTemplate InsertItemTemplate ItemSeparatorTemplate ItemTemplate LayoutTemplate SeletedItemTemplate
其中比较常用的模板有LayoutTemplate和ItemTemplate两个模板,LayoutTemplate用来设置ListView外围的标记,而ItemTemplate是用来生成ListView绑定项的内容。 如:使用ListView显示列表项时,模板代码如下:
《图1 》
从上图我们看出,LayoutTemplate和ItemTemplate分别独立定义,那怎么来把二者进行组合形成一个显示界面呢?我们只需要在LayoutTemplate模板中定义一个“runat=server”的元素,并把这个元素的ID设为ListVieiw控件的ItemPlaceholderID属性所指定的值即可(ListView控件的ItemPlaceholderID属性的默认值为“itemPlaceholder”,如上图中我们定义PlaceHolder的ID就是“itemPlaceholder”。当然我也可以把 PlaceHolder的ID指定为另一个值“aaa”,但需要同时把ListView控件的ItemPlaceholderID的属性设为“aaa”)。 在ListView呈显的时候,就会把LayoutTemplate和ItemTemplate结合起来一起呈现: 首先:用ItemTemplate定义的数据项模板来生成记录项集合
《图2》 然后:再把生成的记录项集合内容替代LayoutTemplate中ID=itemPlacehoder的元素
《图3》
下面我们来试着做个例子显示数据: 在这里我们还是使用“汽车表”作为示例数据。ListView代码如下图所示
《图4》 在这个例子中,我们把ListView控件的ItemPlaceholderID属性修改为“placeForItem”,并在LayoutTemplate模板中把第二<tr>设置为runat="server",并且把该<tr>的ID也设置为“placeForItem”。在ItemTemplate模板中我们从<tr>开始设置模板,在运行的时候会用ItemTemplate生成的数据项(<tr>...</tr>)去替换LayoutTemplate中的<tr runat="server" ID="placeForItem"></tr> 运行结果:
《图5》
《图6》
二、分组显示数据 上面我们使用LayoutTemplate和ItemTemplate实现数据的显示,就是在LayoutTemplate中把要引用ItemTemplate数据项的服务端元素的ID设置为ListView控件的ItemPlaceholderID的值。这种显示方式直接把ItemTemplate生成的内容嵌入到LayoutTemplate中。有的时候这种显示方式不能满足需求,比如:想在一行中显示两项或多项数据的话,上面的方式就无能为力了。
《图7》 要实现上面这种效果就需要使用GroupTemplate模板。 它的实现思想不再是在LayoutTemplate中直接引用ItemTemplate了,而是在LayoutTemplate中引用GroupTempate,在GroupTemplate中再引用ItemTemplate,然后再设置ListView控件的GroupItemCount属性。 在运行的时候,先把ItemTemplate和GroupTemplate整合在一起,然后再根据ListView控件的GroupItemCount属性值,决定每个GroupTemplate中放置几个ItemTemplate。这样我们就可以在LayoutTemplate一行中显示多组数据了。
《图8》 从上面的代码中我们看出,就是在LayoutTemplate和ItemTemplate中间加了一个GroupTemplate。在每个GroupTemplate中显示三个ItemTemplate,然后再把所有GroupTemplate生成的内容嵌入到LayoutTemplate中去。
《图9》
上面的例子我们使用列表项实现分组数据显示,下面我们使用<table>表格实现分组数据的显示。 还是以汽车表为例,我要实现一行显示两辆车的信息。因此我们可以把显示表格设计成这个样子: <table id="listView"> <tr> <td> <table id="car">...</table> </td> <td> <table id="car">...</table> </td> </tr> </table> 外层<table>控制总体部局,外层<tr>控制一行显示几项信息,内层的<table>显示汽车详细信息。 1.ListView控件的GroupItemCount属性设置为2,这就意思着在一个GroupTemplate中显示两个ItemTemplate 2.ItemTemplate中设置如下: <td> <table id="car">...</table> </td> 3.GroupTemplate设置如下: <tr> <td runat="server" ID="placeForItem"></td> </tr> 4.LayoutTemplate设置如下: <table id="listView"> <tr runat="server" ID="placeForGroup"></tr> </table>
完整代码如下:
《图10》 运行结果:
《图11》(原创:灰灰虫的家http://hi.baidu.com/grayworm)
《图12》
三、排序数据 有的时候需要我们对数据进行排序显示,比如:论坛中按发表时间排序、按最后回复时间排序、按阅读次数排序、按回复数量排序等。ListView也像GridView一样为我们提供了免编码的排序功能,下面我们来看看: 在这里我们使用SqlDataSource为数据源,还是访问汽车表的数据,关于如何配置SqlDataSource数据源,在这里不再赘述。 我们要实现对两个字段的排序:“价格”和“油耗” 首选来看我们ListView模板的实现:
《图13》 从上图中我们看出,在汽车表格的上面我们加入了两个按钮,这两个按钮都设置了CommandName和CommandArgument。CommandName="Sort"代表这是个排序按钮,当它被点击的时候就会执行Sort()方法进行排序,并触发Sording和Sorted事件。CommandArgument用来指定按哪列排序,在这里我们指定列名。 这样就可以排序了,并且是升序、降序轮流执行的。
《图14》 这种排序功能实用性不大,主要原因是: 1.自动排序只能与DataSource控件结合使用,由DataSource控件排序后再绑定显示在List中,并且ListView排序对DataSource控件返回的数据类型有要求,即,它只能对DataSource控件返回的DataSet、DataTable和DataView进行自动排序,对理一般的泛型集合是不支持的。 2.需要把所有数据都读取到服务器内存(DataSet,DataTable,DataView)中,才能进行排序,资源利用效率不高。
如果要对泛型集合进行排序的话,那需要我们编写Sorting代码,把集合手动排序后再绑定到ListView中显示,同时要通过e.Cancel=true来阻止DataSource控件自动排序。
四、根据字段进行分组显示 上面我们介绍了如何对ListView进行分组,实现一行显示多条数据。但有的时候需要我们进行下面这种分组方式:
《图15》 即:根据某个字段的值不同,对数据分组显示。 ListView默认没有这个功能,但我们可以通过一系列的技巧来实现出来。 实现思路: 第一步、根据需要分组的字段把数据排序,这样就可以把该字段值相同的数据显示为相临的数据行,为我们以后分组提供方便。 这一步我们可以在BLL层中使用LinQ来实现 public class MyDBBF { private MyDBDataContext _Context = new MyDBDataContext(); public List<Car> GetCars() { return _Context.Car.OrderBy(p=>p.Brand1.Prod_Code).ToList(); } }
第二步、添加分组头。 我们可以在ItemTemplate中,在每次绑定数据行显示之前判断是否需要添加分组头。
《图16》 从上图中我们看到这样一段代码: <%# ShowGroupHeader() %> 这是我在aspx.cs中定义的一个方法,此方法决定分组头的显示。该方法的代码如下:
《图17》 这个方法在每行绑定的时候都会被调用到 变量headerText代表上一行分组头的文字(即汽车厂商),变量currentHeader代表当前分组字段值,如果二者相等,说明这一行和上一行属于同一个分组,不需要加分组头,就返回空字符串。如果二者不等,说明这一行与上一行不属同一个分组,就添加一个<tr>表头。 第三步、运行。 运行效果如下:
《图18》 (原创:灰灰虫的家http://hi.baidu.com/grayworm)