by WebSurfer
2015年11月2日 18:08
CheckBoxList をデータバインドする際、その子コントロールの ListItem の Text, Value, Selected プロパティを同時に設定する方法について書きます。
たぶん Text と Value プロパティをデーターベースから取得するなどして設定しておき、Selected プロパティ(チェックマーク)はユーザーが設定するというシナリオが多いと思います。
それに加えて Selected プロパティもデーターベースから取得した値であらかじめ設定しておきたいという場合を考えます。
ListItem の Text と Value プロパティは、Visual Studio のデザイン画面で CheckBoxList の DataTextField と DataValueField プロパティにデーターソースのフィールド名を指定しておけば自動的に設定されます。
Selected プロパティの方は CheckBoxList.DataBound イベントのハンドラで設定するのがよさそうです。
以下に Microsoft が提供しているサンプルデータベース Northwind の Products テーブルの ProdctName (int), ProductID (nvarchar), Discontinued (bit) を ListItem の Value, Text, Selected プロパティに設定するサンプルを作ってみました。
オマケに、GridView に CheckBox を実装して同様な形になるものも追加しておきました。どちらがいいかは使い方によると思います。
詳しい説明はサンプルのコメントに書きましたのでそれを見てください。手抜きでスミマセン。(汗)
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Data" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
// CheckBoxList の ListItem の Text, Value, Selected プロパ
// ティそれぞれに Products テーブルの ProdctName, ProductID,
// Discontinued を設定する。
// Page_Load で Products テーブルの ProdctName, ProductID,
// Discontinued から DataView を作成して保持する。
DataView dataView;
// DataView を作成して手動で CheckBoxList に DataBind。
// そこで各 ListItem の Text, Value プロパティは自動的に設
// 定される。
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
dataView = (DataView)SqlDataSource1.Select(
DataSourceSelectArguments.Empty);
CheckBoxList1.DataSource = dataView;
CheckBoxList1.DataBind();
}
}
// Page_Load での CheckBoxList1.DataBind() により DataBound
// イベントが発生する。Page_Load で取得した DataView を利用
// して ListItem の Selected プロパティに Discontiued の値
// を設定する。
protected void CheckBoxList1_DataBound(
object sender, EventArgs e)
{
CheckBoxList list = (CheckBoxList)sender;
foreach (ListItem item in list.Items)
{
dataView.RowFilter =
String.Format("ProductID='{0}'", item.Value);
bool auth = (bool)dataView[0]["Discontinued"];
item.Selected = auth;
}
}
// GridView の場合は RowDataBound イベントで DataRowView が
// 取得できる。なので、DataView を保持しておく必要はなく、
// GridView.DataSourceID に SqlDataSource の ID を設定して
// データバインドは自動的に行うようにすることが可能。
protected void GridView1_RowDataBound(
object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DataRowView drv = (DataRowView)e.Row.DataItem;
CheckBox cb =
(CheckBox)e.Row.FindControl("CheckBox1");
if (cb != null)
{
int id = (int)drv["ProductID"];
// Attributes ではなく InputAttributes を使う
cb.InputAttributes.Add("value", id.ToString());
}
}
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:Northwind %>"
SelectCommand=
"SELECT TOP 10
[ProductID], [ProductName], [Discontinued]
FROM [Products]">
</asp:SqlDataSource>
<h3>CheckBoxList</h3>
<asp:CheckBoxList
ID="CheckBoxList1"
runat="server"
DataTextField="ProductName"
DataValueField="ProductID"
OnDataBound="CheckBoxList1_DataBound">
</asp:CheckBoxList>
<hr />
<h3>GridView</h3>
<asp:GridView ID="GridView1"
runat="server"
AutoGenerateColumns="False"
DataKeyNames="ProductID"
DataSourceID="SqlDataSource1"
ShowHeader="False"
OnRowDataBound="GridView1_RowDataBound"
GridLines="None">
<Columns>
<asp:TemplateField HeaderText="Discontinued"
SortExpression="Discontinued">
<ItemTemplate>
<asp:CheckBox ID="CheckBox1"
runat="server"
Checked='<%# Bind("Discontinued") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="ProductName"
HeaderText="ProductName"
SortExpression="ProductName" />
</Columns>
</asp:GridView>
</div>
</form>
</body>
</html>