輸入框輸入時即時顯示建議清單,**不使用 AJAX/UpdatePanel**,而是利用**隱藏按鈕觸發完整 Postback**,再由 `ListBox` 原生鍵盤支援 (上下鍵選擇) 回填輸入框。這在早期 ASP.NET (無 AJAX 擴充) 環境是常見變通方案。
[輸入框 oninput/onpropertychange] → [JS 觸發隱藏按鈕 click] → [Postback → btnHelp_Click 查詢綁定 ListBox]
↑_______________________________|
ListBox SelectedIndexChanged 回填輸入框
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html>
<html>
<head runat="server">
<title>搜尋建議 Demo</title>
<script type="text/javascript">
// 1. 輸入框值變化 → 觸發隱藏按鈕 Postback
function TriggerSearch() {
var btn = document.getElementById("<%= btnHelp.ClientID %>");
if (btn) btn.click();
}
// 2. 鍵盤上下鍵 → 讓 ListBox 取得焦點 (原生支援上下鍵選擇)
function HandleKeyDown(e) {
e = e || window.event;
// 38=Up, 40=Down
if (e.keyCode === 38 || e.keyCode === 40) {
var lst = document.getElementById("<%= lst.ClientID %>");
if (lst) lst.focus();
} else {
// 其他鍵讓輸入框保持焦點
document.getElementById("<%= inpContent.ClientID %>").focus();
}
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
輸入關鍵字:
<br />
<input runat="server" id="inpContent"
oninput="TriggerSearch()"
onpropertychange="TriggerSearch()"
onkeydown="HandleKeyDown(event)" />
<br />
<asp:ListBox runat="server" ID="lst" AutoPostBack="true"
OnSelectedIndexChanged="lst_SelectedIndexChanged"
Style="display:none; position:absolute; z-index:100;" />
<asp:Button runat="server" ID="btnHelp" Text="隱藏按鈕"
OnClick="btnHelp_Click" Style="display:none;" />
</div>
</form>
</body>
</html>
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// 確保按鈕隱藏 (display:none 不會輸出到頁面導致 JS 找不到)
btnHelp.Style["display"] = "none";
}
// 隱藏按鈕 Click:查詢資料並綁定 ListBox
protected void btnHelp_Click(object sender, EventArgs e)
{
string keyword = inpContent.Value.Trim();
// 模擬資料來源
var allData = new[] { "apple", "application", "banana", "band", "cat", "cater", "dog", "door" };
lst.Items.Clear();
int idx = 0;
foreach (var item in allData)
{
if (item.IndexOf(keyword, StringComparison.OrdinalIgnoreCase) >= 0)
{
lst.Items.Add(new ListItem(item, idx.ToString()));
idx++;
}
}
if (lst.Items.Count > 0)
{
lst.Style["display"] = "block";
lst.SelectedIndex = 0; // 預選第一項
}
else
{
lst.Style["display"] = "none";
}
// 焦點回輸入框,方便繼續輸入
ScriptManager.RegisterStartupScript(this, GetType(), "focusInput",
"$get('" + inpContent.ClientID + "').focus();", true);
}
// ListBox 選項變更 (鍵盤上下鍵或滑鼠點擊) → 回填輸入框
protected void lst_SelectedIndexChanged(object sender, EventArgs e)
{
if (lst.SelectedIndex >= 0)
{
inpContent.Value = lst.SelectedItem.Text;
lst.Style["display"] = "block"; // 保持顯示
// 焦點留在 ListBox 方便繼續上下鍵
ScriptManager.RegisterStartupScript(this, GetType(), "focusList",
"$get('" + lst.ClientID + "').focus();", true);
}
}
}
| 技術點 | 說明 |
|---|---|
| `oninput` + `onpropertychange` | 跨瀏覽器偵測輸入框值變化 (IE 專用 `onpropertychange`) |
| 隱藏按鈕 `display:none` | 不可用 `Visible=false` (不會渲染),需用 CSS 隱藏讓 JS 能 `getElementById` |
| `ListBox.AutoPostBack=true` | 選項變更自動 Postback 觸發 `SelectedIndexChanged` |
| 焦點管理 | Postback 後用 `ScriptManager.RegisterStartupScript` 恢復焦點,否則輸入框失焦體驗極差 |
| 鍵盤導航 | 上下鍵 (38/40) 轉移焦點至 ListBox,利用原生行為避免自行實作選項高亮 |
**現代做法**:
1. **jQuery UI Autocomplete / Select2 / Typeahead.js** + **WebMethod/PageMethod/WebAPI** 回傳 JSON。
2. **ASP.NET Core** + **Fetch API** + **輸入防抖** + **虛擬滾動大清單**。
3. 若必須 WebForms:用 `UpdatePanel` 包裹 ListBox + `AsyncPostBackTrigger` 實現局部更新,但仍建議遷移至 AJAX 方案。
「隱藏按鈕 + ListBox」是 WebForms 早期無 AJAX 環境下的巧妙變通,**利用原生控件 Postback 機制與 ListBox 鍵盤支援** 實現下拉提示。理解此模式有助於維護舊系統;新專案請直接採用前端元件庫 + AJAX/JSON 方案。