0

我有一个 ASP.NET 向导控件。第二步,我有两个 ListBox;页面加载时从服务器填充第一个 ListBox 项。

然后用户从 ListBox1 中选择数据并将其移动到 ListBox2。然后,用户单击向导的下一步按钮。不知何故,当用户单击下一步时,ListBox2 为空。

我使用 jQuery 将数据从 ListBox1 移动到 ListBox2。

<td class="style9">
                <asp:ListBox ID="registerCompCats" runat="server" CssClass="ListBox1"
                ClientIDMode="Static" DataTextField="value" DataValueField="key"
                Rows="5" size="5" style="width:135px; size:5px;" SelectionMode="Multiple" ></asp:ListBox>
                    &nbsp;&nbsp;&nbsp;</td>
                <td class="style1">
                    <table>
                        <tr>
                            <td style="padding-left: 20px;">
                                <img id="addCat" onclick="return addCat_onclick()" 
                        src="images/buttons/btn_addCat.jpg" title="Add Category" />
                            </td>
                        </tr>
                        <tr>
                            <td style="padding-left: 20px;">
                                <img id="removeCat" 
                        src="images/buttons/btn_removeCat.jpg" title="Remove Category" />
                            </td>
                        </tr>
                    </table>
                </td>
                <td>
                <asp:ListBox ID="registerCompAcats" runat="server" CssClass="ListBox2"
                ClientIDMode="Static" DataTextField="value" DataValueField="key"
                Rows="5" size="5" style="width:135px; size:5px; margin-top: 0px;" SelectionMode="Multiple" ></asp:ListBox>
                    &nbsp;<asp:RequiredFieldValidator ID="registerCompAcatsValidator" runat="server" 
                        ControlToValidate="registerCompAcats" Display="None" ErrorMessage="categories"></asp:RequiredFieldValidator></td>
4

1 回答 1

3

事件验证

如果您在客户端使用列表框和/或下拉列表的可用选项(即使用 jQuery 或其他方式),内置的 ASP .NET 表单验证(称为“事件验证”)将启动并抛出一个异常,因为您提交的表单与最初呈现控件时所提供的选项不同。要解决此问题,您必须在 .aspx 页面顶部执行此操作:

<%@ Page EnableEventValidation="false" %>

请记住,如果您这样做,您需要自己对下拉列表和列表框执行表单验证。

视图状态

每次将页面回传到服务器时,这些控件都有 0 个选项。是的,您在 HTML 中看到了选项,但在服务器上,它们开始时只有 0 个选项。如果您在这些控件上启用了视图状态,则在页面生命周期中,ASP .NET 框架将自动添加上一页面呈现中存在的选项。这意味着,由于registerCompAcats控件在第一个页面呈现中没有选择,所以当页面回传到服务器时,它仍然没有任何选择。

这些asp:ListBox控件呈现为<select>HTML 中的元素。这些工作的方式是他们将在这些列表框中选择的值发布到服务器。这意味着无论选择是什么,您都只会知道用户在表单帖子的这些列表框中选择的项目。

可能的解决方案

有几种方法可以解决这个问题。我将概述一对。

方法1:回发以将项目添加到其他列表框

这可能是最简单但效率最低的。每次用户单击“添加类别”按钮时,您可能会导致页面回发,而不是使用 jQuery 将项目从一个列表框移动到另一个列表框。这允许服务器端代码控制每个框中的选择,并且视图状态对您有利。您还可以在页面上重新启用事件验证,这通常是个好主意。

<asp:ListBox id="lb1" runat="server" />
<asp:Button id="btnAdd" runat="server" />
<asp:ListBox id="lb2" runat="server" />

对于 btnAdd.Click 事件:

Sub btnAdd_Click(sender As Object, args As EventArgs) Handles btnAdd.Click

  lb2.Items.AddRange(lb1.Items.Where(Function(i) i.Selected).ToArray())

End Sub

方法二:使用jQuery添加项目;在提交之前操纵帖子

就像我上面解释的那样,您需要为此关闭事件验证。使用 jQuery 将项目从一个列表移动到另一个列表 - 这很好。但是,在您实际在页面上进行回发之前,您将使用 jQuery 收集第二个列表框中的所有值,并将这些值放在隐藏字段中,即runat="server".

<asp:ListBox id="lb1" runat="server" />
<input type="button" value="Add" onclick="addCategory();" />
<asp:ListBox id="lb2" runat="server" />
<input type="hidden" id="hdnSelectedCategories" runat="server" />
<asp:Button id="btnSubmit" runat="server" onclientclick="preSubmit();" />

jQuery部分:

<script type="text/javascript">

  var lb1, lb2, hdnSelectedCategories;

  $(function() {
    lb1 = $('#<%=lb1.ClientID %>');
    lb2 = $('#<%=lb2.ClientID %>');
    hdnSelectedCategories = $('#<%=hdnSelectedCategories.ClientID %>');
  });

  function addCategory() {
    lb2.append(lb1.find('option:selected'));
  }

  function preSubmit() {
    // collect all the values from the lb2 listbox into an array
    var values = [];
    lb2.find('option').each(function(index, item) {
      values.push($(item).val());
    });
    // now put the contents of the array in the hidden input, separated by commas
    hdnSelectedCategories.val(values.join(','));
  }
</script>

现在在您的代码后面,对于 btnSubmit.Click 事件:

Sub btnSubmit_Click(sender As Object, args As EventArgs) Handles btnSubmit.Click

  Dim values As String() = hdnSelectedCategories.Value.Split(",")

  'TODO: Profit'

End Sub

在这种方法中,您可能还希望关闭列表框上的 Viewstate,因为它会增加请求的膨胀,并且会在用户单击“提交”按钮后重置您的列表框。

免责声明

我对这段代码进行了最低限度的测试——这只是我的想法。但希望对事件验证、视图状态和回发页面生命周期的解释能够帮助您了解实际发生的情况,并且您可以提出适合您情况的解决方案。

于 2012-10-11T13:16:48.760 回答