列表框未能选择项目

6
我有一个ListBox,我正在代码后端添加ListItems。问题是ListBox无法识别已选项目。 ListBox是根据用户从DropDownList中选择的内容动态填充的,因此DropDownList设置了AutoPostBack为true。我认为这可能是导致问题的原因。
我的SelectedIndexChanged方法用于在选择DropDownList中的项目时调用PopulateListBox方法。以下是这些方法的示例:
protected void SelectedIndexChanged(object sender, EventArgs e)
{
    string typeStr = type.SelectedItem.Text;
    MyType = Api.GetType(typeStr);
    PopulateListBox();
}

private void PopulateListBox()
{
    listbox.Items.Clear();
    foreach (PropertyInfo info in MyType.GetProperties())
        listbox.Items.Add(new ListItem(info.Name));
}

就技术而言,以下是DropDownList和ListBox:

<asp:DropDownList runat="server" ID="type" width="281px" OnSelectedIndexChanged="SelectedIndexChanged" AutoPostBack="true" />

<asp:ListBox runat="server" ID="listbox" width="281px" height="200px" selectionmode="Multiple" />

我试图在单击提交按钮后将一个字符串列表(选定项为字符串)作为会话变量添加。在将列表添加到会话后,按钮将重定向到新页面。通过调试器,当我将其添加到会话中时,字符串列表为空。 listbox.GetSelectedIndices() 什么也没有返回。
更新: 如果我不更改 DropDownList,则可以访问所选项目。ListBox最初在页面加载时填充,如果我进行选择,则它们将被识别。如果我从DropDownList中选择某些内容并重新填充ListBox,则不会识别选择内容。
我的 Page_Load 方法只有两个操作。它初始化我的 Api 变量并调用 PopulateDropDown,它的代码如下:
private void PopulateDropDown()
{
    foreach (Type t in Api.GetAllTypes())
        type.Items.Add(new ListItem(t.Name));
    string typeStr = type.Items[0].Text;
    Type = Api.GetType(typeStr);
    PopulateListBox();
}

你什么时候访问listbox?PageLoad?请检查您访问它的位置是否符合ASP.NET页面生命周期(在处理请求控件的早期阶段,控件的属性尚未设置)。还要检查是否在页面生命周期的早期清除了listbox。 - dzendras
抱歉,我需要问一下:在访问SelectedIndices之前,您是否检查了PopulateListBox方法是否已执行?(在该方法中设置断点会很有帮助) - dzendras
1
如果在页面加载时调用PopulateListBox,你是否将其限制为!IsPostBack?否则,你将清除你的列表框并重新填充它。 - Devin Burke
@Justin:请注意它在页面加载时被调用,并且当用户选择DropDownList中的某个选项时也会被调用。 - Tyler Treat
1
好的,但你真的没有回答我的问题,即你是否在 if (!IsPostBack) { } 中包含了对该方法的引用,请发布你整个 Page_Load 方法。 - Devin Burke
显示剩余3条评论
2个回答

13
问题在于你在每个 Page_Load() 中都调用了 PopulateDropDown(),该方法又调用了 PopulateListBox(),导致清空并重新填充了列表框。通过清空列表框,你也清除了所选项。
你需要用以下代码替换在 Page_Load() 中调用 PopulateDropDown() 的部分。我认为你没有意识到的问题是,在每次 postback 时页面都会加载,并且在页面生命周期中,加载事件会先于其他事件发生。因此,选择下拉列表项时,会先执行 Page_Load() 事件(间接执行 LoadListBox 方法并清除选择)。以下代码仅在页面首次加载时填充下拉列表,请在其他使用加载下拉列表方法的地方保持不变:
protected void Page_Load(object sender, EventArgs e)
{
    // Do your API code here unless you want it to occur only the first
    // time the page loads, in which case put it in the IF statement below.
    if (!IsPostBack)
    {
        PopulateDropDown();
    }
}

IsPostBack返回一个布尔值,指示服务器端代码是否正在第一次加载页面(“false”)或作为回发(“true”)而运行。

正如我在其他地方所说的,要记住,具有多个可选值潜力的列表框必须与具有单个选择潜力的列表框不同处理。不要引用listbox.SelectedItem,而应该使用:

foreach (ListItem item in lbFullNames)
{
    if (item.Selected)
    {
        // TODO: Whatever you are doing with a selected item.
    }
}

啊,谢谢Justin。DropDownList只有在AutoPostBack设置为true时才会调用postback,对吗?我明天会尝试你的解决方案并汇报结果。 - Tyler Treat
是的,但如果将AutoPostBack设置为false,则当您更改索引时C#代码不会执行,这意味着列表框不会重新填充。 - Devin Burke

1

我也发现,如果你在服务器端禁用了 ListBox,然后使用类似以下代码的客户端代码去启用 list box,那么你将无法在服务器端获取选定的项目。

$('.css-class-assigned-to-listbox').attr('disabled', '');

解决方法很简单,只需确保服务器端启用它(默认情况下),然后使用客户端代码禁用它(参见下文)或启用它(参见上文)。
$('.css-class-assigned-to-listbox').attr('disabled', 'disabled');

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