Multi-ListBox ASP.NET控件

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

Multi-ListBox控件分成三部分组成,一个是左边的ListBox(FirstListBox),右边的ListBox(SecondListBox)和一个中间的控制面板(Control Panel)。FirstListBox,SecondListBox类似于Asp.net下面的ListBox。它也有DataSource,Itemes属性,但是它本身没有继承ListBox。如下图。
Multi-ListBox ASP.NET控件

Multi-ListBox ASP.NET控件
在控件的生命周期中,我们主要需要解决用户回发页面的时候保留ListBox的数据源(因为我没有采用复合控件的方式来开发)。因些,我们需要重写控件的SaveViewState, LoadViewState二个方法。

Multi-ListBox ASP.NET控件Multi-ListBox ASP.NET控件ViewStates
 1Multi-ListBox ASP.NET控件 protected override void LoadViewState(object savedState)
 2Multi-ListBox ASP.NET控件Multi-ListBox ASP.NET控件        Multi-ListBox ASP.NET控件{
 3Multi-ListBox ASP.NET控件            if (savedState != null)
 4Multi-ListBox ASP.NET控件Multi-ListBox ASP.NET控件            Multi-ListBox ASP.NET控件{
 5Multi-ListBox ASP.NET控件                Triplet triplet = (Triplet)savedState;
 6Multi-ListBox ASP.NET控件                base.LoadViewState(triplet.First);
 7Multi-ListBox ASP.NET控件Multi-ListBox ASP.NET控件                Reflector.InvokeMethod(this.FirstListBox.Items, "LoadViewState"new object[] Multi-ListBox ASP.NET控件{ triplet.Second });
 8Multi-ListBox ASP.NET控件Multi-ListBox ASP.NET控件                Reflector.InvokeMethod(this.SecondListBox.Items, "LoadViewState"new object[] Multi-ListBox ASP.NET控件{ triplet.Third });
 9Multi-ListBox ASP.NET控件            }

10Multi-ListBox ASP.NET控件            else
11Multi-ListBox ASP.NET控件Multi-ListBox ASP.NET控件            Multi-ListBox ASP.NET控件{
12Multi-ListBox ASP.NET控件                base.LoadViewState(null);
13Multi-ListBox ASP.NET控件            }

14Multi-ListBox ASP.NET控件            this._stateLoaded = true;
15Multi-ListBox ASP.NET控件        }

16Multi-ListBox ASP.NET控件
17Multi-ListBox ASP.NET控件        protected override object SaveViewState()
18Multi-ListBox ASP.NET控件Multi-ListBox ASP.NET控件        Multi-ListBox ASP.NET控件{
19Multi-ListBox ASP.NET控件            if (EnableViewState == false)
20Multi-ListBox ASP.NET控件                return null;
21Multi-ListBox ASP.NET控件            //启用控件视图状态
22Multi-ListBox ASP.NET控件            object x = base.SaveViewState();
23Multi-ListBox ASP.NET控件            object y = Reflector.InvokeMethod(FirstListBox.Items, "SaveViewState"null);
24Multi-ListBox ASP.NET控件            object z = Reflector.InvokeMethod(SecondListBox.Items, "SaveViewState"null);
25Multi-ListBox ASP.NET控件            if ((x == null&& (y == null&& (z == null))
26Multi-ListBox ASP.NET控件Multi-ListBox ASP.NET控件            Multi-ListBox ASP.NET控件{
27Multi-ListBox ASP.NET控件                return null;
28Multi-ListBox ASP.NET控件            }

29Multi-ListBox ASP.NET控件            return new Triplet(x, y, z);
30Multi-ListBox ASP.NET控件        }

31Multi-ListBox ASP.NET控件       
为了省事,我没有自定义ListItem类,改为直接使用ListItemCollection来存储数据。因为MS没有提供ListItemCollection. SaveViewState和LoadViewState,我们必须采用反射的方式来调用这二个方法来保存数据。很让人郁闷。每当到紧要关头,就会发现MS写的类,方法不是internal,就是sealed。无可奈何~当然,你也可以自己写一个类来代替ListItem类.
我们在页面上进行ListBox进行左移,右移的数据全部需要按一定的格式临时存储在HiddenField控件中,这样我们可以通过继承IPostBackDataHandler 接口中的LoadPostData方法获取我们临时存储的数据,对ListBox的数据源进行添加,移除等操作。
Multi-ListBox ASP.NET控件Multi-ListBox ASP.NET控件IPostBackDataHandler
 1Multi-ListBox ASP.NET控件 public bool LoadPostData(string postDataKey, NameValueCollection postCollection)
 2Multi-ListBox ASP.NET控件Multi-ListBox ASP.NET控件        Multi-ListBox ASP.NET控件{
 3Multi-ListBox ASP.NET控件            bool resultValueFlag = false;
 4Multi-ListBox ASP.NET控件            //移除指定ListItem,并需要添加了Left ListBox列表框中
 5Multi-ListBox ASP.NET控件            string itemsRemoved = postCollection[this.ClientID + "_REMOVED"];
 6Multi-ListBox ASP.NET控件            string[] itemsRemovedCol = itemsRemoved.Split(',');
 7Multi-ListBox ASP.NET控件            if (itemsRemovedCol != null)
 8Multi-ListBox ASP.NET控件Multi-ListBox ASP.NET控件            Multi-ListBox ASP.NET控件{
 9Multi-ListBox ASP.NET控件                if (itemsRemovedCol.Length > 0 && itemsRemovedCol[0!= "")
10Multi-ListBox ASP.NET控件Multi-ListBox ASP.NET控件                Multi-ListBox ASP.NET控件{
11Multi-ListBox ASP.NET控件                    for (int i = 0; i < itemsRemovedCol.Length; i++)
12Multi-ListBox ASP.NET控件Multi-ListBox ASP.NET控件                    Multi-ListBox ASP.NET控件{
13Multi-ListBox ASP.NET控件                        string[] itemsRemoveItems = itemsRemovedCol[i].Split('|');
14Multi-ListBox ASP.NET控件                        ListItem item = this.SecondListBox.Items.FindByValue(itemsRemoveItems[1]);
15Multi-ListBox ASP.NET控件                        if (item != null)
16Multi-ListBox ASP.NET控件Multi-ListBox ASP.NET控件                        Multi-ListBox ASP.NET控件{
17Multi-ListBox ASP.NET控件                            this.SecondListBox.Items.Remove(item);
18Multi-ListBox ASP.NET控件                        }

19Multi-ListBox ASP.NET控件                        item = this.FirstListBox.Items.FindByValue(itemsRemoveItems[1]);
20Multi-ListBox ASP.NET控件                        if (item == null)
21Multi-ListBox ASP.NET控件Multi-ListBox ASP.NET控件                        Multi-ListBox ASP.NET控件{
22Multi-ListBox ASP.NET控件
23Multi-ListBox ASP.NET控件                            this.FirstListBox.Items.Add(new ListItem(itemsRemoveItems[0], itemsRemoveItems[1]));
24Multi-ListBox ASP.NET控件                        }

25Multi-ListBox ASP.NET控件                        resultValueFlag = true;
26Multi-ListBox ASP.NET控件                    }

27Multi-ListBox ASP.NET控件                }

28Multi-ListBox ASP.NET控件            }

29Multi-ListBox ASP.NET控件            //从客户端添加指定的ListItem
30Multi-ListBox ASP.NET控件            string itemsAdded = postCollection[this.ClientID + "_ADDED"];
31Multi-ListBox ASP.NET控件            string[] itemsAddedCol = itemsAdded.Split(',');
32Multi-ListBox ASP.NET控件            if (itemsAddedCol != null)
33Multi-ListBox ASP.NET控件Multi-ListBox ASP.NET控件            Multi-ListBox ASP.NET控件{
34Multi-ListBox ASP.NET控件                if (itemsAddedCol.Length > 0 && itemsAddedCol[0!= "")
35Multi-ListBox ASP.NET控件Multi-ListBox ASP.NET控件                Multi-ListBox ASP.NET控件{
36Multi-ListBox ASP.NET控件                    int counter = -1;
37Multi-ListBox ASP.NET控件                    for (int i = 0; i < itemsAddedCol.Length; i++)
38Multi-ListBox ASP.NET控件Multi-ListBox ASP.NET控件                    Multi-ListBox ASP.NET控件{
39Multi-ListBox ASP.NET控件                        string[] itemsAddItems = itemsAddedCol[i].Split('|');
40Multi-ListBox ASP.NET控件                        ListItem item = this.SecondListBox.Items.FindByValue(itemsAddItems[1]);
41Multi-ListBox ASP.NET控件                        if (item == null)
42Multi-ListBox ASP.NET控件Multi-ListBox ASP.NET控件                        Multi-ListBox ASP.NET控件{
43Multi-ListBox ASP.NET控件                            this.SecondListBox.Items.Add(new ListItem(itemsAddItems[0],itemsAddItems[1]));
44Multi-ListBox ASP.NET控件                            counter += 1;
45Multi-ListBox ASP.NET控件                        }

46Multi-ListBox ASP.NET控件                        item = this.FirstListBox.Items.FindByValue(itemsAddItems[1]);
47Multi-ListBox ASP.NET控件                        if (item != null)
48Multi-ListBox ASP.NET控件Multi-ListBox ASP.NET控件                        Multi-ListBox ASP.NET控件{
49Multi-ListBox ASP.NET控件                            this.FirstListBox.Items.Remove(item);
50Multi-ListBox ASP.NET控件                        }

51Multi-ListBox ASP.NET控件                    }

52Multi-ListBox ASP.NET控件                    resultValueFlag = counter > -1 ? true : false;
53Multi-ListBox ASP.NET控件                }

54Multi-ListBox ASP.NET控件            }

55Multi-ListBox ASP.NET控件
56Multi-ListBox ASP.NET控件            //从客户端中移除指定的ListItem
57Multi-ListBox ASP.NET控件            return resultValueFlag;
58Multi-ListBox ASP.NET控件        }

59Multi-ListBox ASP.NET控件
60Multi-ListBox ASP.NET控件        public void RaisePostDataChangedEvent()
61Multi-ListBox ASP.NET控件Multi-ListBox ASP.NET控件        Multi-ListBox ASP.NET控件
62Multi-ListBox ASP.NET控件            //TODO::
63Multi-ListBox ASP.NET控件        }

64Multi-ListBox ASP.NET控件


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

如果在页面中使用?

Multi-ListBox ASP.NET控件Multi-ListBox ASP.NET控件HTML
1Multi-ListBox ASP.NET控件<asp:MultiListBox ID="ListBox1" runat="server" Rows="10" Width="250px" Height="200px" DataTextField="UserName" DataValueField="UserID" SelectionMode="Multiple">
2Multi-ListBox ASP.NET控件Multi-ListBox ASP.NET控件    <FirstListBox><StyleSheet Width="100px" />Multi-ListBox ASP.NET控件</FirstListBox>
3Multi-ListBox ASP.NET控件    <SecondListBox><StyleSheet Width="100px" /></SecondListBox>
4Multi-ListBox ASP.NET控件    </asp:MultiListBox>
5Multi-ListBox ASP.NET控件

Multi-ListBox ASP.NET控件Multi-ListBox ASP.NET控件Submit
 1Multi-ListBox ASP.NET控件protected void Page_Load(object sender, EventArgs e)
 2Multi-ListBox ASP.NET控件    {
 3Multi-ListBox ASP.NET控件        if (Page.IsPostBack)
 4Multi-ListBox ASP.NET控件            return;
 5Multi-ListBox ASP.NET控件        ListBox1.FirstListBox.DataSource = LoadData(1, 5);
 6Multi-ListBox ASP.NET控件        ListBox1.SecondListBox.DataSource = LoadData(6, 10);
 7Multi-ListBox ASP.NET控件        ListBox1.DataBind();
 8Multi-ListBox ASP.NET控件}
 9Multi-ListBox ASP.NET控件protected void Button1_Click(object sender, EventArgs e)
10Multi-ListBox ASP.NET控件    {
11Multi-ListBox ASP.NET控件        Response.Write("您SecondList选择的值为:<br/>");
12Multi-ListBox ASP.NET控件        foreach (ListItem item in this.ListBox1.SecondListBox.Items)
13Multi-ListBox ASP.NET控件        {
14Multi-ListBox ASP.NET控件            Response.Write(item.Text + ":" + item.Value + "<br/>");
15Multi-ListBox ASP.NET控件        }
16Multi-ListBox ASP.NET控件        Response.Write("您FirstList选择的值为:<br/>");
17Multi-ListBox ASP.NET控件        foreach (ListItem item in this.ListBox1.FirstListBox.Items)
18Multi-ListBox ASP.NET控件        {
19Multi-ListBox ASP.NET控件            Response.Write(item.Text + ":" + item.Value + "<br/>");
20Multi-ListBox ASP.NET控件        }
21Multi-ListBox ASP.NET控件    }
22Multi-ListBox ASP.NET控件


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

最后,就是源码奉上(ASP.NET2.0)

演示地址:http://www.zfans.net/multilistboxdemo.aspx
下载地址:http://files.cnblogs.com/cnzc/AspNet2.WebControls.rar

posted on 2007-06-21 10:27 ms_dos 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/nine425/archive/2007/06/21/791485.html