我一直在尝试启动并运行具有两个列表框的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="»" 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="«" 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/