需求:建立可重新排序項目(EnhancedListBox)與雙列表項目移動(ListMover)的 Web 控件。傳統 PostBack 方式雖能自動維持 ViewState,但使用者體驗差(頻繁回傳)。目標:客戶端 JavaScript 即時操作 + 伺服器端 ViewState 同步。
ListBox,重寫 Render 方法,在基底 base.Render() 前後插入標題列與上/下移動按鈕。ShowReorderButtons、ShowHeading、ReorderButtonPostBack 等。PostBack=false,需自行處理客戶端排序邏輯。Page.ClientScript.RegisterClientScriptBlock 於 OnInit 註冊 MoveItemUp/Down、BuildItemList 函式,避免重複輸出。output.AddAttribute("onclick", "MoveItemUp(...) BuildItemList(...)")。Page.ClientScript.RegisterHiddenField("__" + ClientID, "") 儲存序列化後的項目清單(格式自訂,如 value1|text1;value2|text2)。Render 結尾輸出 <script>BuildItemList(...);</script> 初始化隱藏欄位。ASP.NET 2.0 將 ListBox.LoadPostData 設為 virtual,可直接重寫:
protected override bool LoadPostData(string postDataKey, NameValueCollection postCollection)
{
base.LoadPostData(postDataKey, postCollection); // 先讓基底處理 SelectedIndex 等
string serialized = postCollection["__" + ClientID];
if (!string.IsNullOrEmpty(serialized))
{
Items.Clear();
foreach (var part in serialized.Split(';'))
{
var kv = part.Split('|');
Items.Add(new ListItem(kv[1], kv[0]));
}
}
return true;
}
如此即可在 PostBack 時,依隱藏欄位內容重建 Items 集合,達成客戶端與伺服器狀態同步。
CreateChildControls 建立 lstLeft、lstRight 及四個移動按鈕(>、>>、<、<<)。onclick 綁定 JavaScript:AddSelectedItemToList、RemoveSelectedItemFromList、BuildItemList(雙邊同步)。IPostBackDataHandler 介面,LoadPostData 同步處理兩側隱藏欄位。ListMover 屬性(如 AllowDuplicates)轉發給內部 EnhancedListBox。完全封裝:EnhancedListBox 內建排序邏輯與同步機制,ListMover 僅組合兩個實例並處理跨列表移動,符合單一職責與開放封閉原則。