トップ回答者
DetailsViewの接続コードと中でDropDownListのポストバックを有効にするには

質問
-
下記のコードですがエラーが発生した場合Protected Sub On_Sql_Updatedの
Catch ex As Exception
OtherProcessSucceeded = False
End Try
のEnd Tryの部分で
「文字列データまたはバイナリ データが切り捨てられます。 ステートメントは終了されました」となり画面が表示されなくなってしまいます。
HPでこのエラーを元に検索してみたのですが、どう対処したらいいのかわかりません。また、UPDATEの時ドロップダウンで性別を選択するとサイズが性別ごとに
男→M,L,LL
女→S,M,Lというように表示をわけたいのですがどのようにしたらいいのでしょうか?この文↓を追加したいのですが、DropDownListにDropDownListは宣言されていませんというエラーが出て
使い方がわからないのですがよろしくお願いします。
Protected Sub DropDownList1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
If DropDownList1.text = "<選択>" Then
DropDownList2.Items.Clear()
ElseIf DropDownList1.text = "男" Then
DropDownList2.Items.Clear()
DropDownList2.Items.Add("M")
DropDownList2.Items.Add("L")
DropDownList2.Items.Add("LL")
ElseIf DropDownList1.text = "女" Then
DropDownList2.Items.Clear()
DropDownList2.Items.Add("S")
DropDownList2.Items.Add("M")
DropDownList2.Items.Add("L")
End If
End Sub<%@Page Language="VB" %> <%@Import Namespace="System.Data" %> <%@Import Namespace="System.Data.Common" %> <%@Import Namespace="System.Diagnostics" %> <%@ Import Namespace="System.Data.SqlClient" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> Dim fieldNames As New System.Collections.Generic.List(Of String)() Dim oldValues As New System.Collections.Generic.List(Of String)() Dim newValues As New System.Collections.Generic.List(Of String)() Sub CustomerDetail_ItemInserted(ByVal sender As Object, _ ByVal e As DetailsViewInsertedEventArgs) CustomersView.DataBind() End Sub Sub CustomerDetail_ItemInserting(ByVal sender As Object, _ ByVal e As DetailsViewInsertEventArgs) For i As Integer = 0 To e.Values.Count - 1 If e.Values(i) IsNot Nothing Then e.Values(i) = Server.HtmlEncode(e.Values(i).ToString()) End If Next End Sub Sub CustomerDetail_ItemDeleted(ByVal sender As Object, _ ByVal e As DetailsViewDeletedEventArgs) CustomersView.DataBind() End Sub Sub CustomerDetail_ItemUpdating(ByVal sender As Object, _ ByVal e As DetailsViewUpdateEventArgs) For Each entry As DictionaryEntry In e.OldValues fieldNames.Add(DirectCast(entry.Key, String)) oldValues.Add(DirectCast(entry.Value, String)) Next For Each name As String In fieldNames newValues.Add(DirectCast(e.NewValues(name), String)) Next End Sub Public DBAdd As New SqlCommand Public transaction2 As DbTransaction ' Protected Sub On_Sql_Updating(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.SqlDataSourceCommandEventArgs) Dim command As DbCommand Dim connection As DbConnection Dim transaction As DbTransaction 'UPDATEコマンドUpdateCommand="UPDATE 名前 SET 名前 = @名前, 性別 = @性別, サイズ = @サイズ WHERE ID = @ID" command = e.Command '接続の宣言 connection = command.Connection '接続を開く connection.Open() '開いた接続にトランザクションをする宣言 transaction = connection.BeginTransaction() command.Transaction = transaction End Sub Protected Sub On_Sql_Updated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.SqlDataSourceStatusEventArgs) Dim command As DbCommand Dim connection As DbConnection Dim transaction As DbTransaction Dim OtherProcessSucceeded As Boolean = True 'UPDATEコマンドUpdateCommand="UPDATE 名前 SET 名前 = @名前, 性別 = @性別, サイズ = @サイズ WHERE ID = @ID" command = e.Command connection = command.Connection 'トランザクションをする宣言 transaction = command.Transaction Dim rowCount As Integer Try rowCount = e.AffectedRows If rowCount <> 0 Then 'If rowCount = -1 Then Dim insertQuery As String = "Insert Into 履歴 (変更項目, 変更内容, 変更時間) " & "values (@変更項目, @変更内容, @変更時間)" Dim sqlCom As New SqlCommand(insertQuery, DirectCast(connection, SqlConnection)) With sqlCom .Transaction = DirectCast(transaction, SqlTransaction) .Parameters.Add("@変更項目", SqlDbType.VarChar) .Parameters.Add("@変更内容", SqlDbType.VarChar) .Parameters.Add("@変更時間", SqlDbType.DateTime) End With Dim i As Integer For i = 0 To oldValues.Count - 1 If oldValues(i) <> newValues(i) Then sqlCom.Parameters("@変更項目").Value = fieldNames(i) If newValues(i) = Nothing Then sqlCom.Parameters("@変更内容").Value = "" Else sqlCom.Parameters("@変更内容").Value = newValues(i) End If sqlCom.Parameters("@変更時間").Value = Now sqlCom.ExecuteNonQuery() End If Next Else OtherProcessSucceeded = False End If Catch ex As Exception OtherProcessSucceeded = False End Try If (OtherProcessSucceeded) Then transaction.Commit() Label2.Text = "更新しました!" Else transaction.Rollback() Label2.Text = "更新できませんでした" Return End If connection.Close() CustomersView.DataBind() End Sub Protected Sub DropDownList1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) If DropDownList1.text = "<選択>" Then DropDownList2.Items.Clear() ElseIf DropDownList1.text = "男" Then DropDownList2.Items.Clear() DropDownList2.Items.Add("M") DropDownList2.Items.Add("L") DropDownList2.Items.Add("LL") ElseIf DropDownList1.text = "女" Then DropDownList2.Items.Clear() DropDownList2.Items.Add("S") DropDownList2.Items.Add("M") DropDownList2.Items.Add("L") End If End Sub </script> <html > <head id="Head1" runat="server"> <title>DetailsView Example</title> </head> <body> <form id="Form1" runat="server"> <h3>DetailsView Example</h3> <table cellspacing="10"> <tr> <td> <asp:GridView ID="CustomersView" DataSourceID="Customers" AutoGenerateColumns="False" DataKeyNames="ID" runat="server"> <HeaderStyle BackColor="Blue" ForeColor="White" /> <Columns> <asp:CommandField ShowSelectButton="True" /> <asp:BoundField DataField="名前" HeaderText="名前" /> </Columns> </asp:GridView> </td> <td valign="top"> <asp:DetailsView ID="CustomerDetail" DataSourceID="Details" AutoGenerateRows="False" AutoGenerateInsertButton="True" AutoGenerateEditButton="True" AutoGenerateDeleteButton="True" EmptyDataText="No records." DataKeyNames="ID" OnItemInserted="CustomerDetail_ItemInserted" OnItemInserting="CustomerDetail_ItemInserting" OnItemDeleted="CustomerDetail_ItemDeleted" OnItemUpdating="CustomerDetail_ItemUpdating" runat="server"> <HeaderStyle BackColor="Navy" ForeColor="White" /> <RowStyle BackColor="White" /> <AlternatingRowStyle BackColor="LightGray" /> <EditRowStyle BackColor="LightCyan" /> <Fields> <asp:TemplateField HeaderText="ID" InsertVisible="False"> <EditItemTemplate> <asp:Label ID="Label1" runat="server" Text='<%# Eval("ID") %>'></asp:Label> </EditItemTemplate> <ItemTemplate> <asp:Label ID="Label1" runat="server" Text='<%# Bind("ID") %>'></asp:Label> </ItemTemplate> </asp:TemplateField> <asp:TemplateField HeaderText="名前"> <EditItemTemplate> <asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("名前") %>'></asp:TextBox> </EditItemTemplate> <InsertItemTemplate> <asp:TextBox ID="TextBox1" runat="server" MaxLength="5" Text='<%# Bind("名前") %>'></asp:TextBox> </InsertItemTemplate> <ItemTemplate> <asp:Label ID="Label2" runat="server" Text='<%# Bind("名前") %>'></asp:Label> </ItemTemplate> </asp:TemplateField> <asp:TemplateField HeaderText="性別"> <EditItemTemplate> <asp:Label ID="Label5" runat="server" Text='<%# Bind("性別") %>'></asp:Label> <asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="True" SelectedValue='<%# Bind("性別") %>' OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged"> <asp:ListItem><選択></asp:ListItem> <asp:ListItem>男</asp:ListItem> <asp:ListItem>女</asp:ListItem> </asp:DropDownList> </EditItemTemplate> <InsertItemTemplate> <asp:TextBox ID="TextBox2" runat="server" Text='<%# Bind("性別") %>'></asp:TextBox> </InsertItemTemplate> <ItemTemplate> <asp:Label ID="Label3" runat="server" Text='<%# Bind("性別") %>'></asp:Label> </ItemTemplate> </asp:TemplateField> <asp:TemplateField HeaderText="サイズ"> <EditItemTemplate> <asp:Label ID="Label6" runat="server" Text='<%# Bind("サイズ") %>'></asp:Label> <asp:DropDownList ID="DropDownList2" runat="server" SelectedValue='<%# Bind("サイズ") %>'> <asp:ListItem>S</asp:ListItem> <asp:ListItem>M</asp:ListItem> <asp:ListItem>L</asp:ListItem> </asp:DropDownList> </EditItemTemplate> <InsertItemTemplate> <asp:TextBox ID="TextBox3" runat="server" Text='<%# Bind("サイズ") %>'></asp:TextBox> </InsertItemTemplate> <ItemTemplate> <asp:Label ID="Label4" runat="server" Text='<%# Bind("サイズ") %>'></asp:Label> </ItemTemplate> </asp:TemplateField> </Fields> </asp:DetailsView> </td> </tr> </table> <asp:SqlDataSource ID="Customers" runat="server" ConnectionString= "<%$ ConnectionStrings:project_jobConnectionString2%>" SelectCommand="SELECT ID, 名前, 性別, サイズ FROM 名前"> </asp:SqlDataSource> <asp:SqlDataSource ID="Details" ConnectionString= "<%$ ConnectionStrings:project_jobConnectionString2%>" runat="server" SelectCommand="SELECT * FROM 名前 WHERE (ID = @ID)" DeleteCommand="DELETE FROM 名前 WHERE ID = @ID" InsertCommand="INSERT INTO 名前 ( 名前, 性別, サイズ) VALUES (@名前, @性別, @サイズ)" UpdateCommand="UPDATE 名前 SET 名前 = @名前, 性別 = @性別, サイズ = @サイズ WHERE ID = @ID" onupdated="On_Sql_Updated" onupdating="On_Sql_Updating"> <SelectParameters> <asp:ControlParameter ControlID="CustomersView" Name="ID" PropertyName="SelectedValue" Type="String" /> </SelectParameters> <DeleteParameters> <asp:Parameter Name="ID" Type="String" /> </DeleteParameters> <UpdateParameters> <asp:Parameter Name="名前" Type="String" /> <asp:Parameter Name="性別" Type="String" /> <asp:Parameter Name="サイズ" Type="String" /> <asp:Parameter Name="ID" Type="String" /> </UpdateParameters> <InsertParameters> <asp:Parameter Name="ID" Type="String" /> <asp:Parameter Name="名前" Type="String" /> <asp:Parameter Name="性別" Type="String" /> <asp:Parameter Name="サイズ" Type="String" /> </InsertParameters> </asp:SqlDataSource> <asp:Label ID="MessageLabel" runat="server" Text="Label"></asp:Label> <asp:Label id="Label2" runat="server" Text="" /> </form> </body> </html>
回答
-
以下で切り替えれば可能だと思います。
DetailsView.ChangeMode メソッド
http://msdn.microsoft.com/ja-jp/library/system.web.ui.webcontrols.detailsview.changemode.aspx
#タイトルから質問がかけ離れて来ていますので、新しくスレを立て方が良いと思います。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/- 回答としてマーク komi1 2009年6月6日 15:23
すべての返信
-
「文字列データまたはバイナリ データが切り捨てられます。 ステートメントは終了されました」となり画面が表示されなくなってしまいます。
保存する際に、データベースの項目長が短いのではないでしょうか?
この文↓を追加したいのですが、DropDownListにDropDownListは宣言されていませんというエラーが出て
senderからDropDownList1は得られます。DropDownList2はFindControlで見つかると思います。
使い方がわからないのですがよろしくお願いします。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/ -
-
「文字列データまたはバイナリ データが切り捨てられます。 ステートメントは終了されました」となり画面が表示されなくなってしまう問題ですが
保存する際に、データベースの項目長が短いのではないでしょうか?ということですが、
データベースの項目長とは何を指しているのでしょうか?
Dim DropDownList2 As DropDownList = CType(CustomerDetail.FindControl("DropDownList2"), DropDownList)としたら
思うような操作ができるようになりました。ありがとうございます。
DetailsViewの中ではDim XXXX As XXXX で、宣言をすると使えるようになることがわかりました。
ありがとうございます。
編集する時に入力項目(テキストBOXかドロップダウンリスト)の横に、以前入れていたデータがわかるようにテキストボックスをおき
Bind("XXX")とさせました。これで、編集ボタンを押すと、後の方が有効になるので
【テキスト】【入力項目】の場合→新たに選択した入力項目が、保存される
【入力項目】【テキスト】の場合→テキストが保存されるので、変更が保存されない
という結果になってしまいます。テキストは編集ボタンを押したときに一度だけ、テキストに読み込むだけの作業をしたいのですが
どのようにしたらいいのでしょうか? -
保存する際に、データベースの項目長が短いのではないでしょうか?ということですが、
例えば、データベースのテーブルのある項目がnvarchar(10)で定義されている時、11文字の文字列を保存しようとしている場合です。
データベースの項目長とは何を指しているのでしょうか?
Bind("XXX")とさせました。これで、編集ボタンを押すと、後の方が有効になるので
表示だけであればBindではなくEvalを使います。またLabelで表示した方がわかりやすいかもしれません。
【テキスト】【入力項目】の場合→新たに選択した入力項目が、保存される
【入力項目】【テキスト】の場合→テキストが保存されるので、変更が保存されない
という結果になってしまいます。テキストは編集ボタンを押したときに一度だけ、テキストに読み込むだけの作業をしたいのですが
どのようにしたらいいのでしょうか?
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/ -
データベースに保存する前にCustomValidatorなどでチェックを行えば良いでしょう。
また、データベースの更新でエラーが発生したことを知るには、DetailsViewのItemUpdatedイベントハンドラで、DetailsViewUpdatedEventArgsのExceptionを見ることによりわかります。独自にエラー処理をしたら、ExceptionHandledをTrueにします。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/ -
CustomValidatorでチェックをかけることができることがわかりました。
ありがとうございます。これで、文字制限や型の指定ができ、エラーを防げることができますが
もしなんらかの、エラーが発生した場合、エラー画面になり、停止するのではなく、
Label2.Text = "更新できませんでした"となり、更新ボタンを押す前のデータ状態が表示されているようにしたいのですが、
transaction.Rollback()
Label2.Text = "更新できませんでした"
Return
End If
CustomersView.DataBind()
この処理に行ける様にしたいのですが、どのようにしたらいいのでしょうか? -
先に述べたように、データベース更新時にエラーがあったかどうかは、ItemUpdatedイベントハンドラにおいて、DetailsViewUpdatedEventArgsのExceptionがNothingかどうかでわかります。
Nothingでなければ、ItemUpdatedイベントハンドラにおいて、KeepInEditModeおよびExceptionHandledにtrueをセットすれば良いでしょう。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/ -
ありがとうございます。KeepInEditModeおよびExceptionHandledで検索したら
http://msdn.microsoft.com/ja-jp/library/system.web.ui.webcontrols.listviewupdatedeventargs.keepineditmode.aspx
にその例が載っていました。
とりあえず、文に合う様に
Sub ContactsListView_ItemUpdated(sender As Object, e As ListViewUpdatedEventArgs)を
Protected Sub CustomerDetail_ItemUpdated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DetailsViewUpdatedEventArgs)に変更してみましたらうまくエラー画面として表示することができました。
イベントの使い方がいろいろあるんですね。
編集を押したときに例えば QueryString("性別")で女という値をもっていて
編集画面時、選択せずに【女】がすでに入っているようにするには何イベントを使ったらいいのでしょうか? -
性別はDropDownListでしょうか? であれば、DropDownListのDataBoundイベントになります。senderがDropDownListですから、それにキャストすればDataBoundイベントハンドラでDropDownListへの参照が得られます。それをddlとすれば、
ddl.SelectedIndex = ddl.Items.IndexOf(ddl.Items.FindByText("女"))
でうまくいくんじゃないかと思います。(未検証です)
最後のFindByTextのところは、FindByValueを使うことも考えられます。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/ -
ddl.SelectedIndex = ddl.Items.IndexOf(ddl.Items.FindByText("女"))でうまく作動しました。
もし、GridView(CustomersView)を削除し、textBoxとボタンを設置し、
ボタンを押しデータがある場合 → DetailsView(CustomerDetail)のUPDATE画面
ボタンを押しデータがない場合 → DetailsView(CustomerDetail)のINSERT画面を表示と、
DetailsViewイベントにいく前に条件を入れたい場合はどのようにしたらいいのでしょうか? -
以下で切り替えれば可能だと思います。
DetailsView.ChangeMode メソッド
http://msdn.microsoft.com/ja-jp/library/system.web.ui.webcontrols.detailsview.changemode.aspx
#タイトルから質問がかけ離れて来ていますので、新しくスレを立て方が良いと思います。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/- 回答としてマーク komi1 2009年6月6日 15:23
-
ありがとうございます。
下記コードで切り替えができるようになりました。
イベントの使い方や、ドロップダウンや、テキスト、ボタンがダイブ使えるようになり知識も深まりました。
教えていただきありがとうございました。
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim rowCount As Boolean
Dim conStr As String = ConfigurationManager.ConnectionStrings("project_jobConnectionString").ConnectionString
Using con As New SqlConnection(conStr)
Using cmd As SqlCommand = con.CreateCommand()
con.Open()
Try
With cmd
.CommandType = CommandType.Text
.CommandText = "SELECT * FROM 名前 WHERE (ID = @Param1)"
.Parameters.AddWithValue("@Param1", TextBox1.Text)
End With
Dim dr As SqlDataReader
dr = cmd.ExecuteReader(Data.CommandBehavior.CloseConnection)
rowCount = (Not dr.HasRows)
dr.Close()
Catch ex As Exception
End Try
End Using
End Using
Panel1.Visible = True
If rowCount = True Then
DetailsView.DefaultMode = FormViewMode.Insert
Else
DetailsView.DefaultMode = FormViewMode.Edit
End If
End Sub -
ありがとうございます。
下記コードでできるようになりました。
今回の質問で、テキスト・ドロップダウンリスト・ボタンなどの使い方や
イベント処理がだいぶできるようになり知識も深まりました。
ありがとうございました。
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Dim rowCount As Boolean Dim conStr As String = ConfigurationManager.ConnectionStrings("project_jobConnectionString").ConnectionString Using con As New SqlConnection(conStr) Using cmd As SqlCommand = con.CreateCommand() con.Open() Try With cmd .CommandType = CommandType.Text .CommandText = "SELECT * FROM 名前 WHERE (ID = @Param1)" .Parameters.AddWithValue("@Param1", TextBox1.Text) End With Dim dr As SqlDataReader dr = cmd.ExecuteReader(Data.CommandBehavior.CloseConnection) rowCount = (Not dr.HasRows) dr.Close() Catch ex As Exception End Try End Using End Using Panel1.Visible = True If rowCount = True Then DetailsView.DefaultMode = FormViewMode.Insert Else DetailsView.DefaultMode = FormViewMode.Edit End If End Sub