前端界面
<asp:ListBox ID="ListBox1" runat="server" SelectionMode="Multiple" Height="123px" Width="113px">
<asp:ListItem>tom</asp:ListItem><asp:ListItem>jion</asp:ListItem>
<asp:ListItem>j</asp:ListItem><asp:ListItem>l</asp:ListItem><asp:ListItem>k</asp:ListItem>
</asp:ListBox>
<asp:Button ID="btnAdd" Text="添加 >>" OnClick="btnAdd_Click"/>
<asp:Button ID="btnRemove" Text="<< 移除" OnClick="btnRemove_Click"/>
<asp:ListBox ID="ListBox2" runat="server" SelectionMode="Multiple" Height="123px" Width="113px"></asp:ListBox>
錯誤示範:正序遍歷刪除導致漏項
// 錯誤:i 遞增,刪除後後續項目索引前移,導致跳過檢查
for (int i = 0; i < ListBox1.Items.Count; i++)
{
if (ListBox1.Items[i].Selected)
{
ListBox2.Items.Add(ListBox1.Items[i]);
ListBox1.Items.Remove(ListBox1.Items[i]); // 索引錯位!
}
}
正確寫法一:倒序遍歷 + 臨時列表
protected void btnAdd_Click(object sender, EventArgs e)
{
var selected = new List<ListItem>();
for (int i = ListBox1.Items.Count - 1; i >= 0; i--)
{
if (ListBox1.Items[i].Selected)
{
selected.Add(ListBox1.Items[i]);
ListBox1.Items.RemoveAt(i); // RemoveAt 配合倒序安全
}
}
foreach (var item in selected) ListBox2.Items.Add(item);
}
正確寫法二:利用 SelectedIndex 循環(單選或多選連續時)
// 適用於多選但項目不連續時可能遺漏,推薦倒序法
while (ListBox1.SelectedIndex >= 0)
{
ListBox2.Items.Add(ListBox1.SelectedItem);
ListBox1.Items.Remove(ListBox1.SelectedItem);
}
移除操作(ListBox2 → ListBox1)
protected void btnRemove_Click(object sender, EventArgs e)
{
while (ListBox2.SelectedIndex >= 0)
{
ListBox1.Items.Add(ListBox2.SelectedItem);
ListBox2.Items.Remove(ListBox2.SelectedItem);
}
}
核心原理
- 集合刪除時,後續元素索引前移。正序遍歷會導致剛移動到當前索引的元素被跳過。
- 倒序遍歷(從 Count-1 到 0)刪除不影響已檢查/未檢查元素的索引。
- 或先收集選中項到獨立列表,再批量操作,完全避開索引問題。