用户控件事件处理程序在回发时丢失

时间:2009-08-11 12:54:41

标签: c# asp.net postback user-controls webforms

我有一个名为LeftMenu的菜单用户控件,它有一个项目符号列表。它位于ascx页面上:

<asp:BulletedList ID="PublisherList" DisplayMode="LinkButton" OnClick="PublisherList_Click" cssClass="Menu" runat="server"></asp:BulletedList>

我在if(!isPostBack)

下的page_load中对列表进行了数据绑定

我在加载控件的页面上遇到问题。首次加载页面时,事件处理程序将触发。但是,当页面回发它不再触发时,在IE8中,当我调试时,我在Visual Studio中得到“Microsoft JScript运行时错误:对象预期”指向“__doPostBack('LeftMenu $ PublisherList','0') “。在FF我没有得到错误,但没有任何反应。我动态加载控件,它使用以下命令加载到aspx页面上:

<%@ Register TagPrefix="Standards" TagName="LeftMenu" Src="LeftMenu.ascx" %>

<Standards:LeftMenu ID="LeftMenu" runat="server"/>

我在哪里丢失事件处理程序的想法?

我刚刚意识到这也发生在我拥有的另一个用户控件上。一个文本框和一个按钮,我正在使用默认按钮,以确保按Enter键使用该按钮。 .Net将html中的内容转换为:

 <div id="SearchBarInclude_SearchBar" onkeypress="javascript:return WebForm_FireDefaultButton(event, 'SearchBarInclude_QuickSearchButton')">

所以当我在框中输入一个键时,我会在“预期的对象”行中收到一个javascript错误。似乎这两个问题是相关的。

再次编辑:我想我需要澄清一下。这不是我点击菜单项,它无法在回发中找到所选项目。我有这个搜索页面,左侧导航,然后页面的主要内容是导致回发的东西。这个回发一切都很好。一旦该页面被回发,现在如果我点击左侧导航中的项目符号列表,我会收到一个javascript错误,但它失败了。永远不会调用LeftMenu控件的page_init。

6 个答案:

答案 0 :(得分:0)

听起来你可能会丢失点击,因为你不是PostBack上的DataBinding列表。因此,回发后试图引用不存在的控件(特定的项目符号列表项)。

您应该尝试在PostBack上再次绑定列表,看看是否能解决您的问题。但是,真正应该发生的是LeftMenu和BulletedList应该将他们的信息存储到ViewState中,以便您可以确保在初始页面加载时向用户显示的数据与PostBack正在处理和使用的数据相同。

答案 1 :(得分:0)

如果你的UserControl及其中的所有控件都有EnableViewState = true,那么一切都应该可以正常工作。启用ViewState后,ASP将在Init触发后从ViewState重新定义控件。这意味着回发事件arg(指向控件列表中的索引)仍将在该列表位置找到控件。否则列表在回发时为空。

然而,ViewState是魔鬼的作品,其目的仅仅是为了培养你在有条不紊的环境中工作的错觉。可以将它用于少量数据,但通常不适用于模板化控件,如转发器和列表,因为您不知道将在ViewState中创建多少数据。

如果您正在处理静态或相对静态的数据,请将其存储在应用程序缓存中并每次在Page.Init中重新绑定您的列表(请注意它必须在Init中,因为post-init是从ViewState重新绑定的时候;如果你先进入那里,你的数据就会被用来代替。)

如果您正在处理易失性数据,则会出现问题,因为重新绑定的数据必须与原始页面请求完全相同,否则回发事件将针对错误的行触发。在这种情况下,您需要将初始数据存储在Session中,或者只需存储行ID列表(在隐藏变量或Session中),然后每次重新创建要与ID绑定的数据。

更好的解决方案是根本不使用回发事件。尝试将所有事件转换为在查询字符串上具有ID的GET。您仍然可以在第一次通过页面时使用绑定创建列表(正如您当前所做的那样),甚至可以使用新ID获取相同的页面。

如果您需要在同一页面上保持状态,但需要响应用户更改单选按钮选择(或其他内容),请考虑使用Ajax调用来更新屏幕。您也可以使用传递给Ajax调用的ID。

通常,您使用有状态ASP的次数越多,您的网页就越轻,响应速度也越快。如有必要,您还可以更好地转向无状态MVC。您还可以节省大量时间来调试模糊的问题,因为ViewState在您需要时无法使用。

我读过的ViewState的最佳分析在下面的链接中。如果您完全了解它的工作原理,您可以继续使用它,而不必承担相应的费用。

http://weblogs.asp.net/infinitiesloop/archive/2006/08/03/truly-understanding-viewstate.aspx

答案 2 :(得分:0)

这可能与javascript有关,并且在页面中较早加载的脚本会引发错误并导致页面无法正确加载。

您的用户控件是否在网页上加载了任何javascript?你能检查页面初始加载时的javascript错误吗?

答案 3 :(得分:0)

我将代码移动到我们现有的项目中,由于一些奇怪的原因,我停止了javascript错误,而是得到了:

“无效的回发或回调参数。使用配置中的<pages enableEventValidation="true"/>或页面中的<%@ Page EnableEventValidation="true" %>启用事件验证。

出于安全考虑,此功能会验证回发或回调事件的参数是否来自最初呈现它们的服务器控件。如果数据有效且符合预期,请使用ClientScriptManager.RegisterForEventValidation方法注册回发或回调数据以进行验证。“

我还没弄清楚我应该在哪里使用用户控件进行注册事件验证,但同时我只设置enableeventvalidation=false并且它现在似乎正常工作。

答案 4 :(得分:0)

看起来doPostBack函数缺失,因为它的参数是文字,所以它们不是原因。这是你自己的一个函数还是你的意思是调用ASP __doPostBack函数?

查看Firefox错误控制台或允许在IE中进行脚本调试,并确切地查看无法找到的对象。更好的是,下载Firebug并进行调试。

答案 5 :(得分:0)

我有类似的问题。事实证明,Akamai正在修改用户代理字符串,因为正在应用不需要的设置。

这意味着某些.NET控件无法正确呈现__doPostBack代码。此问题已发布为here