在单个页面中处理来自动态创建的控件的多个 "chained" 回发
Dealing with multiple "chained" postbacks from dynamically-created controls in a single page
我正在尝试为一个项目构建一个非常具体的搜索页面,但在处理单个页面上由动态生成的控件调用的多个回发时遇到了很多麻烦。
页面必须像这样工作:
有一个复选框 "Detailed search",它会导致 checking/unchecking.
上的回发
当详细搜索未激活时,将显示一个包含内容和按钮的简单网格。没什么特别的。
当详细搜索处于活动状态时,N 复选框必须从一些动态数据中生成,这些动态数据代表您希望进行搜索的部分。在复选框下方,将显示启用 AJAX 的选项卡控件,最初没有选项卡页。
- 选中其中一个部分复选框时,将发生回发。回发后,将在用户选择的部分中搜索数据,然后将包含结果的 网格视图 和部分名称的新选项卡页面添加到选项卡控件.如果未选中复选框,标签页将在回发后再次从控件中消失。
现在的问题是,几乎所有东西都必须动态生成,而且几乎所有东西都与其他东西相连。
第一期:处理"Detailed search"复选框。听起来很容易,不是吗?我最初的想法是在 check/uncheck 事件处理程序期间将 Page.Viewstate["DetailedSearchEnabled"]
设置为 true
或 false
,然后创建控件在 [=15] 期间动态检查 DetailedSearchEnabled
的值=].
不。 回发事件处理发生在 Page_Load
和 Page_LoadComplete
之间。需要 额外刷新 才能按预期工作。
<< 然后我将在 Page_LoadComplete
上生成控件! >>
不。那些控件也需要事件处理,如果它们是在 Page_Load
之后生成的,它们将无法正确连接。
一个可能的解决方案是在 Page_Load
上提前生成所有内容,并且在 Page_LoadComplete
上只有 hiding/showing 控件。但这效率很低,而且这个搜索页面的一个重点是只生成最少数量的控件。
这项任务的难度似乎来自于事件连接和页面生命周期的工作方式。
肯定有更好的方法来解决这个问题。
我觉得您应该使用 CheckBoxList 控件来处理动态复选框。您可以在 post 返回期间向 CheckBoxList 添加删除项目,而不必担心动态 adding/removing 实际 controls/events 到表单。
这是 msdn 的 link:
https://msdn.microsoft.com/en-us/library/14atsyf5(v=vs.85).aspx
下面是一些示例代码:
Protected void Button1_Click (object sender, System.EventArgs e)
{
CheckBoxList.Items.Add(new ListItem("TextValue1", "Value1"));
CheckBoxList.Items.Add(new ListItem("TextValue2", "Value2"));
}
如果一切都失败了,您仍然可以退回到快速而肮脏的老式 ASP 方式。
- 使用
Response.Write
或 <%...%>
将动态控件生成为普通的 HTML(简单的表单字段,例如 <input type="checkbox" name="foo" value="1" />
)。
- 确保您有一个表单字段用于回发后可能需要的每条 信息。如有必要,在后续回发中使用隐藏表单字段 're-post' 值。
- 回发后,使用
Request
对象检索控件的值。
- 根据需要使用这些值来调整控件的生成。
您应该能够在 Page_Load
中完成所有这些操作。优点是完全自由。缺点是完全可以自由地把你的 aspx 搞得一团糟。因此,您可能希望将所有这些脏代码从您的 aspx 中迁移出来,并迁移到一个自定义的控件中,然后您可以将其添加到您的 aspx 中。
生成您自己的 HTML 时,注意不要引入 XSS 漏洞。必要时使用 HtmlEncode。
与其进行如此多的回发,不如使用 jquery 和 ajax 调用来根据需要加载控件,然后将事件附加到它,或者您甚至可以为此使用 UpdatePnael .帮助链接:
https://www.simple-talk.com/dotnet/asp.net/ajax-basics-with-jquery-in-asp.net/
http://encosia.com/using-jquery-to-directly-call-aspnet-ajax-page-methods/
正如您自己建议的那样,有更好的方法来解决它。
如果我遇到同样的情况,我会创建用于与页面交互的 Web 方法,并使用客户端来执行 UI。我目前主要使用 angular JS,尽管它确实有一个学习曲线。您可以使用 ng-hide/ng-show 绑定到复选框事件以显示详细搜索。当需要显示n个复选框时,你可以用ng-repeat填充它们,对于你需要显示的每个项目,在check/uncheck之后你可以通过web动态填充新控件等如果需要额外的数据,方法调用。
根据我的经验,纯 ASP 回传相当笨重,并不真正适合构建可维护的动态 UI。
First issue: dealing with the "Detailed search" check box.
正确的做法(如果要使用页面post-backs)如下:
- 在 CheckChanged 事件处理程序中,将 Checked 属性 的值保存到
ViewState["DetailedSearchEnabled"]
。如果值为真,则将动态复选框添加到页面。如果值为 false,则查找并删除它们。
- 覆盖 LoadViewState。调用
base.LoadViewState
后,如果 ViewState["DetailedSearchEnabled"]
为真,则重新创建动态复选框并连接它们的事件。请注意,Page_Load 和 Page_LoadComplete 都不适合执行此操作。
是的,您应该在页面生命周期的两个时间点创建动态复选框。我推荐一个辅助方法。
一般来说,您的事件处理程序应该只添加或删除受这些特定事件影响的动态控件(如果有的话),但 LoadViewState 应该重新创建 所有 存在的动态控件来自上一个页面请求。您必须在视图状态中存储足够的信息,LoadViewState 才能执行此操作。
我对 this other question 的回答演示了如何添加和删除动态控件。您可能想将其用作参考。
我正在尝试为一个项目构建一个非常具体的搜索页面,但在处理单个页面上由动态生成的控件调用的多个回发时遇到了很多麻烦。
页面必须像这样工作:
有一个复选框 "Detailed search",它会导致 checking/unchecking.
上的回发当详细搜索未激活时,将显示一个包含内容和按钮的简单网格。没什么特别的。
当详细搜索处于活动状态时,N 复选框必须从一些动态数据中生成,这些动态数据代表您希望进行搜索的部分。在复选框下方,将显示启用 AJAX 的选项卡控件,最初没有选项卡页。
- 选中其中一个部分复选框时,将发生回发。回发后,将在用户选择的部分中搜索数据,然后将包含结果的 网格视图 和部分名称的新选项卡页面添加到选项卡控件.如果未选中复选框,标签页将在回发后再次从控件中消失。
现在的问题是,几乎所有东西都必须动态生成,而且几乎所有东西都与其他东西相连。
第一期:处理"Detailed search"复选框。听起来很容易,不是吗?我最初的想法是在 check/uncheck 事件处理程序期间将 Page.Viewstate["DetailedSearchEnabled"]
设置为 true
或 false
,然后创建控件在 [=15] 期间动态检查 DetailedSearchEnabled
的值=].
不。 回发事件处理发生在 Page_Load
和 Page_LoadComplete
之间。需要 额外刷新 才能按预期工作。
<< 然后我将在 Page_LoadComplete
上生成控件! >>
不。那些控件也需要事件处理,如果它们是在 Page_Load
之后生成的,它们将无法正确连接。
一个可能的解决方案是在 Page_Load
上提前生成所有内容,并且在 Page_LoadComplete
上只有 hiding/showing 控件。但这效率很低,而且这个搜索页面的一个重点是只生成最少数量的控件。
这项任务的难度似乎来自于事件连接和页面生命周期的工作方式。
肯定有更好的方法来解决这个问题。
我觉得您应该使用 CheckBoxList 控件来处理动态复选框。您可以在 post 返回期间向 CheckBoxList 添加删除项目,而不必担心动态 adding/removing 实际 controls/events 到表单。
这是 msdn 的 link: https://msdn.microsoft.com/en-us/library/14atsyf5(v=vs.85).aspx
下面是一些示例代码:
Protected void Button1_Click (object sender, System.EventArgs e)
{
CheckBoxList.Items.Add(new ListItem("TextValue1", "Value1"));
CheckBoxList.Items.Add(new ListItem("TextValue2", "Value2"));
}
如果一切都失败了,您仍然可以退回到快速而肮脏的老式 ASP 方式。
- 使用
Response.Write
或<%...%>
将动态控件生成为普通的 HTML(简单的表单字段,例如<input type="checkbox" name="foo" value="1" />
)。 - 确保您有一个表单字段用于回发后可能需要的每条 信息。如有必要,在后续回发中使用隐藏表单字段 're-post' 值。
- 回发后,使用
Request
对象检索控件的值。 - 根据需要使用这些值来调整控件的生成。
您应该能够在 Page_Load
中完成所有这些操作。优点是完全自由。缺点是完全可以自由地把你的 aspx 搞得一团糟。因此,您可能希望将所有这些脏代码从您的 aspx 中迁移出来,并迁移到一个自定义的控件中,然后您可以将其添加到您的 aspx 中。
生成您自己的 HTML 时,注意不要引入 XSS 漏洞。必要时使用 HtmlEncode。
与其进行如此多的回发,不如使用 jquery 和 ajax 调用来根据需要加载控件,然后将事件附加到它,或者您甚至可以为此使用 UpdatePnael .帮助链接:
https://www.simple-talk.com/dotnet/asp.net/ajax-basics-with-jquery-in-asp.net/ http://encosia.com/using-jquery-to-directly-call-aspnet-ajax-page-methods/
正如您自己建议的那样,有更好的方法来解决它。
如果我遇到同样的情况,我会创建用于与页面交互的 Web 方法,并使用客户端来执行 UI。我目前主要使用 angular JS,尽管它确实有一个学习曲线。您可以使用 ng-hide/ng-show 绑定到复选框事件以显示详细搜索。当需要显示n个复选框时,你可以用ng-repeat填充它们,对于你需要显示的每个项目,在check/uncheck之后你可以通过web动态填充新控件等如果需要额外的数据,方法调用。
根据我的经验,纯 ASP 回传相当笨重,并不真正适合构建可维护的动态 UI。
First issue: dealing with the "Detailed search" check box.
正确的做法(如果要使用页面post-backs)如下:
- 在 CheckChanged 事件处理程序中,将 Checked 属性 的值保存到
ViewState["DetailedSearchEnabled"]
。如果值为真,则将动态复选框添加到页面。如果值为 false,则查找并删除它们。 - 覆盖 LoadViewState。调用
base.LoadViewState
后,如果ViewState["DetailedSearchEnabled"]
为真,则重新创建动态复选框并连接它们的事件。请注意,Page_Load 和 Page_LoadComplete 都不适合执行此操作。
是的,您应该在页面生命周期的两个时间点创建动态复选框。我推荐一个辅助方法。
一般来说,您的事件处理程序应该只添加或删除受这些特定事件影响的动态控件(如果有的话),但 LoadViewState 应该重新创建 所有 存在的动态控件来自上一个页面请求。您必须在视图状态中存储足够的信息,LoadViewState 才能执行此操作。
我对 this other question 的回答演示了如何添加和删除动态控件。您可能想将其用作参考。