2

我的 ASP.NET 站点中有两个选择列表,由服务器填充了一些元素。

// .aspx
<asp:dropdownlist id="abc" runat="server"></asp:dropdownlist>
<asp:dropdownlist id="def" runat="server"></asp:dropdownlist>

// .aspx.cs
abc.Items.Add(new ListItem("element1", "value1"));
def.Items.Add(new ListItem("element1", "value1"));

由于现在解释的原因太复杂,我还需要用 JavaScript 修改选择列表的选项,添加一些值。

// In the <head> of the .aspx page
var abcList = document.getElementById("abc");
var defList = document.getElementById("def");
var newAbcElement = new Option("element2", "value2", false, false);
var newDefElement = new Option("element2", "value2", false, false);
abcList.options[abcList.length] = newAbcElement;
defList.options[defList.length] = newDefElement;

当然,一旦我将表单发送回服务器(无论是通过提交还是作为来自其他一些表单元素的 PostBack AutoPostBack="true"),这将搞乱 Even Validation。

无效的回发或回调参数。使用配置或页面中的 <%@ Page EnableEventValidation="true" %> 启用事件验证。出于安全目的,此功能验证回发或回调事件的参数是否源自最初呈现它们的服务器控件。如果数据有效且符合预期,请使用 ClientScriptManager.RegisterForEventValidation 方法注册回发或回调数据以进行验证。

现在,我没有资源和预算来彻底改造整个页面设计,所以:改变下拉列表的最快最简单的方法是什么,这并不意味着我必须重写整个东西?

以便在提交表单时我的 CodeBehind 文件可以识别通过 JavaScript 添加的值?

4

3 回答 3

1

ViewState您可以完全禁用DropDownList.

<asp:dropdownlist id="abc" runat="server" EnableViewState="false"></asp:dropdownlist>

对于您的问题更新:

这大大改变了这个问题。此处回答了新问题:无效的回发或回调参数。使用 '<pages enableEventValidation="true"/>' 启用事件验证

于 2013-02-26T09:52:08.863 回答
1

你有几个选择。

首先,您可能会重写您的代码,以便服务器端生成所有可能的项目,DropDownList然后在您的 JavaScript 中删除不需要的项目,而不是添加新的项目。

第二种选择是创建一个从System.Web.UI.WebControls.DropDownList. 该类应包含如下所示的一种方法。重要的是您的自定义类不会System.Web.UI.SupportsEventValidationAttribute添加到它 - 因此DropDownList基本方法将自动跳过事件验证。现在将用法替换<asp:dropdownlist>为您的方法。

如果您无法修改 .aspx 代码(或者您有大量的下拉列表要替换),您可以在配置中使用标签映射

namespace Project.MyWebControls
{
    public class MyDropDownList : System.Web.UI.WebControls.DropDownList
    { 
        protected override bool LoadPostData(string postDataKey, NameValueCollection postCollection)
        {
            if (base.LoadPostData(postDataKey, postCollection))
                return true;

            // this means that the value selected was not present in the .Items collection
            string[] values = postCollection.GetValues(postDataKey);
            if (values == null || values.Length == 0)
                return false;

            // add the value to the Items collection so that it can be processed later on.
            this.Items.Add(new ListItem("Custom value created by JavaScript", values[0]));
            this.SetPostDataSelection(this.Items.Count - 1);
        }
    }
}

请注意,根据您的代码,您可能希望Items在呈现之前从集合中删除这些自定义值。

.aspx 文件的示例:

<%@ Register TagPrefix="my" Namespace="Project.MyWebControls" Assembly="Project" %>
<my:MyDropDownList runat="server" ...></my:MyDropDownList>
于 2013-02-28T11:24:31.200 回答
1

好的,这是您的另一种选择。您可以使用 AsyncPostBackTrigger 将这些项目添加到您的列表中。

一些隐藏字段:

<asp:TextBox ID="newItemsForAbc" runat="server" style="display:none;"></asp:TextBox>
<asp:TextBox ID="newItemsForDef" runat="server" style="display:none;"></asp:TextBox>
<asp:Button ID="addNewItems" runat="server" OnClick="addNewItems_Click"
  style="display:none;" />

更新面板:

<asp:UpdatePanel runat="server" ID="UpdatePanel" UpdateMode="Conditional">
   <ContentTemplate>
     <asp:dropdownlist id="abc" runat="server"></asp:dropdownlist>
     <asp:dropdownlist id="def" runat="server"></asp:dropdownlist>
   </ContentTemplate>
   <Triggers>
     <asp:AsyncPostBackTrigger ControlID="addNewItems" EventName="Click" />
   </Triggers>
 </asp:UpdatePanel>

用于执行异步回发的 JS 函数:

<script type="text/javascript"> function UpdateStuff(value1, value2)
{
   var abcItems = document.getElementById("<%= newItemsForAbc.ClientID %>");
   var defItems = document.getElementById("<%= newItemsForDef.ClientID %>");
   abcItems.value=value1;
   defItems.value=value2;
   __doPostBack("<%= addNewItems.ClientID %>","");
}
</script>

处理按钮点击的服务器端函数:

protected void addNewItems_Click(object sender, EventArgs e)
{
    string[] n1 = newItemsForAbc.Text.Split(';');
    string[] n2 = newItemsForDef.Text.Split(';');

    foreach(string i in n1)
    {
         abc.Items.Add(new ListItem(i, i));
    }

    foreach(string i in n2)
    {
         def.Items.Add(new ListItem(i,i));
    } 
}

要更新您的列表:

var newAbcElements = "Element1;Element2;Element3";
var newDefElements = "Element4;Element5";
UpdateStuff(newAbcElements, newDefElements);

最后说明: 这段代码可能无法按原样为您完成工作。您可能需要更改在字符串中存储新项目的方式,因此拆分/解析也会发生变化。您甚至可能需要不同的字符串来显示列表项及其实际值。但我相信你明白了基本的想法。

于 2013-03-05T13:22:45.107 回答