DropDownList 綁定數據源後,常需根據業務邏輯 (如編輯時回顯、默認選項) 設置選中項。本文對比 FindByValue 與遍歷匹配兩種方法,分析性能差異、適用場景,提供擴展方法封裝建議。
// 綁定
ddl.DataSource = GetCategories();
ddl.DataTextField = "Name";
ddl.DataValueField = "Id";
ddl.DataBind();
// 設置選中項
string targetValue = GetSelectedCategoryId(); // 來自 QueryString/Session/DB
ListItem item = ddl.Items.FindByValue(targetValue);
if (item != null)
{
ddl.SelectedIndex = ddl.Items.IndexOf(item); // 或 item.Selected = true
}
else
{
// 未找到:可選插入提示項或保持默認
ddl.Items.Insert(0, new ListItem("-- 請選擇 --", ""));
}
原理:`ListItemCollection` 內部維护 `Hashtable` 索引 Value→Index,`FindByValue` 為哈希查找,極快。
string targetValue = "5";
for (int i = 0; i < ddl.Items.Count; i++)
{
if (ddl.Items[i].Value == targetValue)
{
ddl.SelectedIndex = i;
break;
}
}
// 或 do-while 微優化
int i = 0;
do
{
if (ddl.Items[i].Value == targetValue) { ddl.SelectedIndex = i; break; }
} while (++i < ddl.Items.Count);
適用場景:
| 方法 | 平均耗時 | 備註 |
|---|---|---|
| FindByValue | 0.02 ms | 哈希索引 O(1) |
| for 循環 | 1.8 ms | 線性 O(n) |
| LINQ FirstOrDefault | 2.1 ms | 委托開銷 |
public static class DropDownListExtensions
{
/// 按 Value 設置選中項,不存在則插入提示項
public static void SelectByValue(this DropDownList ddl, string value, string defaultText = "-- 請選擇 --")
{
ddl.ClearSelection();
var item = ddl.Items.FindByValue(value);
if (item != null)
{
item.Selected = true;
}
else if (!string.IsNullOrEmpty(defaultText))
{
ddl.Items.Insert(0, new ListItem(defaultText, ""));
}
}
/// 按 Text 設置選中項 (模糊匹配)
public static void SelectByText(this DropDownList ddl, string text, bool exactMatch = true)
{
ddl.ClearSelection();
var item = exactMatch
? ddl.Items.FindByText(text)
: ddl.Items.Cast().FirstOrDefault(i => i.Text.Contains(text));
if (item != null) item.Selected = true;
}
/// 安全獲取選中值,未選中返回 defaultValue
public static string GetSelectedValue(this DropDownList ddl, string defaultValue = "")
{
return ddl.SelectedItem?.Value ?? defaultValue;
}
}
// 編輯頁面加載
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
BindDropDownLists();
if (Request.QueryString["id"] != null) // 編輯模式
{
var model = GetModel(int.Parse(Request.QueryString["id"]));
ddlCategory.SelectByValue(model.CategoryId.ToString());
ddlStatus.SelectByText(model.Status);
}
else // 新增模式
{
ddlCategory.SelectByValue("1"); // 默認第一分類
}
}
}
| 問題 | 原因 | 解決 |
|---|---|---|
| 綁定後 SelectedIndex 不生效 | 綁定會重置選中狀態 | 綁定 後 設置選中項 |
| FindByValue 返回 null | Value 類型不匹配 (int vs string)、前後空格 | `value.ToString().Trim()`、數據源 Value 字段類型一致 |
| 多個項目同 Value | 數據源主鍵重複 | 清洗數據源、或用 Text 匹配 |
| UpdatePanel 部分回發選中丟失 | ViewState 未正常保存 | 確保 DropDownList 在 UpdatePanel 內、EnableViewState=true |
優先使用 FindByValue + 擴展方法 `SelectByValue`,代碼簡潔、性能最優、語義清晰。遍歷匹配僅作為特殊業務邏輯的補充。統一封裝擴展方法,消除項目中重複的綁定後選中代碼。