每个用户控件都有两个应该生成异步回发的按钮,一个应该在所选值的更改中生成异步回发的下拉列表,以及一个应该生成同步回发的按钮.如果我没有动态生成控件,并且如果只有一个控件,结构将类似于:
<asp:UpdatePanel ID="myUpdatePanel" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="false"> <ContentTemplate> <asp:TextBox ID="textBox1" runat="server" /> <asp:TextBox ID="textBox2" runat="server" /> <asp:Button ID="asyncButton1" runat="server" Text="Button1" onclick="asyncButton1_Click" /> <asp:DropDownList ID="asyncDropDown" ruant="server" AutoPostBack="true" OnSelectedIndexChanged="asyncDropDown_SelectedIndexChanged" /> <asp:Button ID="asyncButton2" runat="server" Text="Button2" OnClick="asyncButton2_Click" /> <asp:Button ID="syncButton" runat="server" Text="SyncButton" OnClick="syncButton_Click" /> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="asyncButton1" EventName="Click" /> <asp:AsyncPostBackTrigger ControlID="asyncButton2" EventName="Click" /> <asp:AsyncPostBackTrigger ControlID="asyncDropDown" EventName="SelectedIndexChanged" /> <asp:PostBackTrigger ControlID="syncButton" /> </Triggers> </asp:UpdatePanel>
当然,ContentTemplate中的所有控件实际上都是每个用户控件的一部分.
在服务器端添加触发器似乎不起作用,因为没有ControlID似乎可以帮助UpdatePanel找到相关的控件.我可以使用控件的ID或控件的UniqueID,它不起作用,我得到一个错误的行
A control with ID 'ctl00$ContentPlaceHolder1$ctl01$asyncButton1' could not be found for the trigger in UpdatePanel 'myUpdatePanel'.
所以,我想知道是否需要在客户端注册触发器而不是使用ASP.NET Ajax.我发现this page基本上解释了如何.但是,我不知道如何考虑EventName.到目前为止我看到的例子只是添加按钮点击,但我不知道如何处理DropDownList中的SelectedIndexChanged事件.
有什么帮助吗?那里有我错过的例子吗?当然,我提供的链接中的方法似乎是“非官方的”,这没有帮助,因此我没有看到关于该主题的任何MSDN文档.
谢谢!
解决方法
为了澄清我的意思,请看下面的例子:
主页面aspx:
<asp:UpdatePanel ID="Upd1" runat="server" UpdateMode="Conditional"> <ContentTemplate> <asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder> </ContentTemplate> </asp:UpdatePanel>
代码隐藏:
Private Property UserControlCount() As Int32 Get If ViewState("UserControlCount") Is Nothing Then ViewState("UserControlCount") = 1 End If Return DirectCast(ViewState("UserControlCount"),Int32) End Get Set(ByVal value As Int32) ViewState("UserControlCount") = value End Set End Property Protected Sub Page_Load(ByVal sender As Object,ByVal e As System.EventArgs) Handles Me.Load recreateUserControls() End Sub Private Sub recreateUserControls() For i As Int32 = 1 To Me.UserControlCount Dim uc As DynamicControls = DirectCast(Me.LoadControl("DynamicControls.ascx"),DynamicControls) uc.ID = "DynamicControls_" & i Addhandlers(uc) Me.PlaceHolder1.Controls.Add(uc) Next End Sub Private Sub Addhandlers(ByVal uc As DynamicControls) AddHandler uc.asyncButton1Clicked,AddressOf ucAsyncButton1Clicked AddHandler uc.asyncButton2Clicked,AddressOf ucAsyncButton2Clicked AddHandler uc.syncButtonClicked,AddressOf ucSyncButtonClicked AddHandler uc.asyncDropDownSelectedIndexChanged,AddressOf ucAsyncDropDownSelectedIndexChanged End Sub Private Sub addUserControl() Me.UserControlCount += 1 Dim uc As DynamicControls = DirectCast(Me.LoadControl("DynamicControls.ascx"),DynamicControls) uc.ID = "DynamicControls_" & Me.UserControlCount Addhandlers(uc) Me.PlaceHolder1.Controls.Add(uc) Upd1.Update() End Sub Private Sub ucAsyncButton1Clicked(ByVal sender As Object,ByVal e As EventArgs) 'only to demonstrate how to add control dynamically and update the UpdatePanel' addUserControl() Me.Upd1.Update() End Sub Private Sub ucAsyncButton2Clicked(ByVal sender As Object,ByVal e As EventArgs) End Sub Private Sub ucSyncButtonClicked(ByVal sender As Object,ByVal e As EventArgs) End Sub Private Sub ucAsyncDropDownSelectedIndexChanged(ByVal sender As Object,ByVal e As EventArgs) End Sub
包含控件的ascx:
<%@ Control Language="vb" AutoEventWireup="false" CodeBehind="DynamicControls.ascx.vb" Inherits="AJAXEnabledWebApplication1.DynamicControls" %> <%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %> <asp:UpdatePanel ID="myUpdatePanel" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="false"> <ContentTemplate> <asp:TextBox ID="textBox1" runat="server" /> <asp:TextBox ID="textBox2" runat="server" /> <asp:Button ID="asyncButton1" runat="server" Text="Button1" /> <asp:DropDownList ID="asyncDropDown" runat="server" AutoPostBack="true" /> <asp:Button ID="asyncButton2" runat="server" Text="Button2" /> <asp:Button ID="syncButton" runat="server" Text="SyncButton" /> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="asyncButton1" EventName="Click" /> <asp:AsyncPostBackTrigger ControlID="asyncButton2" EventName="Click" /> <asp:AsyncPostBackTrigger ControlID="asyncDropDown" EventName="SelectedIndexChanged" /> <asp:PostBackTrigger ControlID="syncButton" /> </Triggers> </asp:UpdatePanel>
UserControl的代码隐藏:
Public Partial Class DynamicControls Inherits System.Web.UI.UserControl Public Event asyncButton1Clicked(ByVal sender As Object,ByVal e As System.EventArgs) Public Event asyncButton2Clicked(ByVal sender As Object,ByVal e As System.EventArgs) Public Event syncButtonClicked(ByVal sender As Object,ByVal e As System.EventArgs) Public Event asyncDropDownSelectedIndexChanged(ByVal sender As Object,ByVal e As System.EventArgs) Private Sub asyncButton1_Click(ByVal sender As Object,ByVal e As System.EventArgs) Handles asyncButton1.Click RaiseEvent asyncButton1Clicked(sender,e) End Sub Private Sub asyncButton2_Click(ByVal sender As Object,ByVal e As System.EventArgs) Handles asyncButton2.Click RaiseEvent asyncButton2Clicked(sender,e) End Sub Private Sub syncButton_Click(ByVal sender As Object,ByVal e As System.EventArgs) Handles syncButton.Click RaiseEvent syncButtonClicked(sender,e) End Sub Private Sub asyncDropDown_SelectedIndexChanged(ByVal sender As Object,ByVal e As System.EventArgs) Handles asyncDropDown.SelectedIndexChanged RaiseEvent asyncDropDownSelectedIndexChanged(sender,e) End Sub End Class
通过这种方式,您不会遇到ClientID的问题.
加成:
如果需要在事件处理程序中访问UserControls的控件,请使用以下两个选项之一:
>将发送者的NamingContainer强制转换为userControl的类型:Dim uc As DynamicControls = DirectCast(DirectCast(sender,Control).NamingContainer,DynamicControls)
>使用(uc as DynamicControls)替换(ByVal sender As Object,ByVal e As System.EventArgs)的所有出现.通过这种方式,您的UserControl的引用将作为参数添加到事件中,您可以从页面访问它的公共属性,f.e.:
dim txt1 as String = uc.Text1
如果您在UserControl中公开了属性Text1:
Public Property Text1() As String Get Return textBox1.Text End Get Set(ByVal value As String) textBox1.Text = value End Set End Property
第二种选择是最干净,最易读的方式.
更新:
根据您的评论:您应该将UpdateProgress放在更新的UpdatePanel内的UserControl中.请记住正确设置AssociatedUpdatePanelID.例如:
<asp:UpdatePanel ID="UdpForm" runat="server" UpdateMode="conditional" ChildrenAsTriggers="false" > <ContentTemplate> <asp:panel ID="FormPanel" runat="server"> <asp:UpdateProgress ID="UpdateProgress1" DynamicLayout="true" runat="server" AssociatedUpdatePanelID="UdpForm" DisplayAfter="0" > <ProgressTemplate> <div class="progress"> <asp:Image ID="ImgProgress1" runat="server" ImageUrl="~/images/ajax-loader-arrows.gif" ToolTip="loading..." /> please wait... </div> </ProgressTemplate> </asp:UpdateProgress> <asp:FormView ID="FormView1" runat="server" DefaultMode="ReadOnly" > <ItemTemplate></ItemTemplate> <EditItemTemplate></EditItemTemplate> <InsertItemTemplate></InsertItemTemplate> <EmptyDataTemplate> </EmptyDataTemplate> <PagerTemplate > </PagerTemplate> </asp:FormView> </asp:panel> </contenttemplate> </asp:UpdatePanel> <asp:UpdatePanel ID="UpdContent" runat="server" UpdateMode="conditional" ChildrenAsTriggers="false" > <ContentTemplate> <asp:Panel ID="PnlMain" runat="server"> <asp:UpdateProgress ID="UpdateProgress2" DynamicLayout="true" runat="server" AssociatedUpdatePanelID="UpdContent" DisplayAfter="0" > <ProgressTemplate> <div class="progress"> <asp:Image ID="ImgProgress1" runat="server" ImageUrl="~/images/ajax-loader-arrows.gif" ToolTip="loading..." /> please wait... </div> </ProgressTemplate> </asp:UpdateProgress> Content </asp:Panel> </ContentTemplate> <Triggers ></Triggers> </asp:UpdatePanel>