我一直在尝试启动并运行具有两个列表框的ASP.NET WebForms页面。这是一个标准范例,其中有两个并排的列表框,左侧有可用项目,右侧有选定项目,以及将这些项目从一侧移到另一侧的按钮。

我希望所有工作都通过JQuery(或其他任何方式)在客户端完成。我希望能够在回发时检索选定的项目。

我遇到了各种各样的障碍。这里有一些:

1)发生回发时,我收到此错误:


  无效的回发或回调参数。使用配置或页面中的启用事件验证。为了安全起见,此功能验证回发或回调事件的参数源自最初呈现它们的服务器控件。如果数据有效且预期,请使用ClientScriptManager.RegisterForEventValidation方法以注册回发或回调数据以进行验证。


关闭“ EnableEventValidation”是有风险的。但是“ ClientScriptManager.RegisterForEventValidation”令人困惑。

2)假设我真的要进行回发,我的列表框不包含所选项目。

推荐的常见解决方案是在回发之前将所选值复制到隐藏字段中。认真吗必须有一个更好的方法。

3)当然,有关客户端脚本如何工作的所有细节也令人困惑,尽管不如前两个项目那么糟糕。

那么解决方案是什么?我在下面发布了答案。

最佳答案

根据http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/的观点,不仅可以提问和回答自己的问题,而且受到鼓励。这就是我正在做的。

这是我的工作解决方案,在此之后,我将详细介绍。请注意,我绝不是Web开发或Javascript方面的专家-远非如此。因此,请耐心等待所有这些,并且永远记住,如果您的代码设法执行了HCF代码,我将不承担任何责任。

<script>
    function addAllItems() {
        $("#<%= lbAvail.ClientID %> option").appendTo("#<%= lbSelected.ClientID %>");
        enableControls();
    }

    function addSelectedItems() {
        $("#<%= lbAvail.ClientID %> option:selected").appendTo("#<%= lbSelected.ClientID %>");
        enableControls();
    }

    function removeAllItems() {
        $("#<%= lbSelected.ClientID %> option").appendTo("#<%= lbAvail.ClientID %>");
        enableControls();
    }

    function removeSelectedItems() {
        $("#<%= lbSelected.ClientID %> option:selected").appendTo("#<%= lbAvail.ClientID %>");
        enableControls();
    }

    function enableButtons(listBoxControlId, buttonAllControlId, buttonSelectedContolId) {
        var count = $("#" + listBoxControlId + " option").length;
        document.getElementById(buttonAllControlId).disabled = count <= 0;

        count = $("#" + listBoxControlId + " option:selected").length;
        document.getElementById(buttonSelectedContolId).disabled = count <= 0;
    }

    function enableControls() {
        enableButtons("<%= lbAvail.ClientID %>", "<%= btnAddAll.ClientID %>", "<%= btnAddSelected.ClientID %>");
        enableButtons("<%= lbSelected.ClientID %>", "<%= btnRemoveAll.ClientID %>", "<%= btnRemoveSelected.ClientID %>");
    }

    function selectAll() {
        $("#<%= lbSelected.ClientID %> option").prop("selected", true);
    }
</script>

<div style="margin-top: 20px;">
    <table>
        <tr>
            <td>
                <asp:ListBox ID="lbAvail" runat="server" style="min-width: 150px" Height="150" SelectionMode="Multiple"
                             onchange="enableControls();" ondblclick="addSelectedItems();"/>
            </td>
            <td style="padding-left: 10px; padding-right: 10px;">
                <table>
                    <tr>
                        <td>
                            <asp:Button Width="35" ID="btnAddAll" Text="&raquo;" OnClientClick="addAllItems(); return false;" UseSubmitBehavior="False" runat="server"/>
                        </td>
                    </tr>
                    <tr>
                        <td style="padding-top: 5px">
                            <asp:Button Width="35" ID="btnAddSelected" Text=">" OnClientClick="addSelectedItems(); return false;" UseSubmitBehavior="False" runat="server"/>
                        </td>
                    </tr>
                    <tr>
                        <td style="padding-top: 5px">
                            <asp:Button Width="35" ID="btnRemoveSelected" Text="<" OnClientClick="removeSelectedItems(); return false;" UseSubmitBehavior="False" runat="server"/>
                        </td>
                    </tr>
                    <tr>
                        <td style="padding-top: 5px">
                            <asp:Button Width="35" ID="btnRemoveAll" Text="&laquo;" OnClientClick="removeAllItems(); return false;" UseSubmitBehavior="False" runat="server"/>
                        </td>
                    </tr>
                </table>
            </td>
            <td>
                <asp:ListBox ID="lbSelected" runat="server" style="min-width: 150px" Height="150" SelectionMode="Multiple"
                             onchange="enableControls();" ondblclick="removeSelectedItems();"/>
            </td>
        </tr>
    </table>

    <div style="margin-top: 10px;">
        <asp:Button ID="btnSubmit" CssClass="btn btn-primary" Text="Submit" runat="server" OnClientClick="selectAll();"/>
    </div>
</div>


...

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        lbAvail.Items.Add(new ListItem("Monday", "Mon"));
        lbAvail.Items.Add(new ListItem("Tuesday", "Tues"));
        lbAvail.Items.Add(new ListItem("Wednesday", "Wed"));
        lbAvail.Items.Add(new ListItem("Thursday", "Thur"));
        lbAvail.Items.Add(new ListItem("Friday", "Fri"));
        lbAvail.Items.Add(new ListItem("Saturday", "Sat"));

        lbSelected.Items.Add(new ListItem("Sunday", "Sun"));

        ScriptManager.RegisterStartupScript(this, GetType(), "CallEnableControls", "enableControls()", true);
    }
    else
    {
        string[] selectedValues = Request.Form.GetValues(lbSelected.UniqueID);
        // ...
    }
}

protected override void Render(HtmlTextWriter writer)
{
    // Register all Available items as valid items in the Selected listbox.
    foreach (ListItem item in lbAvail.Items)
    {
        ClientScript.RegisterForEventValidation(lbSelected.UniqueID, item.Value);
    }

    // When a user removes an item from the Selected listbox, we put it into the
    // Available listbox, so we have to register it here, or we'll get an error.
    foreach (ListItem item in lbSelected.Items)
    {
        ClientScript.RegisterForEventValidation(lbAvail.UniqueID, item.Value);
    }

    base.Render(writer);
}


这里有一些解释:

还记得我将项目从一个列表框移到另一个列表框,然后发布页面时遇到的“无效的回发或回调参数”错误吗?该错误实际上是ASP.NET确实在回发数据中包括已修改列表框内容的事实的线索。

为了访问修改后的列表框项,我们需要的是以下行:

string[] selectedValues = Request.Form.GetValues(lbSelected.UniqueID);


这使我们在“选定”列表框中具有一组值。我们不需要使用隐藏字段或文本框等。由于数据被发送回给我们,我们不妨使用它。请注意,这些是值,而不是显示字符串。

重要说明:仅发回列表框中的选定项目。因此,在标记代码中,您将看到单击“提交”按钮时,我会调用一些javascript代码,以选择“已选择”列表框中的所有项目(我不在乎“可用”列表框中的内容)。

那么,如何防止出现“无效的回发或回调参数”错误,以便我们可以实际使用此数据?我们必须告诉ASP.NET每个列表框哪些值有效。我们使用“ Render()”方法中的“ ClientScript.RegisterForEventValidation”进行此操作。

ASP.NET已经知道我们最初放在每个列表框中的值是要返回的有效值。因此,我们要做的就是注册可能返回的其他值。这就是我在上面的“ Register”方法中所做的事情。

至于Javascript代码,它应该是不言自明的。只要记住它实际上是在调用一些JQuery函数,因此显然您必须包括Jquery。

我希望这有帮助。我花了好一会儿才弄清楚,就像我说的那样,我找不到所有答案的地方。当然,一旦我发布此信息,就会有15个人指出我可以轻松找到这些信息的地方,但这就是生活。

关于c# - ASP.NET双列表框使用JQuery更新了客户端,以及如何在服务器端检索结果,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24293744/

10-11 19:58
查看更多