Asp.net >> CheckBoxList控件
本篇主要介绍asp.net控件CheckBoxList,会分好几个DEMO来实现。其中会出现几个DLL对象,可从下面地址下载:
http://www.cnblogs.com/insus/articles/1654653.html
http://www.cnblogs.com/insus/articles/1622884.html
从数据库取出数据绑定至CheckBoxList控件,在取出数据之前,得在SQL数据库准备一些数据,创建表[DevCodes],插入数据与获取数据存储过程usp_DevCodes_GetAll:
(
[DC_nbr] [int] IDENTITY(1,1) PRIMARY KEY NOT NULL,
[CodeName] [nvarchar](50) NOT NULL,
)
GO
INSERT INTO [dbo].[DevCodes] ([CodeName]) VALUES
('Assembly'),('C#'),('C/C++'),('CSS'),('HTML'),('Java'),('JScript'),('Delphi(Pascal)'),('Perl'),('PHP'),('Python'),('SQL'),('VB'),('VB.NET'),('VBScript'),('XML')
GO
CREATE PROCEDURE [dbo].[usp_DevCodes_GetAll]
AS
SELECT [DC_nbr],[CodeName] FROM [dbo].[Devcodes]
GO
DevCodes类别:
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
/// <summary>
/// Summary description for DevCodes
/// </summary>
namespace Insus.NET
{
public class DevCodes
{
BusinessBase objBusinessBase = new BusinessBase();
public DevCodes()
{
//
// TODO: Add constructor logic here
//
}
public DataTable GetDevCodes()
{
return objBusinessBase.GetDataToDataSet("usp_DevCodes_GetAll").Tables[0];
}
}
}
.aspx:
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<div>
Development Code:
<br />
<asp:CheckBoxList ID="CheckBoxList1" runat="server" RepeatColumns="4" RepeatDirection="Horizontal">
</asp:CheckBoxList>
</div>
</ContentTemplate>
</asp:UpdatePanel>
.aspx.cs:
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Insus.NET;
public partial class Default2 : System.Web.UI.Page
{
DevCodes objDevCodes = new DevCodes();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Data_Binding();
}
}
private void Data_Binding()
{
//常规写法
this.CheckBoxList1.DataSource = objDevCodes.GetDevCodes();
this.CheckBoxList1.DataTextField = "CodeName";
this.CheckBoxList1.DataValueField = "DC_nbr";
this.CheckBoxList1.DataBind();
}
}
运行时,可以预览到结果:
接下来,是重构,因为一个专案之中,CheckBoxList会有多处地方出现,参考下图常规的写法,非常繁杂,重构中会使用到CheckBoxListUtility对象,去简化CheckBoxList的写法,重构之后,把常规写法的代码注释掉。
Demo1,把选择的选择显示出来,Insus.NET会在.aspx页面放置一个Button和另外一个CheckBoxList去显示选择的结果。
在SQL中写一个存储过程usp_DevCodes_GetByNbr:
(
@nbr NVARCHAR(100)
)
AS
DECLARE @Params NVARCHAR(100) = REPLACE(@nbr, ',',''',''')
EXECUTE('SELECT [DC_nbr],[CodeName] FROM [dbo].[Devcodes] WHERE [DC_nbr] IN (''' + @Params + ''')')
在DevCodes类别添加一个方法GetDevCodesByNbr():
{
Parameter[] parameter = {
new Parameter("@nbr",SqlDbType.NVarChar,100,nbr)
};
return objBusinessBase.GetDataToDataSet("usp_DevCodes_GetByNbr",parameter).Tables[0];
}
在.aspx页面中,添加如下html:
<asp:Button ID="Button1" runat="server" Text="Select" OnClick="Button1_Click" />
<br />
Select development Code:
<br />
<asp:CheckBoxList ID="CheckBoxList2" runat="server" RepeatColumns="4" RepeatDirection="Horizontal">
</asp:CheckBoxList>
在.aspx.cs写Button1_Click事件,下面代码中,你会看到有一个函数GetCheckBoxListSelectedValue(),这个函数最好写在一个公共类别中,这样子整个专案中都可以调用这个函数:
{
string nbr = GetCheckBoxListSelectedValue(this.CheckBoxList1);
objCbl.CheckBoxListParse(this.CheckBoxList2, objDevCodes.GetDevCodesByNbr(nbr), "CodeName", "DC_nbr");
}
//处理选择的值
private string GetCheckBoxListSelectedValue(CheckBoxList checkBoxList)
{
string selectedValue = string.Empty;
foreach (ListItem li in checkBoxList.Items)
{
if (li.Selected)
{
selectedValue = selectedValue + "," + li.Value;
}
}
if (selectedValue.Length > 0)
{
selectedValue = selectedValue.Substring(1);
}
return selectedValue;
}
页面在run时,选择一些选项之后,得到的结果:
Demo2,放置一个CheckBox控件,实现全选功能,这个CheckBox设置属性AutoPostBack="true"和事件OnCheckedChanged ="CheckBox1_CheckedChanged" 。
<br />
Check all:<asp:CheckBox ID="CheckBox1" runat="server" AutoPostBack="true" OnCheckedChanged ="CheckBox1_CheckedChanged" /><br />
<asp:CheckBoxList ID="CheckBoxList1" runat="server" RepeatColumns="4" RepeatDirection="Horizontal">
</asp:CheckBoxList>
在.aspx.cs写OnCheckedChanged的事件CheckBox1_CheckedChanged:
{
ChangedCheckBoxListSelectState(this.CheckBox1, this.CheckBoxList1);
}
private void ChangedCheckBoxListSelectState(CheckBox cb, CheckBoxList cbl)
{
if (cb.Checked)
{
CheckedChanged(cbl, true);
}
else
{
CheckedChanged(cbl, false);
}
}
private void CheckedChanged(CheckBoxList cbl, bool isSelected)
{
foreach (ListItem li in cbl.Items)
{
li.Selected = isSelected;
}
}
运行时,选择这个全选的checkBox,显示效果如下:
Demo3,这个部分,我们把用户选择的做永久保存,即是说保存至SQL数据库中。然后在页面显示时,再去读取数据库。这样子,我们在数据库中设计相关表与存储过程,参考下面SQL代码。
CREATE TABLE MyProfile
(
U_Name NVARCHAR(30) UNIQUE NOT NULL ,
MyCode NVARCHAR(100) NULL
)
GO
--存储过程保存用户选择
CREATE PROCEDURE usp_MyProfile_IntOrUpd
(
@U_Name NVARCHAR(30),
@MyCode NVARCHAR(100)
)
AS
--保存之前首先判断是否已经曾经保存过
SELECT [U_Name],[MyCode] FROM [dbo].[MyProfile] WHERE [U_Name] = @U_Name
--如果是首次选择,把选择选项插入这个表中
IF @@ROWCOUNT <= 0
INSERT INTO [dbo].[MyProfile] ([U_Name],[MyCode]) VALUES (@U_Name,@MyCode)
--非首次,做更新动作。
ELSE
UPDATE [dbo].[MyProfile] SET [MyCode] = @MyCode WHERE [U_Name] = @U_Name
GO
--创建一个存储过程,Get By user选择的数据。
CREATE PROCEDURE usp_MyProfile_GetByUser
(
@U_Name NVARCHAR(30)
)
AS
SELECT [MyCode] FROM [dbo].[MyProfile] WHERE [U_Name] = @U_Name
GO
修改DevCodes类别,添加一个方法InsertOrUpdate(xxx)与函数GetMyCodeByUser(xxx):
public void InsertOrUpdate(string uname, string mycode)
{
Parameter[] parameter = {
new Parameter("@U_Name",SqlDbType.NVarChar,30,uname),
new Parameter("@MyCode",SqlDbType.NVarChar,100,mycode)
};
objBusinessBase.ExecuteProcedure("usp_MyProfile_IntOrUpd", parameter);
}
//获取用户保存的选择的数据
public string GetMyCodeByUser(string uname)
{
Parameter[] parameter = {
new Parameter("@U_Name",SqlDbType.NVarChar,30,uname)
};
return Convert.ToString(objBusinessBase.ExecuteProcedureScalar("usp_MyProfile_GetByUser", parameter));
}
继续修改选择Button1_Click事件:
{
string nbr = GetCheckBoxListSelectedValue(this.CheckBoxList1);
//objCbl.CheckBoxListParse(this.CheckBoxList2, objDevCodes.GetDevCodesByNbr(nbr), "CodeName", "DC_nbr");
try
{
//注意一下这个"Insus.NET",由于没有用户注册环境,如果有的话,应该取得当前用户ID
objDevCodes.InsertOrUpdate("Insus.NET", nbr);
}
catch (Exception ex)
{
InsusJsUtility objJs = new InsusJsUtility();
objJs.JsAlert(ex.Message);
}
}
页面运行时,选择Dev code之后关触发铵钮事件,然后去数据库查看Myprofile表,可以看到保存的结果:
接下来是新建另外一页Edit.aspx,把用户选择的选项从数据库取出来,并显示在编辑页面中,如下图:
新建一页Edit.aspx:
<form id="form1" runat="server">
<div>
My Code:
<br />
<asp:CheckBoxList ID="CheckBoxList1" runat="server" RepeatColumns="4" RepeatDirection="Horizontal">
</asp:CheckBoxList>
</div>
</form>
</body>
.Edit.aspx.cs:
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Insus.NET;
public partial class _Edit : System.Web.UI.Page
{
DevCodes objDevCodes = new DevCodes();
CheckBoxListUtility objCbl = new CheckBoxListUtility();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Data_Binding();
}
}
private void Data_Binding()
{
//从数据库取出用户选择的选项
string myCode = objDevCodes.GetMyCodeByUser("Insus.NET");
//转为阵列
string[] cde = myCode.Split(',');
//使用CheckBoxListUtility组件之上,留意方法重载,最后一个参数
objCbl.CheckBoxListParse(this.CheckBoxList1, objDevCodes.GetDevCodes(), "CodeName", "DC_nbr",cde);
}
}
下图解剖,把选择的值绑定至CheckBoxList控件上。
Demo4,这段演示,把CheckBoxList嵌入至GridView中去,为了演示,Insus.NET在数据库中创建另一个表[Program],其中有一个字段是与上面一表[MyProfile]的[U_Name]关联,以及一个存储过程usp_Program_GetAll。
(
Program_nbr INT IDENTITY PRIMARY KEY NOT NULL,
NVARCHAR(50) NOT NULL,
U_Name NVARCHAR(30)
)
GO
INSERT INTO [dbo].[Program] ([Pgm_Name],[U_Name]) VALUES ('Software Management System','Insus.NET')
GO
CREATE PROCEDURE usp_Program_GetAll
AS
SELECT [Program_nbr],[Pgm_Name], [U_Name] FROM [dbo].[Program]
GO
.aspx页面的html,使用自定义模版<ItemTemplate>和<EditItemTemplate>,前者是显示非编辑状态,需要把CheckBoxList的 Enabled设为"false",即是说不能让用户可选择;而在编辑模版时,与<ItemTemplate>的CheckBoxList设为相反。其它相关的GridView的Edit,Update,Cancel和Delete可参考另外一篇:http://www.cnblogs.com/insus/articles/1944295.html
OnRowCancelingEdit="GridView1_OnCancelCommand" OnRowEditing="GridView1_OnEditCommand"
OnRowUpdating="GridView1_OnUpdateCommand">
<Columns>
<asp:TemplateField HeaderText="Nbr">
<ItemTemplate>
<%# Eval("Program_nbr") %>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Pgm_Name">
<ItemTemplate>
<%# Eval("Pgm_Name") %>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="MyCode">
<ItemTemplate>
<asp:CheckBoxList ID="CheckBoxList1" runat="server" RepeatColumns="4" RepeatDirection="Horizontal"
Enabled="false">
</asp:CheckBoxList>
</ItemTemplate>
<EditItemTemplate>
<asp:CheckBoxList ID="CheckBoxList2" runat="server" RepeatColumns="4" RepeatDirection="Horizontal">
</asp:CheckBoxList>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Edit">
<HeaderStyle BorderWidth="1" BorderColor="#c0c0c0" Width="30" />
<ItemStyle BorderWidth="1" BorderColor="#c0c0c0" />
<ItemTemplate>
<asp:Button ID="Button1" runat="server" Text="Edit" CommandName="Edit" />
</ItemTemplate>
<EditItemTemplate>
<asp:Button ID="Button2" runat="server" Text="Update" CommandName="Update" />
<asp:Button ID="Button3" runat="server" Text="Cancel" CommandName="Cancel" />
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
.aspx.cs,只帖出重点部分:
{
DataRowView drv = (DataRowView)e.Row.DataItem;
if (e.Row.RowType == DataControlRowType.DataRow)
{
if (e.Row.FindControl("CheckBoxList1") != null)
{
EmbedCBL(e, "CheckBoxList1", drv["U_Name"].ToString());
}
if (e.Row.FindControl("CheckBoxList2") != null)
{
EmbedCBL(e, "CheckBoxList2", drv["U_Name"].ToString());
}
}
}
private void EmbedCBL(GridViewRowEventArgs e,string cblId, string Datakey)
{
CheckBoxList cbl = (CheckBoxList)e.Row.FindControl(cblId);
string myCode = objDevCodes.GetMyCodeByUser(Datakey);
string[] cde = myCode.Split(',');
objCbl.CheckBoxListParse(cbl, objDevCodes.GetDevCodes(), "CodeName", "DC_nbr", cde);
}
protected void GridView1_OnUpdateCommand(object sender, GridViewUpdateEventArgs e)
{
CheckBoxList cbl = (CheckBoxList)GridView1.Rows[e.RowIndex].FindControl("CheckBoxList2");
string nbr = GetCheckBoxListSelectedValue(cbl);
objDevCodes.InsertOrUpdate("Insus.NET", nbr); //注意一下,此"Insus.NET"键,因为此是Demo,所以写死了。真正不能这样子喔。
GridView1.EditIndex = -1;
Data_Binding();
}
结果可浏览(下图是一个gif动画,如果没有看到动画效果,尝试刷新一次网页):
Demo5,这部分演示,Insus.NET需要改变一下它的存储方式,不想以"3,8,5,2,9"相似阵列方式存储,改用整型存储。首先把表[MyProfile]的字段MyCode的数据类型由NVARCHAR改为BIGINT.
修改存储过程[dbo].[usp_MyProfile_IntOrUpd]:
(
@U_Name NVARCHAR(30),
@MyCode BIGINT --数据类型由NVARCHAR(100)改为BIGINT
)
AS
SELECT [U_Name],[MyCode] FROM [dbo].[MyProfile] WHERE [U_Name] = @U_Name
IF @@ROWCOUNT <= 0
INSERT INTO [dbo].[MyProfile] ([U_Name],[MyCode]) VALUES (@U_Name,@MyCode)
ELSE
UPDATE [dbo].[MyProfile] SET [MyCode] = @MyCode WHERE [U_Name] = @U_Name
修改DevCodes类别的InsertOrUpdate(xxx)方法。
{
Parameter[] parameter = {
new Parameter("@U_Name",SqlDbType.NVarChar,30,uname),
new Parameter("@MyCode",SqlDbType.BigInt,8,mycode)
};
objBusinessBase.ExecuteProcedure("usp_MyProfile_IntOrUpd", parameter);
}
去修改Button1_Click的事件,你会看到注释“由于每个选择的选项的主键是唯一,我们可以把选中的主键进行Math.Pow处理并相加,最后把相加的总值存起来”。
{
//string nbr = GetCheckBoxListSelectedValue(this.CheckBoxList1);
////objCbl.CheckBoxListParse(this.CheckBoxList2, objDevCodes.GetDevCodesByNbr(nbr), "CodeName", "DC_nbr");
long iV = 0;
foreach (ListItem li in CheckBoxList1.Items)
{
if (li.Selected)
{
//注意一下,下面使用Math.Pow处理。
iV = iV + (long)Math.Pow(2, Convert.ToInt32(li.Value));
}
}
try
{
//注意一下这个"Insus.NET",由于没有用户注册环境,如果有的话,应该取得当前用户ID
//objDevCodes.InsertOrUpdate("Insus.NET", nbr);
objDevCodes.InsertOrUpdate("Insus.NET", iV);
}
catch (Exception ex)
{
InsusJsUtility objJs = new InsusJsUtility();
objJs.JsAlert(ex.Message);
}
}
这时我们查看数据库,可以看到存储这样的结果:
为了看更详细一些,可以下图参考(2^2+2^12+2^14=20484):
由于数据类型改变,如果想把用户选择的选项显示在CheckBoxList为选中的状态,还需要改一下DevCodes类别的GetMyCodeByUser(xxx)方法。
public long GetMyCodeByUser(string uname)
{
Parameter[] parameter = {
new Parameter("@U_Name",SqlDbType.NVarChar,30,uname)
};
return Convert.ToInt64(objBusinessBase.ExecuteProcedureScalar("usp_MyProfile_GetByUser", parameter));
}
接下来是显示绑定的代码:
{
//从数据库取出用户选择的选项
long myCode = objDevCodes.GetMyCodeByUser("Insus.NET");
this.CheckBoxList1.DataSource = objDevCodes.GetDevCodes();
this.CheckBoxList1.DataTextField = "CodeName";
this.CheckBoxList1.DataValueField = "DC_nbr";
this.CheckBoxList1.DataBind();
//foreach CheckBoxList控件
foreach (ListItem li in CheckBoxList1.Items)
{
//Math.Pow处理存储结果
long k = (long)Math.Pow (2,Convert.ToInt32(li.Value));
//如果匹配为true,反之为false
li.Selected = ((myCode & k) == k) ? true : false;
}
}
运行结果:
此Demo5方法,有点限制不足,就是选项不能超过32个选项,在Insus.NET开发过专案中基本没有超过32个的,所以也是Insus.NET最喜欢使用的方法。