关于 GridView,HyperLinkField,UrlEncode
我假定你是碰到了和我相同的问题,搜索标题中这几个关键字来到这篇文章的。
简单的描述一下这个有点挠头的问题,就是对于 GridView 中的 HyperLinkField 列,MS 并没有像 BoundField 那样提供 UrlEncode/HtmlEncode 之类相关的属性设置。可实际运用中,你很可能碰到需要在 URL 中传中文参数的问题。Google 出来的网页表明,西方人也会因为一些特殊字符(比如 &)碰到同样的问题。当然相比西方人,CJK 圈子里更普遍一些。
目前看到的文章给出的方案大都是将 HyperLinkField 转化为 TemplateField 之后,手动用 HttpUtility.UrlEncode 方法处理数据绑定。代码会增多,看起来也不太雅观。而且如果你反悔或者想调整字段时,从 TemplateField 也不能自动转回 HyperLinkField。
Google 出来的网页中,有一些网友跟我同样的想法,希望 MS 能够在 .net 2.0 下个版本(也就是 .net 3.x)中提供一个这样的常用属性,并且已经有人向 MS 提交了“bug 报告”。MS 的答复应该令不少人失望:为了在版本升级中保持 backward-compatibility,MS 不会添加这样的属性。
(顺便多句嘴,backward-compatibility 这个词,国内有人译作“向前兼容”,也有人译作“向后兼容”,呵呵,很有意思的一件事,都有点道理,“以前”是指 before now,“向前看”却是 look forward。)
在 MS 说明 backward-compatiblity 的 blog 上,很多网友表达了跟我类似的疑惑:既然 .net 各个版本之间可以互不影响的独立工作,那就没有必要去“过分”地追求 100% backward-compatibility。当然,为了大家不至于重新学习,做到尽可能兼容就可以了,但以前写的程序,就还让它们在原来的 .net framework 上运行就好了。
而至于版本迁移,决策者准备迁移之前,就应该考虑好迁移的优点和缺点,就像 PetShop 从 .net 1.x 迁移到 2.0 改动不可谓之不大,但为了利用 2.0 最新的技术,它那样去做了,到底值不值得,那就是决策者的算盘了。
好了,上面对于多数人来说都是废话,来主要的吧:
下面这段代码给你一个新选择,避免将 HyperLinkField 转换为 TemplateField ,但同时实现了 UrlEncode。
public static void HyperLinkFieldUrlEncodeHack(GridView gridView) { if (gridView == null) { return; } gridView.RowDataBound += delegate(object sender, GridViewRowEventArgs e) { if (e.Row.RowType != DataControlRowType.DataRow) { return; } for (int i = 0; i < gridView.Columns.Count; i++) { DataControlField field = gridView.Columns[i]; if (field is HyperLinkField) { log.Debug(e.Row.RowType.ToString()); TableCell td = e.Row.Cells[i]; if (td.Controls.Count > 0 && td.Controls[0] is HyperLink) { HyperLink hyperLink = (HyperLink)td.Controls[0]; HyperLinkField hyperLinkField = (HyperLinkField)field; if (!String.IsNullOrEmpty( hyperLinkField.DataNavigateUrlFormatString)) { string[] dataUrlFields = new string [hyperLinkField.DataNavigateUrlFields.Length]; for (int j = 0; j < dataUrlFields.Length; j++) { object obj = DataBinder.Eval(e.Row.DataItem, hyperLinkField.DataNavigateUrlFields[j]); dataUrlFields[j] = HttpUtility.UrlEncode( (obj == null ? "" : obj.ToString())); } hyperLink.NavigateUrl = String.Format( hyperLinkField.DataNavigateUrlFormatString, dataUrlFields); } } } } }; }
我想你该知道怎么来使用这段代码吧?