GridView日期过期校验报错BC30311:Control无法转换为Date
解决GridView中日期判断的BC30311错误
这个错误的根源很明确:你试图把一个Control类型的对象直接赋值给Date变量,但两者类型完全不兼容。问题出在playDate = r.Cells(1).FindControl("playDate")这行——因为playDate是BoundField,它不是一个可通过FindControl获取的服务器控件,单元格里只是渲染后的日期文本,并非控件实例。
修正步骤与代码
我们需要先获取单元格的文本内容,再将其转换为Date类型,之后再进行日期比较。另外要注意你的日期格式是dd/MM/yyyy,转换时要指定格式避免解析错误:
For Each r As GridViewRow In gdvCompetitions.Rows If r.RowType = DataControlRowType.DataRow Then ' 1. 获取单元格的日期文本,去除首尾空白 Dim playDateText As String = r.Cells(1).Text.Trim() Dim playDate As Date ' 2. 安全转换日期(避免空文本、格式错误导致异常) If Date.TryParseExact(playDateText, "dd/MM/yyyy", Globalization.CultureInfo.InvariantCulture, Globalization.DateTimeStyles.None, playDate) Then ' 3. 获取注册链接控件(注意单元格索引:你的注册列是第6列,索引为5) Dim hypBook As HyperLink = DirectCast(r.Cells(5).FindControl("hypBook"), HyperLink) ' 4. 仅比较日期部分,忽略时间差导致的误判 If Date.Now.Date > playDate.Date Then hypBook.Visible = False End If End If End If Next r
关键细节说明
- 为什么不能用FindControl?:
BoundField会直接把字段值渲染成纯文本,不会生成带ID的服务器控件,所以FindControl("playDate")找不到任何目标控件,返回Nothing,自然无法赋值给Date变量。 - 安全转换日期:用
Date.TryParseExact替代直接Date.Parse,可以避免因单元格文本为空、格式不符等情况抛出异常,让代码更健壮。 - 日期比较技巧:使用
.Date属性只比较日期部分,避免当前时间(比如上午10点)和比赛日期(当天0点)的时间差导致误判。
更优雅的替代方案:RowDataBound事件处理
如果你想更高效地处理,推荐在GridView的RowDataBound事件中直接从数据源获取日期值,无需解析文本:
Protected Sub gdvCompetitions_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles gdvCompetitions.RowDataBound If e.Row.RowType = DataControlRowType.DataRow Then ' 直接从绑定的数据项中获取日期,跳过文本解析步骤 Dim playDate As Date = DirectCast(DataBinder.Eval(e.Row.DataItem, "playDate"), Date) Dim hypBook As HyperLink = DirectCast(e.Row.FindControl("hypBook"), HyperLink) If Date.Now.Date > playDate.Date Then hypBook.Visible = False End If End If End Sub
这种方式不仅更高效,还彻底避免了日期解析可能带来的问题,是更推荐的实现方式。
内容的提问来源于stack exchange,提问作者mark davies
相关产品推荐
相关产品推荐

