常見於權限配置、角色指派等介面:左側顯示可用項目,右側顯示已選項目,透過中間按鈕進行單項/全部 新增與移除。
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="DeptSelect.aspx.cs" Inherits="Demo.DeptSelect" %>
<!DOCTYPE html>
<html xmlns="https://www.w3.org/1999/xhtml">
<head runat="server">
<title>部門多選示範</title>
<style>
.list-container { display: flex; gap: 20px; align-items: flex-start; margin-top: 20px; }
.list-box { width: 250px; height: 300px; border: 1px solid #ccc; overflow-y: auto; }
.btn-group { display: flex; flex-direction: column; gap: 10px; margin-top: 50px; }
button { width: 60px; padding: 5px; }
</style>
</head>
<body>
<form id="form1" runat="server">
<div class="list-container">
<div>
<label>可選部門</label>
<asp:ListBox ID="lstSource" runat="server" SelectionMode="Multiple" CssClass="list-box" DataTextField="Name" DataValueField="Name"></asp:ListBox>
</div>
<div class="btn-group">
<asp:Button ID="btnAddAll" Text="全選 >>" OnClick="btnAddAll_Click" runat="server" />
<asp:Button ID="btnAdd" Text="新增 >" OnClick="btnAdd_Click" runat="server" />
<asp:Button ID="btnRemove" Text="< 移除" OnClick="btnRemove_Click" runat="server" />
<asp:Button ID="btnRemoveAll" Text="<< 全不選" OnClick="btnRemoveAll_Click" runat="server" />
</div>
<div>
<label>已選部門</label>
<asp:ListBox ID="lstTarget" runat="server" SelectionMode="Multiple" CssClass="list-box"></asp:ListBox>
</div>
</div>
<hr />
<asp:Button ID="btnConfirm" Text="確定" OnClick="btnConfirm_Click" runat="server" />
<asp:Label ID="lblResult" runat="server" ForeColor="Green" />
<asp:HiddenField ID="hfSelected" runat="server" />
</form>
</body>
</html>
public partial class DeptSelect : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// 模擬資料來源,實務可從 DB 讀取
var depts = new[] { "總經理辦公室", "財務部", "市場部", "行政部", "資訊部", "人資部", "研發部", "業務部" };
lstSource.DataSource = depts;
lstSource.DataBind();
}
}
// 單項新增
protected void btnAdd_Click(object sender, EventArgs e)
{
foreach (ListItem item in lstSource.Items.Cast().Where(i => i.Selected).ToList())
{
if (!lstTarget.Items.Cast().Any(i => i.Value == item.Value))
lstTarget.Items.Add(new ListItem(item.Text, item.Value));
}
}
// 全部新增
protected void btnAddAll_Click(object sender, EventArgs e)
{
foreach (ListItem item in lstSource.Items)
{
if (!lstTarget.Items.Cast().Any(i => i.Value == item.Value))
lstTarget.Items.Add(new ListItem(item.Text, item.Value));
}
}
// 單項移除
protected void btnRemove_Click(object sender, EventArgs e)
{
for (int i = lstTarget.Items.Count - 1; i >= 0; i--)
{
if (lstTarget.Items[i].Selected)
lstTarget.Items.RemoveAt(i);
}
}
// 全部移除
protected void btnRemoveAll_Click(object sender, EventArgs e)
{
lstTarget.Items.Clear();
}
// 確定:將結果存入 HiddenField 或 Session 供後續使用
protected void btnConfirm_Click(object sender, EventArgs e)
{
var selected = lstTarget.Items.Cast().Select(i => i.Value).ToList();
hfSelected.Value = string.Join(",", selected);
lblResult.Text = $"已選擇 {selected.Count} 項:{hfSelected.Value}";
}
}
Items.Cast() 將 ListItemCollection 轉為可查詢集合,簡化判斷邏輯。for (int i = count-1; i >= 0; i--) 避免移除項目導致索引錯位。Any(i => i.Value == item.Value) 確認不重複。dblclick 事件觸發對應按鈕 PostBack。DataSource 重繫結實現即時過濾。hfSelected.Value 存入資料庫或 Session,跨頁面保持狀態。雙向 ListBox 是經典 WebForms 操作模式,配合 LINQ 與現代 CSS 排版,即可打造清晰易用的多選介面。若專案已轉向 ASP.NET Core / Blazor,建議改用 <select multiple> 搭配 JavaScript 元件(如 Select2、Tom Select)獲得更豐富體驗。