破宝

我是一块破破烂烂的宝贝石头。
随笔 - 85, 评论 - 1279, 引用 - 54

导航

工具

关于

自选精华版 RECOMMENDATIONS
留言板 GUESTBOOK

本人 blog 文章、图片及其他资源等,除另有声明外,均遵循以下原则向全球(当然包括朝鲜、古巴、利比亚等国)共享:

1。欢迎转载、复制、传播、引用,但转载、复制(包括但不仅限于作为参考资料复制到本地)、传播、引用同时必须在显著位置注明作者(破宝/percyboy)和文章原始 URL 地址等信息。但商业转载、复制、传播(尤指用于图书、光盘等媒体的部分或全部),须事先征得本人的许可。

2。文章以“现状”提供,不为由于使用本站资源而造成的任何损失而负责,仅提供力所能及的咨询和参考意见。

3。关于修改:允许您将本 blog 中的资源作为参考资料复制时的一定修改,但仍须保留作者和出处信息;其他情况下的修改(包括修改后再发布),须和本人确认许可。
 

标签

每月存档

广告



访客

 

GridView 是 ASP.NET 2.0 中提供的原来 DataGrid 的后继控件。提供了比 DataGrid 更为强大的功能。

GridView 现在有两种数据绑定模型。一种是向后(backward)兼容 1.x 的 DataSource 语法。一种是新的 DataSourceID 语法。

前者通过在代码中直接将数据源赋值给 DataSource 属性,并调用 DataBind 方法实现数据的绑定。
后者可以在“Design”视图中,放置 DataSource 控件(SqlDataSource, AccessDataSource, ObjectDataSource, XmlDataSource等),然后将 DataSource 控件的 ID 在“Properties”面板中设置给 GridView 控件的 DataSourceID 属性。

关于第二种绑定语法,QuickStart 中的示例挺多。演示了自动的分页、排序、(通过脚本回调式的)无刷新分页、排序等等。应该很全面了。

我尝试用一个 GridView 控件列出 ASP.NET 2.0 成员资格(Membership)中的所有角色。简单的使用 System.Web.Security.Roles.GetAllRoles() 方法即可得到全部的角色列表。

Roles.GetAllRoles 方法返回的是一个 string 数组,直接按照第一种绑定语法,写上两行代码:this.GridView1.DataSource = Roles.GetAllRoles(); this.GridView1.DataBind(); 效果便出来了。

只有一列,列头是一个“Item”字样,很不好,我需要自定义的列头(比如我想写一个“Role”的列头会更好一些)。这个“需求”可以简单的用自定义 GridView 的 Columns 来实现:我添加了一个 TemplateColumn,指定列头为“Role”,模版中写的代码是 <%# Container.DataItem %>还是用 1.x 中的绑定语法。(其实 2.0 中新推出的绑定语法是 EvalBind 语法,不过我这个地方没办法使用。不信?你试试看,呵呵)另外,要顺便关闭 AutoGenerateColumns 属性。

OK,截至目前,上面的需求都顺利完成了,下面我尝试给它加入排序功能。

对于 GridView 的 Column 来说,如果其 SortExpression 没有设置,呈现后的列头不会出现排序用的 LinkButton。于是我就为刚才添加的那个 TemplateColumn 设置了 SortExpression = "role"。现在再到浏览器里去看,LinkButton 就出来了。

点一下试一试?那个再熟悉不过的错误页面出来了,“The GridView 'GridView1' fired event Sorting which wasn't handled.”查了查文档,原来,GridView 内置了对于第二种绑定模型的自动分页、排序功能。对于通过 DataSource 的第一种绑定模型,GridView 只提供 UI,不提供实现。看来还需要我们手工去实现。

文档还有刚才那个错误消息都告诉我们,实现排序是通过 Sorting 事件。这个事件处理程序,我是这么写的:

protected void GridView1_Sorting(object sender, GridViewSortEventArgs e) { if (e.SortExpression == "role") { string[] roles = this.GridView1.DataSource as string[]; if (roles == null) { roles = Roles.GetAllRoles(); } if (e.SortDirection == SortDirection.Ascending) { Array.Sort<string>(roles); } else { Array.Sort<string>(roles, new Comparison<string>( delegate(string a, string b) { return -a.CompareTo(b); } )); } this.GridView1.DataSource = roles; this.GridView1.DataBind(); } else { e.Cancel = true; } }

效果如何呢?点一下试验一下,第一下还好用,正序排列没问题;再点一次问题就出来了:依然是正序,并没有按照预想那样变成逆序。

我在?Visual Web Developer?2005 Express?Edition 中启动 Debug,设置了断点,发现每次进入这个事件处理程序时,e.SortDirection 都等于 Ascending。看来问题出在这里啊。

尝试了其他一些方法,都没有解决这个问题,我决定使用 Reflector 来看看究竟。有这么两段代码:

private void HandleSort(string sortExpression) { if (this.AllowSorting) { SortDirection direction1 = SortDirection.Ascending; if ((this.SortExpressionInternal == sortExpression) && (this.SortDirectionInternal == SortDirection.Ascending)) { direction1 = SortDirection.Descending; } this.HandleSort(sortExpression, direction1); } }

Sorting 事件触发前,实际上是有这样的一个判断:如果此次排序列的 SortExpression 和前次的排序列的 SortExpression (GridView 的 SortExpression 属性值和它等价,即上面的 SortExpressionInternal 字段)相同,并且前次排序方向为正序,那这次排序方向就改为 Descending。其他情况为 Ascending。这段代码和我们的预期逻辑是一致的,但为什么效果不对?接着看:

private void HandleSort(string sortExpression, SortDirection sortDirection) { bool flag1 = base.IsBoundUsingDataSourceID; GridViewSortEventArgs args1 = new GridViewSortEventArgs(sortExpression, sortDirection); this.OnSorting(args1); if (!args1.Cancel) { if (flag1) { ....... this.SortExpressionInternal = args1.SortExpression; this.SortDirectionInternal = args1.SortDirection; this._pageIndex = 0; } this.OnSorted(EventArgs.Empty); base.RequiresDataBinding = true; } }

看到了吧,if (flag1) { ... } 当 flag1 也就是 base.IsBoundUsingDataSourceID 为真时,才会执行那两行改变 SortExpressionInternalSortDirectionInternal 的代码。换句话说,如果使用的是第一种绑定模型,这两个 private 的字段是不会被修改的了;那么无论点多少次,在前面那个方法中,都不会进入 direction1 = SortDirection.Descending; 这一行代码的。

如果是这样,能不能我们手动设置这两个要紧的字段值呢?很遗憾,GridView 的 SortExpressionSortDirection 两个属性是只读的,不能直接设置;SortExpressionInternalSortDirectionInternal 两个字段是 private 的,即使从 GridView 派生子类都无法访问这两个字段。

找了一圈,似乎陷入绝境了,恐怕只能等微软来解决了。

(BTW,哪位知道 .NET Framework 2.0 的 Bug 报告网址?)

相关文章

Loading...

打印 | 张贴于 2006-06-08 12:06:00 | Tag:暂无标签

留言反馈

#回复: Bug?用 DataSource 属性绑定的 GridView 的排序问题 编辑
The GridView's built-in sorting and paging works only if the DataSourceID property of the GridView is set to the ID of the data source. If you use the DataSource property instead, you will have to implement all of the same event handlers that are required to perform sorting and paging with a DataGrid (see Recipe 2.11).
2008-01-16 14:14:00 | [匿名用户:gerald1015]
#回复: Bug?用 DataSource 属性绑定的 GridView 的排序问题 编辑
微软的初衷
GridView用 DataSourceID一切从简,
用DataSource一切自己作;
排序可以用查询自己做!
2007-11-26 11:21:00 | [匿名用户:tyseffxl]
#回复: Bug?用 DataSource 属性绑定的 GridView 的排序问题 编辑
都错了,你们不要在害人了
2006-12-08 10:04:00 | [匿名用户:HBH]
#re: Bug?用 DataSource 属性绑定的 GridView 的排序问题 编辑
to sunmast:
对这个问题,你可以做简单的实验,“万能的Reflection”只能帮你做一点点事情,引起更大的麻烦而已。
2006-09-23 14:07:00 | [匿名用户:破宝]
#re: Bug?用 DataSource 属性绑定的 GridView 的排序问题 编辑
to Flytang:
你这篇文章中的方案肯定是可行的,我也想到过。
但我说它是微软设计上的 bug 也是站的住脚的,为什么微软不能更好的支持一下 基于 DataSource 属性的数据绑定呢,还让我们如此麻烦的使用 ViewState 去维持 GridView 的状态呢?像 SortOrder/SordDirection 这些都应该属于 UI 的范畴,应该在 GridView 控件内部封装完毕才对。
我猜大概是因为微软想让我们更多的使用 DataSource 控件吧。
2006-09-23 14:04:00 | [匿名用户:破宝]
#re: Bug?用 DataSource 属性绑定的 GridView 的排序问题 编辑
你们总是把简单问题复杂化,一个排序有必要这么折腾吗???
2006-09-13 18:47:00 | [匿名用户:过客]
#re: Bug?用 DataSource 属性绑定的 GridView 的排序问题 编辑
GridView对使用DataSourceID作了很多附加的处理,但在使用DataSource的时候,总有一些奇怪的问题——还有那个DetailsView控件也是

感觉这几个控件就是鸡肋
2006-06-22 23:47:00 | [匿名用户:kknd]
#re: Bug?用 DataSource 属性绑定的 GridView 的排序问题 编辑
你好,有没有兴趣出计算机方面的书
可以和我联系 martt0656@163.com
2006-06-15 22:23:00 | [匿名用户:book]
#re: Bug?用 DataSource 属性绑定的 GridView 的排序问题 编辑
嗯,同Montaque,这种问题可以用万能的Reflection搞定,哈哈
2006-06-10 09:47:00 | [匿名用户:sunmast]
#re: Bug?用 DataSource 属性绑定的 GridView 的排序问题 编辑
你打英文和中文之间也有个空格,我也从微软的帮助文档里学到了这一招,看起来比较舒服。
2006-06-10 09:08:00 | [匿名用户:Robbie Mosaic]
#re: Bug?用 DataSource 属性绑定的 GridView 的排序问题 编辑
to Montaque:
你说的方法我试了一下:虽然我可以将值写入这两个字段,但 Sort 第二次时便出现了错误,这次是 DataBind 时出错,而且错误很深入,再用反射就不现实了。可以说解决了一个,后面还有 N 多配套问题。
2006-06-08 15:36:00 | [匿名用户:破宝]
#re: Bug?用 DataSource 属性绑定的 GridView 的排序问题 编辑
sorry, 更正一个小细节:
GridView 的 SortExpressionInternal 和 SortDirectionInternal 是 private 的属性,对应的字段是 _sortExpression 和 _sortDirection,这两个也是 private 的。


to Montaque:
你说的方法我会试试的,谢谢!
2006-06-08 14:45:00 | [匿名用户:破宝]
#re: Bug?用 DataSource 属性绑定的 GridView 的排序问题 编辑
Private 字段你用反射赋值就可以呀,很多Bug都是这么Fix的
2006-06-08 14:24:00 | [匿名用户:Montaque]
#re: Bug?用 DataSource 属性绑定的 GridView 的排序问题 编辑
呵呵,真巧,昨天也发现了这个问题。不通过datasource控件绑定的话,e.SortDirection值始终都是SortDirection.Ascending。所以只能自定义来保存正反序状态了:
public SortDirection GridViewSortDirection
{
get
{
if (ViewState["sortDirection"] == null)
ViewState["sortDirection"] = SortDirection.Ascending;

return (SortDirection)ViewState["sortDirection"];
}
set { ViewState["sortDirection"] = value; }
}
2006-06-08 14:06:00 | [匿名用户:阿福]
对不起,目前本随笔不允许发表新评论.

Powered by: Joycode MVC Blogger System