在ASP.NET中使用多个用户控件实例

5
我是一个有帮助的助手,可以为您进行文本翻译。
我有一个带有文本框的用户控件。单击文本框会打开一个弹出控件扩展,其中有几个复选框。当选中一个复选框时,它会将复选框值写入文本框。
这是我的JavaScript代码:
<script type = "text/javascript">

    function CheckItem(checkBoxList) {
        var options = checkBoxList.getElementsByTagName('input');
        var arrayOfCheckBoxLabels = checkBoxList.getElementsByTagName("label");
        var s = "";

        for (i = 0; i < options.length; i++) {
            var opt = options[i];
            if (opt.checked) {
                s = s + "," + arrayOfCheckBoxLabels[i].innerText;
            }
        }
        if (s.length > 0) {
            s = s.substring(2, s.length); 
        }
        var TxtBox = document.getElementById("<%=txtCombo.ClientID%>");
    TxtBox.value = s;
    document.getElementById('<%=hidVal.ClientID %>').value = s;
    }

</script>

在上面的JS代码中,var TxtBox = document.getElementById("<%=txtCombo.ClientID%>"); 获取文本框并向其写入内容。
当我在aspx页面中使用UserControl时,如果只有一个UserControl实例,则可以正常工作。但是,当我添加第二个UserControl实例时,文本仅写入到第二个文本框实例中。如果我选中/取消选中第一个实例中的复选框,仍会将文本添加到最后选中的复选框中。
有人能帮助我解决这个问题吗?如何获取每个复选框实例,以便我可以修改我的JavaScript? 编辑 添加完整代码
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MultiSelectDropDown.ascx.cs" Inherits="MenuTest.MultiSelectDropDown" %>
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" %>

<script type = "text/javascript">

    function CheckItem(checkBoxList) {
        var options = checkBoxList.getElementsByTagName('input');
        var arrayOfCheckBoxLabels = checkBoxList.getElementsByTagName("label");
        var s = "";

        for (i = 0; i < options.length; i++) {
            var opt = options[i];
            if (opt.checked) {
                s = s + "," + arrayOfCheckBoxLabels[i].innerText;
            }
        }
        if (s.length > 0) {
            s = s.substring(2, s.length); //sacar la primer 'coma'
        }
        var TxtBox = document.getElementById("<%=txtCombo.ClientID%>");
    TxtBox.value = s;
    document.getElementById('<%=hidVal.ClientID %>').value = s;
    }

</script>


<asp:TextBox ID="txtCombo" runat="server" ReadOnly="true" Width="150" Font-Size="X-Small"></asp:TextBox>
<cc1:PopupControlExtender ID="PopupControlExtender111" runat="server" 
    TargetControlID="txtCombo" PopupControlID="Panel111" Position="Bottom"
     >
</cc1:PopupControlExtender>

<input type="hidden" name="hidVal" id="hidVal" runat="server" />

<asp:Panel ID="Panel111" runat="server" ScrollBars="Vertical" Width="150" Height="110" BackColor="AliceBlue" BorderColor="Gray" BorderWidth="1">

    <asp:CheckBoxList ID="chkList" 
        runat="server" 
        Height="80" onclick="CheckItem(this)">      
        <asp:ListItem Text="Contains" Value="Contains"/>
        <asp:ListItem Text="Related" Value="Related"/>
        <asp:ListItem Text="Exact" Value="Exact"/>
    </asp:CheckBoxList>
</asp:Panel>

1
你确认他们得到了不同的ID吗? - Hanlet Escaño
1
我已经使用了开发者工具,并且发现它们有不同的ID。 - AMS
1
好的,那么也许你需要再次执行getElementsByTagName。 - Hanlet Escaño
1
谢谢@HanletEscaño,如果我使用按标记获取元素,那么它是否确保将其写入相应的用户控件文本框? - AMS
1
不完全正确。让我们来解决这个问题:http://chat.stackoverflow.com/rooms/37269/lets-solve-this - Hanlet Escaño
@HanletEscaño 我已经添加了完整的代码以供参考。 - AMS
4个回答

2

另一种方法是使javascript函数名称对于每个用户控件实例都是唯一的。您可以通过将用户控件的客户端ID附加到函数名称中来实现此目的。

function CheckItem<%=ClientID %>(checkBoxList) {

在调用该函数时,确保同时包含客户端ID。

Height="80" onclick="CheckItem<%=ClientID %>(this)">

1
onclick="CheckItem<%=ClientID %>(this)" 不是有效的语法。我收到以下错误:这不是脚本。将作为纯文本输出。 - Steve Staple
1
@SteveStaple 当您尝试在服务器端标记中(任何带有runat="server"的内容)使用<%=时,就会出现这种情况。如果您正在数据绑定控件,则可以将其更改为<%#。或者,如果您只需要运行客户端函数而不执行服务器端代码,则它不需要是服务器标记,例如,您可以只使用<a>标记。 - rdans
1
我喜欢它,这让我疯狂了。 - Jake Gaston

2
每次你有一个UserControl实例,你也会重新添加javascript函数。你应该只添加一次javascript函数,所以从UserControl中删除它,在你的主.aspx页面中添加它,并将其更改为以下内容:
function CheckItem(chk, txt, hid) {
    var tbl = chk.parentNode.parentNode.parentNode; //table with checkboxes

    var options = tbl.getElementsByTagName('input'); //checkboxes
    var arrItems = new Array(); //array for selected items

    for (i = 0; i < options.length; i++) {
        var opt = options[i];
        if (opt.checked) {
            arrItems.push(opt.value); //if checked, push it in array
        }
    }

    txt.value = arrItems.join(", "); //use join to comma separate them
    hid.value = arrItems.join(); //comma separated without extra space
}

现在让我们从每个复选框中调用该函数,而不是从CheckBoxList中调用。为此,我们在每次用户单击复选框项目时向其添加一个属性,而不是整个控件,并将其放置在代码后台:
protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        foreach (ListItem li in this.chkList.Items)
        {
            li.Attributes.Add("onclick", "CheckItem(this, document.getElementById('" + txtCombo.ClientID + "'), document.getElementById('" + hidVal.ClientID + "'))");
        }
    }
}

最后,从你的CheckBoxList中删除任何JavaScript事件,因为我们在代码后台已经完成了此操作:

<asp:CheckBoxList ID="chkList" runat="server" Height="80">
    <asp:ListItem Text="Contains" Value="Contains" />
    <asp:ListItem Text="Related" Value="Related" />
    <asp:ListItem Text="Exact" Value="Exact" />
</asp:CheckBoxList>

1
包括您的ASP和完整的JavaScript代码,对我来说会更有帮助,以便我能更清楚地了解您的挑战...或者至少了解CheckItem()调用的来源。
话虽如此,我在这个提案中做出了一些假设:
您能否修改CheckItem()的调用程序,使其包括txtCombo.ClientID和hidVal.ClientID?类似于这样:
<script type = "text/javascript">

    function CheckItem(checkBoxList, txtClientId, hidClientId) {
        var options = checkBoxList.getElementsByTagName('input');
        var arrayOfCheckBoxLabels = checkBoxList.getElementsByTagName("label");
        var s = "";

        for (i = 0; i < options.length; i++) {
            var opt = options[i];
            if (opt.checked) {
                s = s + "," + arrayOfCheckBoxLabels[i].innerText;
            }
        }
        if (s.length > 0) {
            s = s.substring(2, s.length); //sacar la primer 'coma'
        }
        var TxtBox = document.getElementById(txtClientId);
    TxtBox.value = s;
    document.getElementById(hidClientId).value = s;
    }

</script>

而你的调用将会是这样的:

CheckItem(checkBoxList, '<%=txtCombo.ClientID%>', '<%=hidVal.ClientID %>');

你可以在上面的链接中查看完整的代码:http://forums.asp.net/p/1935248/5507228.aspx?Multiple+instance+of+UserControl+in+a+grid+view - AMS
好的,谢谢您发布整个控件。要么使用我上面的解决方案,要么更改您的代码后端,使您的代码为每个用户控件创建一个唯一的JavaScript函数名称。 - Stan Smith
我已经使用了你的解决方案,但似乎仍然无法正常工作。在执行 JavaScript 函数时,CheckItem(checkBoxList, '<%=txtCombo.ClientID%>', '<%=hidVal.ClientID %>') 无法将 txtcombo 的 ID 发送到该函数中,因为它的 ID 在 JavaScript 执行时为 null。 - AMS
有没有机会让我访问你的网页?只是为了确认一下... 你把函数签名改成了这样:function CheckItem(checkBoxList, txtClientId, hidClientId) {,并且你把 onClick 改成了 onclick="CheckItem(this, '<%=txtCombo.ClientID%>', '<%=hidVal.ClientID %>')。 - Stan Smith

1
尝试添加一个类似于jQuery的选择器:$( "input[id*='man']" ),可以找到 'bigman' 和 'littleman'。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接