ComboBox [开放源代码]

我在Web项目的开发过程中很多时候都要用到ComboBox,找了很多类似的控件来用发现都不尽如人意,我所希望的能够在WEB上使用的ComboBox应该就是在DropDownList的功能上加入了文本输入功能,我个人比较看重的一点就是下拉列表应该可以伸展到浏览器之外,然而目前大多数的ComboBox要么是用DIV来显示选择项,要么就是用TextBox+ListBox,DIV的方式会不能伸展到浏览器之外,而TextBox+ListBox方式ListBox占用页面空间。后来发现了A DHTML combo box , 于是决定基于此HTC开发一个ASP.NET服务器控件. 
单击在新窗口中打开图片,Ctrl+滚轮缩放图片  

关键类设计  
  • ComboBox : 关键是有一个Text属性获取控件值,没有SelectedIndexChanged事件(我觉得该事件对ComboBox来说不是很重要,当然你也可以根据你自己的需要增加对此事件的支持),Items属性当然是必不可少的; 
  • ComboItem : 相对于ListItem来说我没有设计Value属性; 
  • ComboItemCollection : 这是ComboItem的集合类,实现了ICollection接口,其功能类似ListItemCollection。

实现ViewState  

实现ViewState是我个人觉得最有趣的部分,根据类的层次结构,先看看ComboItem如何实现ViewState,其实很简单,就是实现System.Web.UI.IStateManager接口: 
[csharp]  view plain  copy
  1.     public void TrackViewState()
        {
            this._IsTrackingViewState = true;
        }
        public bool IsTrackingViewState
        {
            get { return this._IsTrackingViewState; }
        }
        public object SaveViewState()
        {
            return new Pair(this._text, this._selected);
        }
        public void LoadViewState(object state)
        {
            if (state != null && state is Pair)
            {
                Pair p = (Pair)state;
                this._text = (string)p.First;
                this._selected = (bool)p.Second;
            }
        }  

SaveViewState()方法保存了ComboItem的Text和Selected属性,而LoadViewState(object state)则还原了这两个属性。 

接着看看ComboItemCollection,同样实现IStateManager接口: 
[csharp]  view plain  copy
  1.     public void TrackViewState()
        {
            this._IsTrackingViewState = true;
            for (int i = 0; i < this._items.Count; i++)
            {
                ((IStateManager)this[i]).TrackViewState();
            }
        }
        public bool IsTrackingViewState
        {
            get { return this._IsTrackingViewState; }
        }
        public object SaveViewState()
        {
            ArrayList list1 = new ArrayList();
            ArrayList list2 = new ArrayList();
            for (int num3 = 0; num3 < this.Count; num3++)
            {
                object obj1 = ((IStateManager)this[num3]).SaveViewState();
                if (obj1 != null)
                {
                    list1.Add(num3);
                    list2.Add(obj1);
                }
            }
            if (list1.Count > 0)
            {
                return new Pair(list1, list2);
            }
            return null;
        }
        public void LoadViewState(object state)
        {
            if (state == null)
            {
                return;
            }
            if (state is Pair)
            {
                Pair pair1 = (Pair)state;
                ArrayList list1 = (ArrayList)pair1.First;
                ArrayList list2 = (ArrayList)pair1.Second;
                for (int num1 = 0; num1 < list1.Count; num1++)
                {
                    int num2 = (int)list1[num1];
                    if (num2 < this.Count)
                    {
                        ((IStateManager)this[num2]).LoadViewState(list2[num1]);
                    }
                    else
                    {
                        ComboItem item1 = new ComboItem();
                        ((IStateManager)item1).LoadViewState(list2[num1]);
                        this.Add(item1);
                    }
                }
            }
        }

SaveViewState()方法逐项保存视图状态,LoadViewState(object state) 逐项还原。 

最后看看ComboBox,重写了如下一些方法: 
[csharp]  view plain  copy
  1.     protected override void TrackViewState()
        {
            base.TrackViewState();
            ((IStateManager)this.Items).TrackViewState();
        }
        protected override object SaveViewState()
        {
            object obj1 = base.SaveViewState();
            object obj2 = ((IStateManager)this.Items).SaveViewState();
            object obj3 = this.Text;
            if (obj1 == null && obj2 == null && obj3 == null)
                return null;
            return new Triplet(obj1, obj2, obj3);
        }
        protected override void LoadViewState(object savedState)
        {
            if (savedState != null)
            {
                Triplet state = (Triplet)savedState;
                base.LoadViewState(state.First);
                ((IStateManager)this.Items).LoadViewState(state.Second);
                _text = (string)state.Third;
            }
        }

SaveViewState()方法保存了基类的视图状态,同时将Items属性和Text属性保存到视图状态中,而LoadViewState(object savedState)方法则实现还原。 

实现IPostBackDataHandler接口  
[csharp]  view plain  copy
  1.     public void RaisePostDataChangedEvent()
        {
        }
        public bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
        {
            string[] textArray1 = postCollection.GetValues(postDataKey);
            if (textArray1 != null)
            {
                this.ClearSelection();
                ComboItem item = this.FindByText(textArray1[0]);
                if (item != null)
                {
                    item.Selected = true;
                }
                _text = textArray1[0];
            }
            return false;
        }


实现数据绑定  

如何像DropDownList一样实现数据绑定,也是我十分关心的部分。关键是重写OnDataBinding方法,同时增加了一个类DataSourceHelper来解析数据源。 
[csharp]  view plain  copy
  1.     protected override void OnDataBinding(EventArgs e)
        {
            base.OnDataBinding(e);
            IEnumerable enumerable1 = DataSourceHelper.GetResolvedDataSource(this.DataSource, this.DataMember);
            if (enumerable1 != null)
            {
                this.Items.Clear();
                foreach (object obj1 in enumerable1)
                {
                    ComboItem item = new ComboItem();
                    if (this.DataTextField != string.Empty)
                        item.Text = DataBinder.GetPropertyValue(obj1, this.DataTextField, null);
                    else
                        item.Text = obj1.ToString();
                    this.Items.Add(item);
                }
            }
        }
三种使用方式  
编程方式: 
[csharp]  view plain  copy
  1.         for (int i = 1; i < 10; i++)
            {
                ComboItem item = new ComboItem("Item" + i.ToString());
                ComboBox1.Items.Add(item);
            }

数据绑定方式 
[csharp]  view plain  copy
  1.         DataTable dt = new DataTable();
            dt.Columns.Add("text", typeof(string));
            for (int i = 1; i < 10; i++)
            {
                DataRow ndr = dt.NewRow();
                ndr["text"] = "Item" + i.ToString();
                dt.Rows.Add(ndr);
            }


            ComboBox3.DataSource = dt.DefaultView;
            ComboBox3.DataTextField = "text";
            ComboBox3.DataBind(); 

页面直接申明方式 
[html]  view plain  copy
  1. <bestcomy:ComboBox id="ComboBox2" runat="server" Width="120px">
    <BESTCOMY:COMBOITEM Text="Item1"></BESTCOMY:COMBOITEM>
    <BESTCOMY:COMBOITEM Text="Item2"></BESTCOMY:COMBOITEM>
    <BESTCOMY:COMBOITEM Text="Item3" Selected="true"></BESTCOMY:COMBOITEM>
    <BESTCOMY:COMBOITEM Text="Item4"></BESTCOMY:COMBOITEM>
    </bestcomy:ComboBox>

源代码下载 
http://www.cnblogs.com/Files/bestcomy/WebControlTest.rar  
ComboBox(组合框)在.NET编程中通常用来展示一组选项供用户选择,它的数据源决定了ComboBox显示的内容。数据源可以是多种类型的,下面是几种常见的设置方式: 1. **字符串数组**:直接在属性窗口的`Items`属性中添加一维字符串数组,每个字符串代表一个选项。 ```csharp string[] options = {"Option1", "Option2", "Option3"}; comboBox.DataSource = options; ``` 2. **列表(List<T>)**:可以使用动态生成的列表,例如`List<string>`,包含自定义的对象或字符串。 ```csharp List<string> items = new List<string> { "Item1", "Item2" }; comboBox.DataSource = items; ``` 3. **自定义数据结构**:当选项来自数据库或其他复杂数据源时,可以使用`BindingSource`或`ICollectionView`,它们支持数据绑定到外部数据源。 ```csharp BindingSource bs = new BindingSource(); bs.DataSource = GetCustomData(); // 自定义函数返回数据集 comboBox.DataSource = bs; ``` 4. **枚举**:如果所有选项是从枚举类型中提取的,可以直接绑定到枚举类型本身。 ```csharp enum Color { Red, Green, Blue } comboBox.DataSource = Enum.GetValues(typeof(Color)); comboBox.DisplayMember = "Name"; ``` 5. **事件驱动**:通过事件(如`DataSourceChanged`或`CurrentIndexChanged`)实时更新数据源,比如用户输入筛选条件后从数据库加载新数据。 每种数据源设置方式都会影响ComboBox的行为,比如用户交互、数据过滤和搜索等。明确数据源后,可以根据实际需求配置`DisplayMember`(显示文本的属性)和`ValueMember`(表示选定对象的属性)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值