有一个项目需要用到checkboxlist的多选,本以为生成几个层然后点点鼠标就搞定的,结果发现麻烦一大堆,因为CheckBoxList不支持多选.
当我们调用SelectedValue的时候,他默认只返回选中的第一项.然后网上看大多数做法都是在页面内对items遍历然后找被selected的项,但我比较懒,比较喜欢绑定,FormView里面的绑定不用写一堆代码实在是说不过去的.
于是,对CheckBoxList做个扩展看起来是个不错的方法.
摆在我面前的有两条路,第一,重新SelectedValue使他支持多个项目,第二,弄一个新的SelectedValues属性.由于有SelectedIndex这种属性,似乎没法让他返回一个数组而不是数,而且我也不想看CheckBoxList都是如何调用这2个属性的,当然还有SelectedItem,所以我选择了后者.
本着够用就OK的原则,添加了一个属性,SelectedValues,最初的实现方式如下.
public
string
SelectedValues

{
get

{
StringBuilder sb = new StringBuilder();
foreach (ListItem li in this.Items)

{
if (li.Selected)

{
sb.Append(li.Value);
sb.Append(",");
}
}
return sb.ToString();
}
set

{

string[] values = value.Split(new char[]
{','},StringSplitOptions.RemoveEmptyEntries);
this.ClearSelection();
foreach (string val in values)

{
ListItem li = this.Items.FindByValue(val);
if (li != null)
li.Selected = true;
}
}
}
然后拖控件,放到FormView里面,弄好DataBinding跟数据源,更新,提交,看看数据库,Roles字段里面出来个"Administrators,"(顺便说一下,这个是用做自定义的一个权限管理的),恩,回去看的时候却发现CheckBoxList还是空的,我晕,Set出问题了.
调试的时候发现value是有的,但是Items.Count==0,突然意识到现在还没有绑定数据....
没办法,看看SelectedValue的实现方法吧..
[Browsable(
false
), WebCategory(
"
Behavior
"
), Bindable(
true
, BindingDirection.TwoWay), DefaultValue(
""
), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Themeable(
false
), WebSysDescription(
"
ListControl_SelectedValue
"
)]
public
virtual
string
SelectedValue

{
get

{
int selectedIndex = this.SelectedIndex;
if (selectedIndex >= 0)

{
return this.Items[selectedIndex].Value;
}
return string.Empty;
}
set

{
if (this.Items.Count != 0)

{
if ((value == null) || (base.DesignMode && (value.Length == 0)))

{
this.ClearSelection();
return;
}
ListItem item = this.Items.FindByValue(value);
if ((((this.Page != null) && this.Page.IsPostBack) && this._stateLoaded) && (item == null))

{

throw new ArgumentOutOfRangeException("value", SR.GetString("ListControl_SelectionOutOfRange", new object[]
{ this.ID, "SelectedValue" }));
}
if (item != null)

{
this.ClearSelection();
item.Selected = true;
}
}
this.cachedSelectedValue = value;
}
}
cachedSelectedValue,很明显了....他存了一下,肯定DataBound后调用.
于是修改代码,下面贴出完整版:)
using
System;
using
System.Data;
using
System.Configuration;
using
System.Web;
using
System.Web.Security;
using
System.Web.UI;
using
System.Web.UI.HtmlControls;
using
System.Web.UI.WebControls;
using
System.Web.UI.WebControls.WebParts;
using
System.ComponentModel;
using
System.Text;
[assembly: TagPrefix(
"
KingCMS.Web.UI
"
,
"
KingCMS
"
)]
namespace
KingCMS.Web.UI

{
[ToolboxData("<{0}:LoningCheckBoxList runat=server></{0}:LoningCheckBoxList>")]
public class LoningCheckBoxList:CheckBoxList

{
[Category("扩展")]
private string selectedValues;
public string SelectedValues

{
get

{
StringBuilder sb = new StringBuilder();
foreach (ListItem li in this.Items)

{
if (li.Selected)

{
sb.Append(li.Value);
sb.Append(",");
}
}
return sb.ToString();
}
set

{

string[] values = value.Split(new char[]
{','},StringSplitOptions.RemoveEmptyEntries);
selectedValues = value;
this.ClearSelection();
foreach (string val in values)

{
ListItem li = this.Items.FindByValue(val);
if (li != null)
li.Selected = true;
}
}
}
protected override void OnDataBound(EventArgs e)

{
base.OnDataBound(e);
if (selectedValues != null)

{
this.ClearSelection();

string[] values = selectedValues.Split(new char[]
{ ',' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string val in values)

{
ListItem li = this.Items.FindByValue(val);
if (li != null)
li.Selected = true;
}
}
}

}
}
代码还有很多地方需要改进,比如每次都来个StringBuider,没有缓存等等...不过由于在后台了,所以我认为无所谓的,实现功能好了,如果您有好的改进,拿出来一起分享了:)