我有一个公共文件,其中放置了最常用的函数和方法,然后由其他页面使用其名称和点操作符调用。在这些函数中,我实现了一个使用FindControls
的函数。它返回的不是一个控件,而是null
,我得到了以下错误:
对象引用未设置为对象且为空
mycontrol = (global::System.Web.UI.WebControls.Repeater)Page.FindControl("Repeater1");
mycontrol.DataSource = message; // getting that error at this place
我期望FindControls
方法从页面返回相应的控件。我做错了什么?
2条答案
按热度按时间eit6fx6z1#
没有什么能阻止你为你想要在你所有的webforms中共享的一堆通用代码例程创建一个通用代码模块。
要使此功能正常工作,您需要:
通用代码例程应为静态类。你必须遵循的唯一真实的的规则是,类不能使用类作用域变量,因为它们在所有用户之间共享。这是一个小问题,简单地采用一种设计模式,即您 * 从不 * 尝试在共享代码中持久化类作用域的值,您就可以了。
下一个:
一些不属于webforms代码的蓝色代码模块,因此不知道要操作哪个表单/网页,是吗?
我的意思是,如果我打开了5个浏览器选项卡,我调用一些常规代码例程,这些代码将在哪个网页上操作?(答案:没有线索)。
因此,简单的解决方案是始终传递当前页面,或当前div或任何您希望这些通用助手例程操作的内容。
因此,find control可以在这样的例程中使用,但您仍然必须将当前页传递给这样的例程,以便find control或任何仍然可以使用的内容。
让我们创建一个例程来填写GridView。
所以,我们可以在页面上使用这种格式
我们的静态类(我们的共享代码库)是这样的:
所以,我们真的不需要在这里找到控制,是吗?
然而,让我们说一些奇怪的原因,我们确实想在我们的代码中使用find控件。
所以,我们可以说一般来说:
因此,我们将从网页代码中使用以下内容:
因此,如上所示,我们可以使用find控件,但实际上,在大多数情况下,您不需要使用find控件,而只需首先传递控件类型!
而且我想在第一天(大约)之后,我变得厌倦了在一个页面上填写控件。同样的代码是在页面上填写一些表单数据。
所以,我在General中构建了一个例程,在其中我将页面上的div和一个数据行发送给它。(所以现在代码可以自动为我填充控件)。
所以,假设我有这个标记:
(我将发布这个标记-真的不重要,你可以跳过大部分标记)。
然而,我所做的是为每个控件添加一个名为“f”的虚构属性,这意味着数据行的列名。
所以,现在有了这个标记:
我可以在上面填写这个:
因此,在上面的代码中,我们使用了几个通用例程,包括floader。(您向它传递一个数据行)。
因此,上面的所有标记都被填充。
注意在这个例子中我是如何传递div的。我使用了一个div,因为我可能希望页面上有几个不同数据源的部分。
因此,这个floader的代码必须循环所有控件(在那个div中,但我可以传递整个页面)。
代码看起来像这样:
因此,上面的代码循环了控件,检查了“f”属性,并填写了表单(然后我使用jQuery.ui弹出它)。
结果如下:
所以,我在General类中有很多例程,你可以自由地从Web表单中调用/使用这些代码,包括使用find控件,传递控件,或者经常传递整个页面。
因此,在上面的例子中,当用户点击一个网格视图行时,我使用floader例程来填充该div中的“酒店控件”,然后使用jquery. ui弹出该div。但是,正如你所看到的,当你在General中构建例程时,毫无疑问,你编写的代码越来越少,有一个很好的实用程序例程“抓取包”来做基本的事情,比如在div中填写控件,而不必一遍又一遍地编写代码。
unguejic2#
我认为答案是由@Albert发布的。卡拉尔是一个更完整和深入的解释如何去做。
但既然你问我了,我会试着在这里给予我的观点(不要把这当作一个答案-它只是更好地张贴它作为一个答案比大量的评论块)
我试着将你的代码从3条评论中复制并粘贴到一个代码块中,结果如下。
我很抱歉我的C#不是很好,所以我结束了一个额外的结束花括号?无论如何,我记住了我认为不正确的那个。
通常,当我们遇到问题时,隔离它们的最佳方法是将它们分解为各个部分,我的意思是,您正在使用FindControl方法/函数,所以如果您首先将FindControl方法的代码隔离到一个单独的函数中,并在不同的网页上使用一些控件进行测试,那会更好。
从VB的背景来看,首先我只是把一个函数放在一起,在PAGE对象中搜索一个子控件。它只搜索控件,没有其他任何东西,没有错误消息,尽管我已经对它进行了注解,以显示错误的位置/内容。
然后我使用Telerik免费在线代码转换器将其转换为C#。
首先这里是VB代码,注意它只搜索页面的顶层,它会递归遍历每个子对象/控件,这些子对象/控件本身可能包含其他对象/控件。
您可能需要创建一个单独的函数或修改您的findcontrol函数来考虑子对象(特别是如果您的repeater不在直接页上,而是嵌套在另一个对象/控件中)。
然后转换成C#代码
无论VB或C#代码是否会找到你的Repeater,如果它嵌套在另一个控件中,你必须循环通过每个子控件,检查它是否有任何子控件,并循环通过,所以它可以是相当递归的,但良好的规划和坚持基础将有所帮助。这就是为什么我会选择阿尔伯特D。Kallal方法,并尝试一步一步地完成它,直到你明白发生了什么。
我只是把这个贴在这里,因为你特别问我。
更多阅读:Microsoft文档https://learn.microsoft.com/en-us/dotnet/api/system.web.ui.page.findcontrol?view=netframework-4.8.1#system-web-ui-page-findcontrol(system-string)