日期:2014-05-18  浏览次数:20471 次

求助:VS2003 datagrid模板列不能编辑
VS2003中,datagrid非模板列能正常编辑及更新,但改为模板列后,能进入编辑状态,点击 "更新 ",出现错误:
无法将类型为“System.Web.UI.LiteralControl”的对象强制转换为类型“System.Web.UI.WebControls.TextBox”。  
说明:   执行当前   Web   请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。  

异常详细信息:   System.InvalidCastException:   无法将类型为“System.Web.UI.LiteralControl”的对象强制转换为类型“System.Web.UI.WebControls.TextBox”。

源错误:  


行   321:                 tb   =   CType(e.Item.Cells(4).Controls(0),   TextBox)
行   322:                 type4   =   tb.Text
行   323:                 tb   =   CType(e.Item.Cells(7).Controls(0),   TextBox) '出现错误
行   324:                 jieguo7   =   tb.Text
行   325:                 tb   =   CType(e.Item.Cells(8).Controls(0),   TextBox)


 


------解决方案--------------------
使用 e.Item.FindControl(...) 定位控件。

Cells里边是完全可能改变的。例如写:

yourDataGrid.Items[4].Cells[4].Attributes[ "colspan "]= "2 ";
yourDataGrid.Items[4].Cells.RemoveAt(5);

这就合并了第5行中第5、6单元格。所以,使用“Cells[整数]”这种方法,对于个人开发软件来说就是给自己设置易出错的圈套,对于团队开发软件来说就是太想当然。
------解决方案--------------------
e.Item.Cells(8).FindControl( "你的文本框控件名 ")
------解决方案--------------------
假设模板中的TextBox的id是abc,写:

tb = CType(e.Item.FindControl( "abc "), TextBox)

------解决方案--------------------
e.Item.FindControl( "abc ")
e.Item.Cells(0).FindControl( "abc ")
e.Item.Cells(8).FindControl( "abc ")

毫无分别,全都返回同一个控件。

可以自己试一下,不论你要找的id为abc的控件在哪一列,Cells(n)这里的n可以随便胡写,只要缺失有n+1列,都能找到abc控件。

实际上,这说明写Cells(n)貌似正确(abc确实在某一个列中,因此很自然想到可以从这个列开始FindControl),实际上不一定正确(因为你实际上可以随便写这个n)。正确的是从行查找,而不是从单元格查找。实际上,当你从单元格查找的时候,asp.net会先找它所在行,然后从行开始查找,所以会有这个结果。
------解决方案--------------------
在说得技术明确一点,Control.FindControl(...) 中的这个 Control 应该是实现了 INamingContainer接口的控件。如果没有实现,asp.net就先向上查找 parent,直到找到实现这个接口的控件,才开始查找控件。

但是这个做法应该是用来兼容业余或者不成熟的写法的。上面已经说个,这容易“貌似正确”。

如果你技术比较好,那么你写这类代码的时候都要注意仅对具有 INamingContainer 的控件执行 FindControl 操作,这样的代码比较成文自明。