我遇到按钮和AddHandler的问题。它仅在我在Page_load中使用AddHandler Button1.click,AddressOf ...时才有效,但如果我在其中一个子例程中动态创建按钮,则事件不会触发。
例如,
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
<asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="True">
<asp:ListItem>1</asp:ListItem>
<asp:ListItem>2</asp:ListItem>
</asp:DropDownList>
<asp:ScriptManager id="ScriptManager1" runat="server"></asp:ScriptManager>
<asp:UpdatePanel id="UpdatePanel1" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="False">
<contenttemplate>
<asp:PlaceHolder id="PlaceHolder1" runat="server"></asp:PlaceHolder>
</contenttemplate>
</asp:UpdatePanel>
<asp:UpdatePanel id="UpdatePanel2" runat="server" UpdateMode="Conditional">
<contenttemplate>
<asp:Label id="Label2" runat="server" Text="Label"></asp:Label>
</contenttemplate>
</asp:UpdatePanel>
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
Label1.Text = Date.Now
ScriptManager1.RegisterAsyncPostBackControl(DropDownList1)
End Sub
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs)
Label2.Text = "Panel refreshed at " + Date.Now.ToString()
End Sub
Protected Sub DropDownList1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles DropDownList1.SelectedIndexChanged
Dim b As New Button
b.Text = "Click"
ScriptManager1.RegisterAsyncPostBackControl(b)
AddHandler b.Click, AddressOf Button1_Click
PlaceHolder1.Controls.Add(b)
UpdatePanel1.Update()
End Sub
下拉列表有效,但按钮没有。我做错了什么?
答案 0 :(得分:3)
您必须在每次回发时重新生成动态创建的控件(最后在Page_Load中,最好在Page_Init中)。您必须相应地设置控件的ID,因为ASP.Net需要它来识别哪个控件导致回发并处理相应的事件。
您可以在ViewState中保存已创建按钮的数量,并使用它在Page_Load上重新生成它们。添加新按钮时增加数量。使用此数字也可以使Button的ID唯一(将其附加到ID)以确保每次回发都相同。
有关更多信息,请查看Page-Lifecycle和ViewState with dynamically added controls。
编辑:正如Joel评论的那样,如果你只需要一个Button,你可以静态设置它的ID,但是你必须在回发f.e上重新生成它。处理其点击事件。
答案 1 :(得分:1)
只是为了帮助任何有这个问题并且不太确定如何实施的人。这是一个简单的例子。 此示例首先显示下拉列表。当用户从下拉列表中选择某些内容时,会出现另一个下拉列表。 我把它排在了我的头顶,所以它可能包含错误,但你得到了想法=)
在aspx文件中,添加占位符:
在你的代码隐藏中: ...
Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
'Store control count in viewstate
If Not IsPostBack Then ViewState("ControlCounter") = 1
'Rebuild dynamic controls on every postback so when page's life cycle hits Page_Load,
'selected values in the viewstate (asp.net default behavior) can be loaded into the dropdowns
Build_Dynamic_Controls()
End Sub
Protected Sub Build_Dynamic_Controls()
'Clear placeholder
myPlaceholder.Controls.Clear()
'This is where the control counter stored in the viewstate comes into play
For i as Integer = 0 To CInt(ViewState("ControlCounter") -1
Dim ddlDynamic as New DropDownList With {
.ID = "ddlDynamicDropdown" & i,
.AutoPostBack = True
}
'This is the event that will be executed when the user changes a value on the form
'and the postback occurs
AddHandler ddlDynamic.SelectedIndexChanged, AddressOf ddlDynamic_SelectedIndexChanged
'Add control to the placeholder
myPlaceholder.Controls.Add(ddl)
'Put some values into the dropdown
ddlDynamic.Items.Add("Value1")
ddlDynamic.Items.Add("Value2")
ddlDynamic.Items.Add("Value3")
Next i
End Sub
Protected Sub ddlDynamic_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
'When a dropdown value is changed, a postback is triggered (autopostback=true)
'The event is captured here and we add another dropdown.
'First we up the control count:
ViewState("ControlCounter") = CInt(ViewState("ControlCounter")) + 1
'Now that the "total controls counter" is upped by one,
'Let's recreate the controls in the placeholder to include the new dropdown
Build_Dynamic_Controls()
End Sub
...