詳解ASP.NET的Multi-ListBox控件
開發一個優秀的數據綁定不是一件很容易的事情。剛開始的時候走了一些彎路,一直緊緊咬著 DataBoundControl類不放。最終失望之后冷靜下來想到關于DataSource不就是一個數據集合嗎?明白之后,有關數據源的問題基本上也解決了。在整個ASP.NET Multi-ListBox控件控件開發中,我認為最重要的實際上就是頁面的生命周期的理解,如果您基本上理解了它的話,那么,基本上,你以后開發一款ASP.NET控件也不是一件很難的事情。我們還是簡單了解開發的思路吧。
在ASP.NET Multi-ListBox控件的生命周期中,我們主要需要解決用戶回發頁面的時候保留ListBox的數據源(因為我沒有采用復合控件的方式來開發)。因此,我們需要重寫控件的SaveViewState, LoadViewState二個方法。
- ViewStates
- 1 protected override void LoadViewState
- (object savedState)
- 2 {
- 3 if (savedState != null)
- 4 {
- 5 Triplet triplet = (Triplet)savedState;
- 6 base.LoadViewState(triplet.First);
- 7 Reflector.InvokeMethod(this.FirstListBox.
- Items, "LoadViewState", new object[]
- { triplet.Second });
- 8 Reflector.InvokeMethod(this.SecondListBox.Items,
- "LoadViewState", new object[] { triplet.Third });
- 9 }
- 10 else
- 11 {
- 12 base.LoadViewState(null);
- 13 }
- 14 this._stateLoaded = true;
- 15 }
- 16
- 17 protected override object SaveViewState()
- 18 {
- 19 if (EnableViewState == false)
- 20 return null;
- 21 //啟用控件視圖狀態
- 22 object x = base.SaveViewState();
- 23 object y = Reflector.InvokeMethod
- (FirstListBox.Items, "SaveViewState", null);
- 24 object z = Reflector.InvokeMethod
- (SecondListBox.Items, "SaveViewState", null);
- 25 if ((x == null) && (y == null) && (z == null))
- 26 {
- 27 return null;
- 28 }
- 29 return new Triplet(x, y, z);
- 30 }
為了省事,我沒有自定義ListItem類,改為直接使用ListItemCollection來存儲數據。因為MS沒有提供ListItemCollection. SaveViewState和LoadViewState,我們必須采用反射的方式來調用這二個方法來保存數據。很讓人郁悶。每當到緊要關頭,就會發現MS寫的類,方法不是internal,就是sealed。無可奈何~當然,你也可以自己寫一個類來代替ListItem類.
我們在頁面上進行ListBox進行左移,右移的數據全部需要按一定的格式臨時存儲在HiddenField控件中,這樣我們可以通過繼承IPostBackDataHandler 接口中的LoadPostData方法獲取我們臨時存儲的數據,對ListBox的數據源進行添加,移除等操作。
- IPostBackDataHandler
- 1 public bool LoadPostData
- (string postDataKey, NameVal
- ueCollection postCollection)
- 2 {
- 3 bool resultValueFlag = false;
- 4 //移除指定ListItem,
- 并需要添加了Left ListBox列表框中
- 5 string itemsRemoved =
- postCollection[this.ClientID "_REMOVED"];
- 6 string[] itemsRemovedCol =
- itemsRemoved.Split(',');
- 7 if (itemsRemovedCol != null)
- 8 {
- 9 if (itemsRemovedCol.Length 〉
- 0 && itemsRemovedCol[0] != "")
- 10 {
- 11 for (int i = 0; i 〈
- itemsRemovedCol.Length; i )
- 12 {
- 13 string[] itemsRemoveItems =
- itemsRemovedCol[i].Split('|');
- 14 ListItem item = this.SecondListBox.
- Items.FindByValue(itemsRemoveItems[1]);
- 15 if (item != null)
- 16 {
- 17 this.SecondListBox.Items.Remove(item);
- 18 }
- 19 item = this.FirstListBox.Items.
- FindByValue(itemsRemoveItems[1]);
- 20 if (item == null)
- 21 {
- 22
- 23 this.FirstListBox.Items.Add
- (new ListItem(itemsRemoveItems[0],
- itemsRemoveItems[1]));
- 24 }
- 25 resultValueFlag = true;
- 26 }
- 27 }
- 28 }
- 29 //從客戶端添加指定的ListItem
- 30 string itemsAdded = postCollection
- [this.ClientID "_ADDED"];
- 31 string[] itemsAddedCol = itemsAdded.
- Split(',');
- 32 if (itemsAddedCol != null)
- 33 {
- 34 if (itemsAddedCol.Length 〉
- 0 && itemsAddedCol[0] != "")
- 35 {
- 36 int counter = -1;
- 37 for (int i = 0; i 〈
- itemsAddedCol.Length; i )
- 38 {
- 39 string[] itemsAddItems =
- itemsAddedCol[i].Split('|');
- 40 ListItem item = this.SecondListBox.
- Items.FindByValue(itemsAddItems[1]);
- 41 if (item == null)
- 42 {
- 43 this.SecondListBox.Items.Add(new
- ListItem(itemsAddItems[0],itemsAddItems[1]));
- 44 counter = 1;
- 45 }
- 46 item = this.FirstListBox.Items.
- FindByValue(itemsAddItems[1]); 軟件開發網 www.mscto.com
- 47 if (item != null)
- 48 {
- 49 this.FirstListBox.Items.Remove(item);
- 50 }
- 51 }
- 52 resultValueFlag = counter 〉 -1 ? true : false;
- 53 }
- 54 }
- 55
- 56 //從客戶端中移除指定的ListItem
- 57 return resultValueFlag;
- 58 }
- 59
- 60 public void RaisePostDataChangedEvent()
- 61 {
- 62 //TODO::
- 63 }
一切就是這么簡單,就是SaveViewaState,LoadViewState,LoadPostData順序。后面二個是頁面回發的時候才會觸發。只要解決這里,***不過就是呈現控件而已。 #p#
如果在頁面中使用ASP.NET Multi-ListBox控件?
- HTML
- 1〈asp:MultiListBox ID="ListBox1"
- runat="server" Rows="10" Width="250px"
- Height="200px" DataTextField="UserName"
- DataValueField="UserID"
- SelectionMode="Multiple" 〉
- 2 〈FirstListBox 〉
- 〈StyleSheet Width="100px" / 〉
- 〈/FirstListBox 〉
- 3 〈SecondListBox 〉
- 〈StyleSheet Width="100px" / 〉
- 〈/SecondListBox 〉
- 4 〈/asp:MultiListBox 〉
- 5
- Submit
- 1protected void Page_Load
- (object sender, EventArgs e)
- 2 {
- 3 if (Page.IsPostBack)
- 4 return;
- 5 ListBox1.FirstListBox.
- DataSource = LoadData(1, 5);
- 6 ListBox1.SecondListBox.DataSource =
- LoadData(6, 10);
- 7 ListBox1.DataBind();
- 8}
- 9protected void Button1_Click(object
- sender, EventArgs e)
- 10 {
- 11 Response.Write("您SecondList選擇的值為:
- 〈br/ 〉");
- 12 foreach (ListItem item in this.ListBox1.
- SecondListBox.Items)
- 13 {
- 14 Response.Write(item.Text ":" item.Value
- "〈br/ 〉");
- 15 }
- 16 Response.Write("您FirstList選擇的值為:
- 〈br/ 〉");
- 17 foreach (ListItem item in this.ListBox1.
- FirstListBox.Items)
- 18 {
- 19 Response.Write(item.Text ":" item.Value
- "〈br/ 〉");
- 20 }
- 21 }
就像前面所說那樣,目前只完成的基本的功能,像如果頁面放了多個控件之后的問題,讓開發人員自定義修改Control Panel的圖標,自定義JS路徑等都還沒有考慮完全(時間有限,只有等以后慢慢完善)。如何跟SqlDataSource控件結合?如何直接可編輯ListBox的Items屬性就能呈現?呵呵。需要挑戰的還有許多地方。
【編輯推薦】