手机版

ASP.NET 2.0中的操作数据XXVII:创建自定义排序用户界面

时间:2021-11-01 来源:互联网 编辑:宝哥软件园 浏览:

简介

显示大量按类别排序的数据(不多),但没有类别分界线,用户很难找到需要的类别。例如,数据库中只有9个类别(8个不同的类别和1个null),总共有81个产品。现在,GridView用于列出所有产品。如果用户对海鲜类产品感兴趣,她会按类别进行排序,并一起排列。分类后,用户会寻找海鲜产品的起止地点。虽然按照英文字母分类查找海鲜并不难,但在GridView中查找仍然需要一些时间。为了进一步区分类别,很多网站使用类别分界线的排序用户界面来区分不同的类别。例如,图1中的分割线可以让用户快速找到所需的类别。

//files.jb51.net/file_images/article/201605/201605090846021.png

图1:不同的组被清楚地区分。

在本文中,我们将解释如何创建这种排序用户界面。

步骤1:创建一个普通的可以排序的GridView。

在我们学习如何创建一个增强的排序用户界面之前,我们首先创建一个普通的GridView,它列出了所有产品并可以对它们进行排序。现在,单击PagingAndSorting文件夹下的CustomSortingUI.aspx,添加一个GridView,设置ID='ProductList ',并使用ObjectDataSource作为数据源。ObjectDataSource的数据是从ProductsBLL类的GetProducts()获取的。

接下来,设置GridView的列,包括产品名称、类别名称、供应商名称、单价绑定列和停产复选框列,然后设置GridView允许排序。设置这些后,您应该能够在代码编辑中看到以下代码:

asp: GridView ID=' Product list ' runat=' server ' alloworting=' True ' AutoGenerateColumns=' False ' DataKeyNames=' Product ID ' data sourceid=' objectdata source E1 ' EnableViewState=' False ' Columns asp: boundfield data field=' Product name ' header text=' Product ' sort expression=' Product name '/asp: boundfield data field=' CategoryName ' header text=' Category ' ReadOnly='//files.jb51.net/file_images/article/201605/201605090846022.png

图2:根据类别可排序的网格视图。

步骤2:如何添加分界线。

在创建一个普通的、可排序的GridView之后,有必要在每个类别的第一行之前添加一条分界线。如何将这些分界线添加到GridView中?首先,我们会想到遍历GridView中的所有行,并在排序列中的值不同时插入分割线。根据这个想法,我们自然希望使用GridView的DataRowBound事件,我们已经在基于数据的自定义格式一章中讨论过了。DataRowBound事件通常用于格式化数据行。但是,DataRowBound事件不能解决这个问题,因为它不能用于向GridView动态添加行,并且GridView的Rows集合是只读的。

向GridView添加行有三种方法:

在GridView绑定数据源中向GridView绑定数据添加分割线后,向GridView控件集中添加额外的TableRow对象以创建自定义服务器控件,扩展GridView控件,并重写其方法以重构GridView结构。

如果自定义排序的用户界面广泛应用于多个页面或网站,创建自定义服务器控件是最好的方法。但是,使用这种方法需要编写太多的代码,并且需要深入了解GridView控件的内部原理。因此,我们不考虑在本文中使用这种方法。另外两种不同的方法——给GridView绑定的数据源添加分界线和在GridView绑定数据后操作其子控件,都值得讨论。向GridView绑定数据源添加分界线。

当GridView绑定到数据源时,GridView会从数据源中的每条记录创建一个GridViewRow。因此,我们可以在数据绑定之前添加一个“分界记录”。图3描述了这个过程。

//files.jb51.net/file_images/article/201605/201605090846033.png

图3:数据源添加分割线示意图。

之所以引用‘分界记录’这个术语,是因为没有这样特殊的记录,我们只是在数据源中添加了一些标记行。例如,将productdatatable对象绑定到GridView,并且productdatatable由ProductRow组成。我们可以将记录标记为“分界记录”,并将CategoryID设置为-1(因为-1在普通记录中不存在)。

要使用这种方法,我们需要以下步骤来实现:1。获取绑定到GirdView(一个productdatatable对象)的数据。2.根据GridView的SortExpression和SortDirection属性排列数据。3.遍历productdatatable中的ProductsRows以查找排序列的边界。4.在每组分界点的数据表中插入“分界线”ProductsRow,CategoryID列值为-1(或其他可以标记“分界线”的值)。5.插入“分界线”后,将数据动态绑定到GridView。

完成以上五个步骤后,需要在RowDataBound事件中确定哪些行是“分隔行”(CategoryID=-1的行),并格式化“分隔行”的显示样式。此外,有必要做更多的工作来保持排序事件中的排序表达式和排序方向的值。在GridView绑定数据后,它将向GridView的控件集中添加额外的TableRow对象。

与绑定数据前的GridView相比,在GridView绑定数据后添加‘分界线’更好。GridView由一个Table组成,一个Table由Row集合组成,一个Row由Cells集合组成,这就是GridView的控件层次结构。GridView的根是一个表对象。GridViewRow(从TableRow派生)是从数据源的每个记录生成的,TableCell是从数据源的每个网格生成的。我们可以使用GridView的控件层次结构在每个组之间添加分界线。因为GridView的控件层次结构是在page被呈现时创建的,所以重写Page类的呈现方法,并在必要的地方添加分界线。图4描述了这个过程。

//files.jb51.net/file_images/article/201605/201605090846034.png

图4:更改GridView控件层次结构并添加边界线示意图。

本文将使用最后一种方法来创建自定义排序用户界面。

请注意,这里在:中使用的代码是基于Teemu Keiski博客中的文章“用GridView排序分组玩一会儿”。

步骤3:向GridView的控件层次结构添加分界线。

在构建完GridView的控件层次结构之后,在进行Page Rendered之前,我们必须在页面生命周期的最后阶段,但在GridView生成HTML语言之前,添加分割线,所以我们必须重写Page类的render方法,例如在下面的代码:中。

受保护的重写void Render(HtmlTextWriter编写器){ //添加操作GridView控件层次结构基的代码。渲染(编剧);}当页面的原始渲染方法(基础。调用Render(writer)),将显示页面上的每个控件,并且生成的HTML标记基于控件层次结构。因此,我们必须在base之前更改GridView的控件层次结构。调用Render(writer)。要添加分界线,我们必须确保用户已经订购了它们。但是,最初GridView并不是按类别排序的,所以没有必要添加分割线。

注意:如果想让GridView默认按某一列排序,应该在Page_Load中调用GridView的排序方法,在if(!IsPostBack)。有关排序方法的更多知识,请参考分页和排序报告数据一章。

假设排序已经完成,下面是确定排序依据的列,并找到不同列组之间的边界。下面的代码确定是否按:排序哪一列。

受保护的覆盖void Render(HtmlTextWriter编写器){ //仅当显示数据表格(一种控件)排序时才添加排序用户界面如果(!字符串IsNullOrEmpty(ProductList .SortExpression)) { //确定数据按int sort columndex=-1排序的列的索引和header text string sort column header text=字符串。空的;for(int I=0;I产品列表.列。计数;i ) { if (ProductList .列[我]。排序表达式。与(ProductList)比较.排序表达式)==0){ sort column dex=I;sortColumnHeaderText=ProductList .列[i].标题打破;} } //TODO:扫描行中已排序列的值的差异}假如显示数据表格(一种控件)没有排序,SortExpression就没有设置值。我们要做的是对已经排序的显示数据表格(一种控件)添加分界行。完成排序后,下一步要判断是按第几列排序,遍历每一列,比较排序表达式和哪一列的标题相同,用两个变量sortColumnIndext和排序列标题文本分别保存该列的索引和标题。

知道是按第几列排序后,最后一步是添加分界行到显示数据表格(一种控件)中,遍历排序列的每一行,比较每上一行的值和它的当前行的值相不相同,不相同就要在中间插入分界行,代码如下:

受保护的覆盖void Render(HtmlTextWriter编写器){ //仅当显示数据表格(一种控件)排序时才添加排序用户界面如果(!字符串IsNullOrEmpty(ProductList .SortExpression)) { //.为简洁起见,删除了查找排序列索引的代码.//引用显示数据表格(一种控件)已呈现到表gridTable=(表)ProductList中的表。控件[0];//枚举每个TableRow,如果//排序后的值已更改字符串lastValue=字符串,则添加排序用户界面头。空的;foreach(ProductList中的GridViewRow(gvr).row){ string CurrentValue=gvr .单元格[排序列索引]。文字;if (lastValue .比较值!=0) { //排序列int rowIndex=gridTable中的值发生了变化划。getrow index(gvr);//添加新的排序标题行GridViewRow排序行=新的GridViewRow(行索引,行索引,数据控制行类型.数据行,数据控制行状态。正常);表格单元格排序单元格=新表格单元格();sortCell .ColumnSpan=ProductList .列。计数;sortCell .文本=字符串。格式(' {0}: {1} ',排序列标题文本,当前值);sortCell .CssClass=' SortHeaderRowStyle//将sortCell添加到sortRow,将排序行添加到gridTable sortRow .单元格。添加(排序单元格);gridTable .控件。//更新最后值最后值=当前值;} } }基础。渲染(编剧);}首先获得显示数据表格(一种控件)控件层次结构的根控件,一个桌子,用gridTable表示。另外用字符串变量lastValue表示上一行的值,当前值表示当前行的值。

注意:我获得通过单元格(单元格)的文本属性赋值给lastValue和当前值,这只能应用的绑定列(边界字段),对于其它种类的列如模板列(TemplateField),复选框列(复选框字段)等等是不可行的,我将会在后面说明如何解决非绑定列的取值问题。

比较lastValue和当前值,如果不同就要添加分界行到显示数据表格(一种控件)的控件层次结构中。取得当前行的索引,创建一个GridViewRow对象(它由单元格组成)插入到显示数据表格(一种控件)的控件层次结构中。另外我们要把分界行格式化成单独的一个单元格,宽度与显示数据表格(一种控件)相同,样式与应用SortHeaderRowStyle样式(css文件在下面给出),显示的文字是排序列名(如类别)和组名(如海鲜),最后把当前值赋值给最后一个值.下面给出钢性铸铁代码:SortHeaderRowStyle {底色: # c00文本-左对齐:字体粗细:粗体;颜色:白色;}完成上面的代码后,就可以对按绑定列排序后生成有分界行的排序界面(图5是按供应者排序后给出的截图).但是我现在还不能对其它种类的列(如模板列或者复选框列)生成用户定义排序界面,如图6所示(按停止排序).

//files.jb51.net/file_images/article/201605/201605090846065.png

图5:绑定列排序

//files.jb51.net/file_images/article/201605/201605090846096.png

图6:按ChectBox列排序,没有分界线。

按checkbox列排序没有分割线的原因是代码通过获取TableCell的Text属性来决定按哪一列排序,但是CheckBox列TableCell的Text是空的,所以我们需要从TableCell包含的控件中获取CheckBox控件。当遇到这种类型的列时,我们需要确定复选框是否被勾选,并替换当前值=gvr。单元格[排序列索引]。代码为3360的文本。

string currentValue=字符串。空的;if (gvr。单元格[sortcolumndex]. controls . count 0){ if(gvr。单元格[排序列索引]。控件[0]是CheckBox) { if (((CheckBox)gvr。单元格[排序列索引]。控件[0])。选中)当前值=“是”;else currentValue=“否”;} //.如果使用带有其他//Web控件的列(日历、下拉列表等),请在此处添加其他检查。).}else currentValue=gvr。单元格[排序列索引]。文字;这段代码判断排序列中的TableCell中是否有任何控件。如果有,并且第一个控件是CheckBox,则根据CheckBox的checking属性为currentValue赋值“是”或“否”,如果绑定,则为currentValue赋值TableCell的Text属性的值。同样,该方法也用于模板列。图7是按中断排序后的改进代码的屏幕截图。

//files.jb51.net/file_images/article/201605/201605090846137.png

图7:分界线根据复选框列出现。

请注意,如果数据库中的CategoryID、SupplierID或UnitPrice为NULL,则在GridView中将显示为空字符串,这意味着分割线显示为“Category:”,如下所示。您可以将绑定列的NullDisplayText属性设置为这种显示样式,或者在Render方法中使用currentValue来设置分割线的显示文本。

摘要

GridView没有自定义排序接口的内置功能,但是我们可以通过一些代码改变GridView的控件层次来创建自定义排序接口。本文解释了如何向可排序的GridView添加分界线,以便用户可以轻松区分不同组的分界线。有关自定义排序界面的更多示例,请访问Scott Guthrie博客中的Afew ASP.NET 2.0 GridView排序提示和技巧。

祝你编程愉快!

作者简介

斯科特米切尔,六本关于ASP/ASP的书的作者。NET,是4GuysFromRolla.com的创始人,自1998年以来一直使用微软的网络技术。Scott是一名独立的技术顾问、培训师和作家,最近完成了一部即将由Sams出版社出版的新作,24小时内精通ASP.NET 2.0。他的联系电子邮件是[emailprotected],也可以通过他的博客http://scottonwriting.net/.联系到他

版权声明:ASP.NET 2.0中的操作数据XXVII:创建自定义排序用户界面是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。