javascript 嵌套 Gridview 的 FooterControl 中未触发 change() 函数

javascript change() function not triggered in FooterControl of Nested Gridview

我有一个嵌套的 gridview,它有一个用于插入数据的页脚行。当父行展开时,将创建页脚控件。有 2 个选择的下拉列表,其中第二个下拉列表依赖于第一个。当第一个下拉列表中的值发生变化时,将启用第二个下拉列表并创建一个列表。问题是当我更改第一个下拉列表中的值时,不会触发 change() 事件。我的编辑功能在 endRequest 功能中运行良好。但是插入控件不起作用。

这是标记:

 <asp:UpdatePanel ID="updatePnlDeviceNestedGrid" runat="server" UpdateMode="Conditional">
    <ContentTemplate>
        <div id="div<%# Eval("RecipientID") %>" style="display:none">
            <asp:GridView ID="RecipientDeviceGridView" runat="server" AutoGenerateColumns="false" CssClass="grid" ShowFooter="true" Caption="Device Information" 
                CaptionAlign="Top" AllowPaging="true" PageSize="3" HorizontalAlign="Left"
                 onpageindexchanging="RecipientDeviceGridView_PageIndexChanging" 
                 OnPageIndexChanged="RecipientDeviceGridView_PageIndexChanged" 
                 onrowcommand="RecipientDeviceGridView_RowCommand" 
                 onrowediting="RecipientDeviceGridView_RowEditing"
                 onrowupdating="RecipientDeviceGridView_RowUpdating"
                 OnRowCancelingEdit="RecipientDeviceGridView_RowCancelingEdit"
                 OnRowDeleting="RecipientDeviceGridView_RowDeleting"
                 OnRowDataBound="RecipientDeviceGridView_RowDataBound">
                <Columns>
                    <asp:TemplateField HeaderText="DeviceID">
                        <ItemTemplate>
                            <asp:Label ID="recdevgvLblDeviceID" runat="server" Text='<%# Bind("DeviceID") %>'></asp:Label>
                        </ItemTemplate>
                    </asp:TemplateField>
                    <asp:TemplateField HeaderText="Device"  ItemStyle-Wrap="false">
                        <ItemTemplate>
                            <asp:Label ID="recdevgvDeviceID" runat="server" Visible="false" Text='<%# Bind("DeviceID") %>'></asp:Label>
                            <asp:Label ID="recdevgvLblDeviceName" runat="server" Text='<%# Bind("DeviceName") %>'></asp:Label>
                        </ItemTemplate>
                        <EditItemTemplate>
                            <asp:Label ID="recdevgvEditDeviceID" runat="server" Visible="false" Text='<%# Bind("DeviceID") %>'></asp:Label>
                            <asp:Label ID="recdevgvEditDeviceName" runat="server" Visible="false" Text='<%# Bind("DeviceName") %>'></asp:Label>
                            <asp:DropDownList ID="recdevgvDDListDeviceName" runat="server" ClientIDMode="Static" 
                                data-placeholder="Choose device…" class="chosen-single">
                            </asp:DropDownList>
                            <asp:RequiredFieldValidator ID="recdevReqValueDDLDeviceNameEdit" runat="server"  
                                    ControlToValidate="recdevgvDDListDeviceName" ValidationGroup="recdevEditDeviceValidation" 
                                    ErrorMessage="Selection required." CssClass="message-error-dropdown">
                            </asp:RequiredFieldValidator>
                        </EditItemTemplate>
                        <FooterTemplate> 
                            <asp:DropDownList ID="recdevgvDDListDeviceNameInsert" runat="server" ClientIDMode="Static"
                                data-placeholder="Choose device..." class="chosen-single">
                            </asp:DropDownList>
                            <asp:RequiredFieldValidator ID="recdevReqValueDDLDeviceNameInsert" runat="server" InitialValue="0" 
                                ControlToValidate="recdevgvDDListDeviceNameInsert" ValidationGroup="recdevInsertDeviceValidation" 
                                ErrorMessage="Selection required." CssClass="message-error-dropdown">
                            </asp:RequiredFieldValidator>
                        </FooterTemplate>
                    </asp:TemplateField>
                    <asp:TemplateField HeaderText="Service Provider">
                        <ItemTemplate>
                            <asp:Label ID="recdevgvLblServiceName" runat="server" Text='<%# Bind("ServiceName") %>'></asp:Label>
                        </ItemTemplate>
                        <EditItemTemplate>
                            <asp:Label ID="recdevgvEditServiceName" runat="server" Visible="false" Text='<%# Bind("ServiceName") %>'></asp:Label>
                            <asp:DropDownList ID="recdevgvDDListServiceName" runat="server" ClientIDMode="Static" 
                                OnSelectedIndexChanged="RecipientDeviceGridView_SelectedIndexChanged_EditServiceName" AutoPostBack="true" EnableViewState="true"
                                 data-placeholder="Choose service…" class="chosen-single">
                            </asp:DropDownList>
                            <asp:RequiredFieldValidator ID="recdevReqValueDDLServiceNameEdit" runat="server" 
                                    ControlToValidate="recdevgvDDListServiceName" ValidationGroup="recdevEditDeviceValidation" 
                                    ErrorMessage="Selection required." CssClass="message-error-dropdown">
                            </asp:RequiredFieldValidator>
                        </EditItemTemplate>
                        <FooterTemplate>
                            <asp:DropDownList ID="recdevgvDDListServiceNameInsert" runat="server" ClientIDMode="Static" Enabled="false"
                                OnSelectedIndexChanged="RecipientDeviceGridView_SelectedIndexChanged_InsertServiceName" AutoPostBack="true" EnableViewState="true" 
                                data-placeholder="Choose service…" class="chosen-single">
                            </asp:DropDownList>
                            <asp:RequiredFieldValidator ID="recdevReqValueDDLServiceNameInsert" runat="server" InitialValue="0" 
                                    ControlToValidate="recdevgvDDListServiceNameInsert" ValidationGroup="recdevInsertDeviceValidation" 
                                    ErrorMessage="Selection required." CssClass="message-error-dropdown">
                            </asp:RequiredFieldValidator>
                        </FooterTemplate>
                    </asp:TemplateField>
                    <asp:TemplateField HeaderText="Address">
                        <ItemTemplate>
                            <asp:Label ID="recdevgvLblAddress" runat="server" Text='<%# Bind("Address") %>'></asp:Label>
                        </ItemTemplate>
                        <EditItemTemplate>
                            <asp:TextBox ID="recdevgvTxtBoxAddress" runat="server" Text='<%# Bind("Address") %>' ClientIDMode="Static"></asp:TextBox>
                            <asp:Label ID="recdevgvEditAddressExt" runat="server" Visible="false" Text='<%# Bind("ServiceExtension") %>' 
                                    ClientIDMode="Static">
                            </asp:Label>
                            <asp:RequiredFieldValidator ID="recdevReqValueAddressEdit" runat="server" 
                                    ControlToValidate="recdevgvTxtBoxAddress" ValidationGroup="recdevEditDeviceValidation" 
                                    ErrorMessage="Required field." CssClass="message-error">
                            </asp:RequiredFieldValidator>
                            <asp:CustomValidator ID="recdevCustomValAddressEdit" runat="server" ControlToValidate="recdevgvTxtBoxAddress" CssClass="message-error" 
                                ErrorMessage="*" ClientValidationFunction="ValidateAddressEdit" EnableClientScript="true" 
                                ValidationGroup="recdevEditDeviceValidation">
                            </asp:CustomValidator>
                        </EditItemTemplate>
                        <FooterTemplate>
                            <asp:TextBox ID="recdevgvTxtBoxAddressInsert" runat="server" ClientIDMode="Static"></asp:TextBox>
                            <asp:Label ID="recdevgvAddressExtInsert" runat="server" Visible="false" ClientIDMode="Static"></asp:Label>
                            <asp:RequiredFieldValidator ID="recdevReqValueAddressInsert" runat="server" 
        ControlToValidate="recdevgvTxtBoxAddressInsert" ValidationGroup="recdevInsertDeviceValidation" 
        ErrorMessage="Required field." CssClass="message-error">
</asp:RequiredFieldValidator>
                            <asp:CustomValidator ID="recdevCustomValAddressInsert" runat="server" ControlToValidate="recdevgvTxtBoxAddressInsert" CssClass="message-error" 
    ErrorMessage="*" ClientValidationFunction="ValidateAddressInsert" EnableClientScript="true" 
    ValidationGroup="recdevInsertDeviceValidation">
</asp:CustomValidator>
                        </FooterTemplate>
                    </asp:TemplateField>
                    <asp:TemplateField HeaderText="Active">
                        <ItemTemplate>
                            <asp:Label ID="recdevgvLblActive" runat="server" Text='<%# (Boolean.Parse(Eval("Active").ToString())) ? "Yes" : "No" %>'></asp:Label>
                        </ItemTemplate>
                        <EditItemTemplate>
                            <asp:DropDownList ID="recdevgvDDListActive" runat="server" class="no-chosen"
                                Text='<%# (Boolean.Parse(Eval("Active").ToString())) ? "Yes" : "No" %>'>
                                <asp:ListItem>Yes</asp:ListItem>
                                <asp:ListItem>No</asp:ListItem>
                            </asp:DropDownList>
                        </EditItemTemplate>
                        <FooterTemplate>
                            <asp:DropDownList ID="recdevgvDDListActiveInsert" runat="server" class="no-chosen">
                                <asp:ListItem Selected="True">Yes</asp:ListItem>
                                <asp:ListItem>No</asp:ListItem>
                            </asp:DropDownList>
                        </FooterTemplate>
                    </asp:TemplateField>
                    <asp:TemplateField HeaderText="Cortext Enabled">
                        <ItemTemplate>
                            <asp:Label ID="recdevgvLblCortextEnabled" runat="server" Text='<%# (Boolean.Parse(Eval("CortextEnabled").ToString())) ? "Yes" : "No" %>'></asp:Label>
                        </ItemTemplate>
                    </asp:TemplateField>
                    <asp:TemplateField HeaderText="Action" ShowHeader="False" ItemStyle-Wrap="false" ItemStyle-HorizontalAlign="Center">
                        <ItemTemplate>
                            <asp:Button ID="recdevgvEditButton" runat="server" CausesValidation="True" CommandName="Edit" 
            Text="Edit" CssClass="gridActionbutton" ValidationGroup="EditDeviceValidation"></asp:Button>
&nbsp;<asp:Button ID="recdevgvDeleteButton" runat="server" CausesValidation="False" CommandName="Delete" 
            Text="Delete" CssClass="gridActionbutton"  OnClientClick="return confirm('Are you sure you want to delete this Device Information?')" >
                            </asp:Button>
                        </ItemTemplate>
                        <EditItemTemplate>
                            <asp:Button ID="recdevgvUpdateButton" runat="server" CausesValidation="True" ValidationGroup="recdevEditDeviceValidation" CommandName="Update" 
                Text="Update" CssClass="gridActionbutton"></asp:Button>
&nbsp;<asp:Button ID="recdevgvCancelButton" runat="server" CausesValidation="False" CommandName="Cancel" 
                Text="Cancel" CssClass="gridActionbutton"></asp:Button>
                        </EditItemTemplate>
                        <FooterTemplate>
                            <asp:Button ID="recdevgvAddButton" runat="server" CommandName="Add" Text="Add Device" CausesValidation="true" 
            CssClass="gridActionbutton" ValidationGroup="recdevInsertDeviceValidation"></asp:Button>
                        </FooterTemplate>
                    </asp:TemplateField>
                </Columns>
            </asp:GridView>
        </div>
    </ContentTemplate>
</asp:UpdatePanel>

这是在页脚行中创建下拉菜单的代码隐藏:

 protected void RecipientInfoGridView_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        try
        {
            if (e.Row.RowType == DataControlRowType.DataRow)
            {
                int tiRecipientID = Convert.ToInt32(RecipientInfoGridView.DataKeys[e.Row.RowIndex].Value.ToString());
                GridView tgvDeviceGrid = (GridView)e.Row.FindControl("RecipientDeviceGridView");
                populateDeviceGrid(tgvDeviceGrid, tiRecipientID);

                // Get the Footer controls that have the new entry data
                Control tFooterControls = CommonMethods.getFooterControls(tgvDeviceGrid);

                DropDownList tddlDeviceNames = tFooterControls.FindControl("recdevgvDDListDeviceNameInsert") as DropDownList;
                m_strXmlTableData = m_pagingClient.GetDeviceTypes();
                DataTable tdtDeviceTypes = CommonMethods.ParseXML(m_strXmlTableData);
                tddlDeviceNames.DataSource = tdtDeviceTypes;
                tddlDeviceNames.DataTextField = tdtDeviceTypes.Columns["DeviceName"].ToString();
                tddlDeviceNames.DataValueField = tdtDeviceTypes.Columns["DeviceTypeID"].ToString();
                tddlDeviceNames.DataBind();
                tddlDeviceNames.Items.Insert(0, new ListItem("", "0"));

                DropDownList tddlServiceNames = tFooterControls.FindControl("recdevgvDDListServiceNameInsert") as DropDownList;
                m_strXmlTableData = m_pagingClient.GetServiceTypes();
                DataTable tdtServiceTypes = CommonMethods.ParseXML(m_strXmlTableData);
                tddlServiceNames.DataSource = tdtServiceTypes;
                tddlServiceNames.DataTextField = tdtServiceTypes.Columns["ServiceName"].ToString();
                tddlServiceNames.DataValueField = tdtServiceTypes.Columns["CombineID_Group"].ToString();
                tddlServiceNames.DataBind();
                tddlServiceNames.Items.Insert(0, new ListItem("", "0"));
            }

        }
        catch (Exception ex)
        {
            //TO DO: Response.Redirect("~/Error.aspx");
        }
    }

这是javascript:

 //This change function is when the Device grid is in Insert Mode
        $("#recdevgvDDListDeviceNameInsert").change(function () {
            alert('Ready Fn - Insert: Device name DDL change fn');
            $("#recdevgvDDListServiceNameInsert").prop("disabled", false);
            $("#recdevgvDDListServiceNameInsert").val('');
            $("#recdevgvDDListServiceNameInsert").chosen({
                search_contains: true,
                no_results_text: "Sorry, no match!"
            });

            var DeviceSelValue = $(this).val();
            $("#recdevgvDDListServiceNameInsert").children("option").hide();
            $("#recdevgvDDListServiceNameInsert").trigger("chosen:updated");

            switch (DeviceSelValue) {
                case "1":
                    $("#recdevgvDDListServiceNameInsert option[value*='cell']").show();
                    $("#recdevgvDDListServiceNameInsert").trigger("chosen:updated");
                    $("#recdevgvAddressExtInsert").hide();
                    break;
                case "2":
                    $("#recdevgvDDListServiceNameInsert option[value*='email']").show();
                    $("#recdevgvDDListServiceNameInsert").trigger("chosen:updated");
                    $("#recdevgvAddressExtInsert").hide();
                    break;
                case "3":
                    $("#recdevgvDDListServiceNameInsert option[value*='page']").show();
                    $("#recdevgvDDListServiceNameInsert").trigger("chosen:updated");
                    $("#recdevgvAddressExtInsert").hide();
                    break;
                default:
                    break;
            }
        });

更新 感谢阿列克谢的建议。现在触发了我的更改功能。但是 ServiceName 下拉列表的更改没有发生。当嵌套网格处于编辑模式时,我在此页面上使用此函数调用。 当我更改设备名称下拉列表的值时,服务名称下拉列表未启用且未显示值 'Choose service'。就好像选择器 #recdevgvDDListServiceNameInsert 没有被识别。 该控件具有属性 ClientIDMode="Static"

控件位于更新面板 updatePmlDeviceNestedGrid 和 Gridview RecipientDeviceGridView 内。我尝试将更新面板控件添加为选择器中的父控件,但这没有用。 我使用 document.ready() 并且为了使编辑模式起作用,我使用了 endRequest 函数。

我尝试了 bindEvent 函数,但得到了相同的结果。

这是我的 javascript:

$(document).ready(function () {
    // alert("ready function");
    //Configure the DropDownBox using the 'chosen' jquery plugin
    $(".chosen-single").chosen({
        search_contains: true,
        width: "200px",
        no_results_text: "Sorry, no match!"
    });
});

Sys.WebForms.PageRequestManager.getInstance().add_endRequest(onEndRequest);

function onEndRequest(sender, args) {
    if (sender._postBackSettings.panelsToUpdate != null) {
        $("select:not(.chosen-select, .no-chosen)").chosen({
            search_contains: true,
            width: "200px",
            no_results_text: "Sorry, no match!"
        });
    };
//more code to activate the dropdowns in Edit Mode...
};
//This change function is when the Device grid is in Insert Mode
 $(document).on("change", "#recdevgvDDListDeviceNameInsert", function () {
     alert('Ready Fn - Insert: Device name DDL change fn');
      $("#recdevgvDDListServiceNameInsert").prop("disabled", false);
      $("#recdevgvDDListServiceNameInsert").val('');
      $("#recdevgvDDListServiceNameInsert").chosen({
          search_contains: true,
          no_results_text: "Sorry, no match!"
      });

     var DeviceSelValue = $(this).val();
     $("#recdevgvDDListServiceNameInsert").children("option").hide();
     $("#recdevgvDDListServiceNameInsert").trigger("chosen:updated");

     switch (DeviceSelValue) {
         case "1":
             $("#recdevgvDDListServiceNameInsert option[value*='cell']").show();
             $("#recdevgvDDListServiceNameInsert").trigger("chosen:updated");
             $("#recdevgvAddressExtInsert").hide();
             break;
         case "2":
             $("#recdevgvDDListServiceNameInsert option[value*='email']").show();
             $("#recdevgvDDListServiceNameInsert").trigger("chosen:updated");
             $("#recdevgvAddressExtInsert").hide();
             break;
         case "3":
             $("#recdevgvDDListServiceNameInsert option[value*='page']").show();
             $("#recdevgvDDListServiceNameInsert").trigger("chosen:updated");
             $("#recdevgvAddressExtInsert").hide();
             break;
         default:
             break;
     }
 });

更新 我在编辑模式下遇到了这个问题...... 我将其添加到更改功能中,下拉列表至少显示选项 Choose service....

function bindEvents() {
   $(document).on("change", "#recdevgvDDListDeviceNameInsert", function () {
        $("select:not(.chosen-select, .no-chosen)").chosen({
             search_contains: true,
              width: "200px",
             no_results_text: "Sorry, no match!"
          });
});

但是,下拉菜单仍然没有启用...

更新 为了启用禁用的所选下拉列表,我无法使用 ID 值,但是: $("select").prop("disabled", false); 启用后,该功能的其余部分将起作用。

我假设您的 updatePnlDeviceNestedGrid 在初始页面调用时出现在页面上,所以让我们将 ClientIDMode="Static" 添加到您的 updatePanel 以使我们的 js 更具可读性

 <asp:UpdatePanel ID="updatePnlDeviceNestedGrid" runat="server" UpdateMode="Conditional" ClientIDMode="Static">

不要在每次部分回发时重新附加事件,你应该像下面这样让你的更改事件附加函数定义,我们将它放在 jQuery 文档中准备好确保 updatePnlDeviceNestedGrid 在 DOM

$(function () {
    $('#updatePnlDeviceNestedGrid').on('change', '#recdevgvDDListDeviceNameInsert', function() {
        alert('Ready Fn - Insert: Device name DDL change fn');
        // ans so on .....
    });
})

如果不做额外的更改,您也可以直接将其附加到文档中

 $(document).on('change', '#recdevgvDDListDeviceNameInsert'

这里是 jQuery 文档参考 http://api.jquery.com/on/

"Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time. By picking an element that is guaranteed to be present at the time the delegated event handler is attached, you can use delegated events to avoid the need to frequently attach and remove event handlers. This element could be the container element of a view in a Model-View-Controller design, for example, or document if the event handler wants to monitor all bubbling events in the document. The document element is available in the head of the document before loading any other HTML, so it is safe to attach events there without waiting for the document to be ready."

更新

另一方面,您可以在每次部分回发时重新绑定它,如本答案所示 jQuery $(document).ready and UpdatePanels?

例如,您将创建绑定事件的函数

function bindEvents(){
   $("#recdevgvDDListDeviceNameInsert").change(function () {
       // your code......
   }

   //some other bindings
}

// initial page load
$(function () {
   bindEvents();
})

var prm = Sys.WebForms.PageRequestManager.getInstance();

prm.add_endRequest(function() {
   // re-bind your jQuery events here after updatepanel update
    bindEvents(); 
});