最終更新日 2006 年 3 月 30 日
サンプル コードのダウンロード
(aspnettips_ClientCallback4.msi, 271 KB)
※このサンプルをお使いいただくためには、Visual Studio 2005 が必要です。
クライアント・コールバックでデータベースの値を表示する方法
クライアント・コールバックの機能を使い、サーバーにあるデータベースから値を受け取る方法については、クライアント・コールバックでデータベースの値を表示する方法で紹介しました。ここで紹介したサンプルは、データベースの値を表示するのみでした。では、値を更新するときにはどうすればよいでしょうか。
そこで、今回は、クライアント・コールバックの機能を使い、値を送信しすることで、データベースの値を更新する方法について紹介します。
サンプル フォームの準備
サーバーで参照するデータベースは、図1 にあるものを使います。今回は、データベースを更新するため、クライアント・コールバックでデータベースの値を表示する方法で紹介したページに [更新] ボタンを追加したページを用意します(リスト1、リスト2、および図1)。[更新] ボタンを押したとき現在の値をサーバーへ送信してデータベースを更新するページを作成していきます。
図
1. IMAGE.mdb
の
IMGINFO
テーブル
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="ClientCallback.aspx.vb" Inherits="_ClientCallback" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html >
<head runat="server">
<title>Sample Page</title>
<script type="text/javascript">
function ChangeImage()
{
var lb = document.MyForm.ListBox1;
var imageNo = lb.options[lb.selectedIndex].value
CallServer(imageNo, "");
}
function ReceiveServerData(rcvValue)
{
// サーバーからの戻り値を配列に変換
rcvValues = rcvValue.split(unescape("%0A"));
// 列を添え字にした連想配列を作成
var Row = new Object();
for (count = 0; count < rcvValues.length; count=count+2){
Row[rcvValues[count]] = rcvValues[count + 1];
}
// 値の表示
if (Row["IMGPATH"] == ""){
document.MyForm.Image1.src = "dummy.gif";
}else{
document.MyForm.Image1.src = Row["IMGPATH"];
}
document.MyForm.TextImageName.value = Row["NAME"];
document.MyForm.TextImageColor.value = Row["COLOR"];
}
</script>
</head>
<body>
<form id="MyForm" runat="server">
<br />
<table border="1">
<tr>
<td>
画像番号
</td>
<td>
<asp:ListBox ID="ListBox1" runat="server"></asp:ListBox>
</td>
</tr>
<tr>
<td>
イメージ
</td>
<td>
<asp:Image ID="Image1" runat="server" ImageUrl="dummy.gif" />
</td>
</tr>
<tr>
<td>
名称
</td>
<td>
<asp:TextBox ID="TextImageName" Runat="server"></asp:TextBox>
</td>
</tr>
<tr>
<td>
色
</td>
<td>
<asp:TextBox ID="TextImageColor" Runat="server"></asp:TextBox>
</td>
</tr>
<tr>
<td colspan="2" style="height: 28px" align="center">
<input type="Button" id="Button1" value="更新" onclick="UpdateData();"/>
</td>
</tr>
</table>
</form>
</body>
</html> |
リスト1.ClientCallback.aspx
Partial Class _ClientCallback
Inherits System.Web.UI.Page
Implements System.Web.UI.ICallbackEventHandler
Private returnValue As String
Private myDataSet As Data.DataSet
Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim cbReference As String
cbReference = Page.ClientScript.GetCallbackEventReference(Me, "arg", "ReceiveServerData", "context")
Dim callbackScript As String = ""
callbackScript &= "function CallServer(arg, context) { " & cbReference & "} ;"
Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), "CallServer", callbackScript, True)
' DataSet を作成し、データを読み込む
myDataSet = New Data.DataSet
myDataSet.Locale = Globalization.CultureInfo.InvariantCulture
LoadDataSet()
' リスト ボックスの設定
ListBox1.DataSource = myDataSet
ListBox1.DataTextField = "NAME"
ListBox1.DataValueField = "ID"
ListBox1.DataBind()
ListBox1.Attributes.Add("onchange", "ChangeImage();")
End Sub
Public Function OpenDataBase() As Data.OleDb.OleDbConnection
Dim Conn As New Data.OleDb.OleDbConnection()
Conn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" + _
AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "IMAGE.MDB"
' 取得したレコードを DataSet に設定
Dim ds As New Data.DataSet
ds.Locale = Globalization.CultureInfo.InvariantCulture
Conn.Open()
Return Conn
End Function
Public Sub LoadDataSet()
Dim oleConn = OpenDataBase()
Dim cmdSelect As New Data.OleDb.OleDbCommand("SELECT * FROM IMGINFO", oleConn)
Dim oleDataAdapter As New Data.OleDb.OleDbDataAdapter(cmdSelect)
oleDataAdapter.Fill(myDataSet)
oleConn.Close()
oleDataAdapter.Dispose()
cmdSelect.Dispose()
oleConn.Dispose()
End Sub
Public Function GetRecordString(ByVal keyId As String) As String
Dim DataView As New Data.DataView(myDataSet.Tables(0))
DataView.RowFilter = "ID=" + keyId
Dim recordString As New StringBuilder()
If DataView.Count > 0 Then
' 改行コードを区切りにして複数パラメータを渡す
For count As Integer = 0 To DataView.Table.Columns.Count - 1
' フィールド名を設定
recordString.Append(DataView.Table.Columns(count).ColumnName)
recordString.Append(vbLf) ' 改行コード
' 値を設定
recordString.Append(DataView(0)(count).ToString)
If count < DataView.Table.Columns.Count - 1 Then
recordString.Append(vbLf) ' 改行コード
End If
Next
End If
DataView.Dispose()
Return recordString.ToString
End Function
Public Sub RaiseCallbackEvent(ByVal eventArgument As String) Implements System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent
' レコードの取得処理
returnValue = GetRecordString(eventArgument)
End Sub
Public Function GetCallbackResult() As String Implements System.Web.UI.ICallbackEventHandler.GetCallbackResult
Return returnValue
End Function
End Class |
リスト2.ClientCallback.aspx.vb
図
2. ClientCallback.aspx
のデザイナ画面
データベースの更新処理を作成する
リスト3 のコード追加して、DataSet の値を元にデータベースを更新する処理を追加します。このコードを追加した後、myDataSet のレコードを更新してから UpdateDataSet を呼出すことでデータベースを更新することが出来ます。
Public Sub UpdateDataSet()
Dim oleConn = OpenDataBase()
Dim cmdSelect As New Data.OleDb.OleDbCommand("SELECT * FROM IMGINFO", oleConn)
Dim oleDataAdapter As New Data.OleDb.OleDbDataAdapter(cmdSelect)
Dim oleCmdBuilder = New Data.OleDb.OleDbCommandBuilder(oleDataAdapter)
oleDataAdapter.Update(myDataSet)
oleConn.Close()
oleDataAdapter.Dispose()
cmdSelect.Dispose()
oleConn.Dispose()
End Sub |
リスト3.ClientCallback.aspx.vb に追加するコード
サーバー コールバック メソッドでレコードの更新処理を追加する
今回のサンプルでは、クライアント・コールバック処理は 1 つ実装していますが、データベースの値の取得と、更新の 2 種類の処理に分かれています。そこで、RaiseCallbackEvent で渡ってくるコールバック値が、改行文字で区切られていなかった場合は、画像番号のみ送られてきたと判断し、レコードの取得処理を実行します。改行文字で区切られていた場合は、レコードの全てのフィールド値が送られてきたと判断し、レコードの更新処理を実行します(リスト4 の赤文字)。
レコードの更新処理では、受け取ったコールバック値をフィールド毎に分離します。分離した値は、フィールド名を添え字とする連想配列に格納します。こうすることで、フィールド名を指定した連想配列から値を取得することが出来ます。
Public Sub RaiseCallbackEvent(ByVal eventArgument As String) Implements System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent
If eventArgument.IndexOf(vbLf) < 1 Then
' レコードの取得処理
returnValue = GetRecordString(eventArgument)
Else
' レコードの更新処理
' クライアントが渡してきたパラメータを配列に変換
Dim arrArg As String() = eventArgument.Split(vbLf)
' 列を添え字にした連想配列を作成
Dim hasRow As New Hashtable()
For count As Integer = 0 To arrArg.Length - 2 Step 2
hasRow(arrArg(count)) = arrArg(count + 1)
Next
' 指定された ID のレコードが存在したら値を更新
Dim dataRow As Data.DataRow() = myDataSet.Tables(0).Select("ID=" + hasRow("ID"))
If dataRow.Length > 0 Then
' 値の更新
Dim rowTarget As Data.DataRow = dataRow(0)
rowTarget("NAME") = hasRow("NAME")
rowTarget("COLOR") = hasRow("COLOR")
UpdateDataSet()
End If
' クライアントへ返す戻り値
returnValue = ""
End If
End Sub |
リスト4.ClientCallback.aspx.vb に追加するコード
クライアント コールバック メソッドでレコードの更新処理を追加する
[更新] ボタンが押されたとき呼出される UpdateData を追加します。ここでは、サーバーへ送信するレコードの値を各コントロールから取得し、サーバー側の GetRecordString で作成する文字列と同じフォーマットのものを作成します(リスト5)。
function UpdateData()
{
var lb = document.MyForm.ListBox1;
if (lb.selectedIndex != -1){
var imageNo = lb.options[lb.selectedIndex].value;
var imageName = document.MyForm.TextImageName.value;
var imageColor = document.MyForm.TextImageColor.value;
var paramData = "";
paramData += "ID" + unescape("%0A") + imageNo + unescape("%0A");
paramData += "NAME" + unescape("%0A") + imageName + unescape("%0A");
paramData += "COLOR" + unescape("%0A") + imageColor;
CallServer(paramData, "");
}
} |
リスト5.ClientCallback.aspx
に追加するコード
また、サーバー側の処理が完了したときに呼ばれる ReceiveServerData では、サーバー側の RaiseCallbackEvent と同様に、取得と更新の 2 つの処理に分けます。今回のサンプルでは、更新完了時になにも行っていませんが、処理の完了を通知するクライアント スクリプト コードを追加することもできます(リスト6)。
function ReceiveServerData(rcvValue)
{
if (rcvValue.indexOf(unescape("%0A")) < 1){
// レコードの更新完了
}else{
// レコードの取得完了
// サーバーからの戻り値を配列に変換
rcvValues = rcvValue.split(unescape("%0A"));
// 列を添え字にした連想配列を作成
var Row = new Object();
for (count = 0; count < rcvValues.length; count=count+2){
Row[rcvValues[count]] = rcvValues[count + 1];
}
// 値の表示
if (Row["IMGPATH"] == ""){
document.MyForm.Image1.src = "dummy.gif";
}else{
document.MyForm.Image1.src = Row["IMGPATH"];
}
document.MyForm.TextImageName.value = Row["NAME"];
document.MyForm.TextImageColor.value = Row["COLOR"];
}
} |
リスト6.ClientCallback.aspx に追加するコード
完成した ClientCallback.aspx と ClientCallback.aspx.vb は、リスト7 およびリスト8 になり、実行結果は図3 のようになります。
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="ClientCallback.aspx.vb" Inherits="_ClientCallback" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html >
<head runat="server">
<title>Sample Page</title>
<script type="text/javascript">
function ChangeImage()
{
var lb = document.MyForm.ListBox1;
var imageNo = lb.options[lb.selectedIndex].value;
CallServer(imageNo, "");
}
function ReceiveServerData(rcvValue)
{
if (rcvValue.indexOf(unescape("%0A")) < 1){
// レコードの更新完了
}else{
// レコードの取得完了
// サーバーからの戻り値を配列に変換
rcvValues = rcvValue.split(unescape("%0A"));
// 列を添え字にした連想配列を作成
var Row = new Object();
for (count = 0; count < rcvValues.length; count=count+2){
Row[rcvValues[count]] = rcvValues[count + 1];
}
// 値の表示
if (Row["IMGPATH"] == ""){
document.MyForm.Image1.src = "dummy.gif";
}else{
document.MyForm.Image1.src = Row["IMGPATH"];
}
document.MyForm.TextImageName.value = Row["NAME"];
document.MyForm.TextImageColor.value = Row["COLOR"];
}
}
function UpdateData()
{
var lb = document.MyForm.ListBox1;
if (lb.selectedIndex != -1){
var imageNo = lb.options[lb.selectedIndex].value;
var imageName = document.MyForm.TextImageName.value;
var imageColor = document.MyForm.TextImageColor.value;
var paramData = "";
paramData += "ID" + unescape("%0A") + imageNo + unescape("%0A");
paramData += "NAME" + unescape("%0A") + imageName + unescape("%0A");
paramData += "COLOR" + unescape("%0A") + imageColor;
CallServer(paramData, "");
}
}
</script>
</head>
<body>
<form id="MyForm" runat="server">
<br />
<table border="1">
<tr>
<td>
画像番号
</td>
<td>
<asp:ListBox ID="ListBox1" runat="server"></asp:ListBox>
</td>
</tr>
<tr>
<td>
イメージ
</td>
<td>
<asp:Image ID="Image1" runat="server" ImageUrl="dummy.gif" />
</td>
</tr>
<tr>
<td>
名称
</td>
<td>
<asp:TextBox ID="TextImageName" Runat="server"></asp:TextBox>
</td>
</tr>
<tr>
<td>
色
</td>
<td>
<asp:TextBox ID="TextImageColor" Runat="server"></asp:TextBox>
</td>
</tr>
<tr>
<td colspan="2" style="height: 28px" align="center">
<input type="Button" id="Button1" value="更新" onclick="UpdateData();"/>
</td>
</tr>
</table>
</form>
</body>
</html> |
リスト7.ClientCallback.aspx
Partial Class _ClientCallback
Inherits System.Web.UI.Page
Implements System.Web.UI.ICallbackEventHandler
Private returnValue As String
Private myDataSet As Data.DataSet
Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim cbReference As String
cbReference = Page.ClientScript.GetCallbackEventReference(Me, "arg", "ReceiveServerData", "context")
Dim callbackScript As String = ""
callbackScript &= "function CallServer(arg, context) { " & cbReference & "} ;"
Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), "CallServer", callbackScript, True)
' DataSet を作成し、データを読み込む
myDataSet = New Data.DataSet
myDataSet.Locale = Globalization.CultureInfo.InvariantCulture
LoadDataSet()
' リスト ボックスの設定
ListBox1.DataSource = myDataSet
ListBox1.DataTextField = "NAME"
ListBox1.DataValueField = "ID"
ListBox1.DataBind()
ListBox1.Attributes.Add("onchange", "ChangeImage();")
End Sub
Public Function OpenDataBase() As Data.OleDb.OleDbConnection
Dim Conn As New Data.OleDb.OleDbConnection()
Conn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" + _
AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "IMAGE.MDB"
' 取得したレコードを DataSet に設定
Dim ds As New Data.DataSet
ds.Locale = Globalization.CultureInfo.InvariantCulture
Conn.Open()
Return Conn
End Function
Public Sub LoadDataSet()
Dim oleConn = OpenDataBase()
Dim cmdSelect As New Data.OleDb.OleDbCommand("SELECT * FROM IMGINFO", oleConn)
Dim oleDataAdapter As New Data.OleDb.OleDbDataAdapter(cmdSelect)
oleDataAdapter.Fill(myDataSet)
oleConn.Close()
oleDataAdapter.Dispose()
cmdSelect.Dispose()
oleConn.Dispose()
End Sub
Public Sub UpdateDataSet()
Dim oleConn = OpenDataBase()
Dim cmdSelect As New Data.OleDb.OleDbCommand("SELECT * FROM IMGINFO", oleConn)
Dim oleDataAdapter As New Data.OleDb.OleDbDataAdapter(cmdSelect)
Dim oleCmdBuilder = New Data.OleDb.OleDbCommandBuilder(oleDataAdapter)
oleDataAdapter.Update(myDataSet)
oleConn.Close()
oleDataAdapter.Dispose()
cmdSelect.Dispose()
oleConn.Dispose()
End Sub
Public Function GetRecordString(ByVal keyId As String) As String
Dim DataView As New Data.DataView(myDataSet.Tables(0))
DataView.RowFilter = "ID=" + keyId
Dim recordString As New StringBuilder()
If DataView.Count > 0 Then
' 改行コードを区切りにして複数パラメータを渡す
For count As Integer = 0 To DataView.Table.Columns.Count - 1
' フィールド名を設定
recordString.Append(DataView.Table.Columns(count).ColumnName)
recordString.Append(vbLf) ' 改行コード
' 値を設定
recordString.Append(DataView(0)(count).ToString)
If count < DataView.Table.Columns.Count - 1 Then
recordString.Append(vbLf) ' 改行コード
End If
Next
End If
DataView.Dispose()
Return recordString.ToString
End Function
Public Sub RaiseCallbackEvent(ByVal eventArgument As String) Implements System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent
If eventArgument.IndexOf(vbLf) < 1 Then
' レコードの取得処理
returnValue = GetRecordString(eventArgument)
Else
' レコードの更新処理
' クライアントが渡してきたパラメータを配列に変換
Dim arrArg As String() = eventArgument.Split(vbLf)
' 列を添え字にした連想配列を作成
Dim hasRow As New Hashtable()
For count As Integer = 0 To arrArg.Length - 2 Step 2
hasRow(arrArg(count)) = arrArg(count + 1)
Next
' 指定された ID のレコードが存在したら値を更新
Dim dataRow As Data.DataRow() = myDataSet.Tables(0).Select("ID=" + hasRow("ID"))
If dataRow.Length > 0 Then
' 値の更新
Dim rowTarget As Data.DataRow = dataRow(0)
rowTarget("NAME") = hasRow("NAME")
rowTarget("COLOR") = hasRow("COLOR")
UpdateDataSet()
End If
' クライアントへ返す戻り値
returnValue = ""
End If
End Sub
Public Function GetCallbackResult() As String Implements System.Web.UI.ICallbackEventHandler.GetCallbackResult
Return returnValue
End Function
End Class |
リスト8.ClientCallback.aspx.vb
図
3. ClientCallback.aspx
の実行結果