开发一个优秀的数据绑定不是一件很容易的事情。刚开始的时候走了一些弯路,一直紧紧咬着 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属性就能呈现?呵呵。需要挑战的还有许多地方。
【编辑推荐】