0 Comments

ASP.NET中Multi-ListBox控件编程详解

发布于:2013-10-18  |   作者:广州网站建设  |   已聚集:人围观

开发一个优秀的数据绑定不是一件很容易的事情。刚开始的时候走了一些弯路,一直紧紧咬着DataBoundControl类不放。最终失望之后冷静下来想到关于DataSource不就是一个数据集合吗?明白之后,有关数据源的问题基本上也解决了。在整个Multi-ListBox控件开发中,我认为最重要的实际上就是页面的生命周期的理解,如果您基本上理解了它的话,那么,基本上,你以后开发一款ASP.NET控件也不是一件很难的事情。我们还是简单了解开发的思路吧!下面是类的设计图(跟本文无关的方法和属性已被我隐藏)

类的设计图

在控件的生命周期中,我们主要需要解决用户回发页面的时候保留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,
    NameValueCollection 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]); 
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 } 
64

 

一切就是这么简单,就是SaveViewaState,LoadViewState,LoadPostData顺序。后面二个是页面回发的时候才会触发。只要解决这里,最后不过就是呈现控件而已。

如果在页面中使用?

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 } 
22

 

就像前面所说那样,目前只完成的基本的功能,像如果页面放了多个控件之后的问题,让开发人员自定义修改Control Panel的图标,自定义JS路径等都还没有考虑完全(时间有限,只有等以后慢慢完善)。如何跟SqlDataSource控件结合?如何直接可编辑ListBox的Items属性就能呈现?呵呵!需要挑战的还有许多地方。我会抽时间慢慢完善它的功能。

标签:
飞机