トップ回答者
ListViewでフッタの表示の仕方、データの合計の表示の仕方について。

質問
-
いつもお世話になっております。
ちぃと申します。早速ですが、質問させて頂きます。
ListViewでフッタを表示させる方法がわからず質問させていただいています。
自分なりに調べた結果、LayoutTemplateのところにヘッダのコードを書けばいいのではということは解ったのですが、
書き方が解らず質問させていただいております。
ListViewのコードを載せさせていただきます。太字の部分が問題の部分です。
どのようにコードを加えたらよいのか教えていただけますか?商品名 l 注文数 l 単価 l 金額
---------------------------------------------------
ミックスピザ l 1 l 1050 l 1050
--------------------------------------------------
ミックピザ l 2 l 1050 l 2100
--------------------------------------------------
総計 3150 フッタ行
---------------------------------------------------<asp:ListView ID="ListView1" runat="server" DataSourceID="SqlDataSource5"
DataKeyNames="伝票id,行番号" InsertItemPosition="LastItem">
<ItemTemplate>
<tr style="background-color: #FFFBD6;color: #333333;">
<td>
<asp:Label ID="商品名Label" runat="server" Text='<%# Eval("商品名") %>' />
</td>
<td>
<asp:Label ID="注文数Label" runat="server" Text='<%# Eval("注文数") %>' />
</td>
<td>
<asp:Label ID="単価Label" runat="server" Text='<%# Eval("単価") %>' />
</td>
<td>
<asp:Label ID="金額Label" runat="server" Text='<%# Eval("金額") %>' />
</td>
<td>
<asp:Button ID="DeleteButton" runat="server" CommandName="Delete" Text="削除"
OnClientClick="return confirm("削除してもよろしいですか?")" />
<asp:Button ID="EditButton" runat="server" CommandName="Edit" Text="編集" />
</td>
</tr>
</ItemTemplate>
<AlternatingItemTemplate>
<tr style="background-color: #FAFAD2;color: #284775;">
<td>
<asp:Label ID="商品名Label" runat="server" Text='<%# Eval("商品名") %>' />
</td>
<td>
<asp:Label ID="注文数Label" runat="server" Text='<%# Eval("注文数") %>' />
</td>
<td>
<asp:Label ID="単価Label" runat="server" Text='<%# Eval("単価") %>' />
</td>
<td>
<asp:Label ID="金額Label" runat="server" Text='<%# Eval("金額") %>' />
</td>
<td>
<asp:Button ID="DeleteButton" runat="server" CommandName="Delete" Text="削除"
OnClientClick="return confirm("削除してもよろしいですか?")"/>
<asp:Button ID="EditButton" runat="server" CommandName="Edit" Text="編集" />
</td>
</tr>
</AlternatingItemTemplate>
<EmptyDataTemplate>
<table runat="server"
style="background-color: #FFFFFF;border-collapse: collapse;border-color: #999999;border-style:none;border-width:1px;">
<tr>
<td>
データは返されませんでした。</td>
</tr>
</table>
</EmptyDataTemplate>
<InsertItemTemplate>
<tr style="">
<td>
<asp:DropDownList ID="DropDownList6" runat="server"
AppendDataBoundItems="true"
DataSourceID="SqlDataSource6"
DataTextField="商品名"
DataValueField="商品id">
<asp:ListItem>選択してください</asp:ListItem>
</asp:DropDownList>
</td>
<td>
<asp:TextBox ID="注文数TextBox" runat="server" Text='<%# Bind("注文数") %>' />
</td>
<td>
N/A (入力不可)
</td>
<td>
N/A (入力不可)
</td>
<td>
<asp:Button ID="InsertButton" runat="server" CommandName="Insert" Text="挿入" />
<asp:Button ID="CancelButton" runat="server" CommandName="Cancel" Text="クリア" />
</td>
</tr>
</InsertItemTemplate>
<LayoutTemplate>
<table runat="server">
<tr runat="server">
<td runat="server">
<table ID="itemPlaceholderContainer" runat="server" border="1"
style="background-color: #FFFFFF;border-collapse: collapse;border-color: #999999;border-style:none;border-width:1px;font-family: Verdana, Arial, Helvetica, sans-serif;">
<tr runat="server" style="background-color: #FFFBD6;color: #333333;">
<th runat="server">
商品名</th>
<th runat="server">
注文数</th>
<th runat="server">
単価</th>
<th runat="server">
金額</th>
</tr>
<tr ID="itemPlaceholder" runat="server">
</tr>
</table>
</td>
</tr>
<tr runat="server">
<td runat="server"
style="text-align: center;background-color: #FFCC66;font-family: Verdana, Arial, Helvetica, sans-serif;color: #333333;">
<asp:DataPager ID="DataPager1" runat="server">
<Fields>
<asp:NextPreviousPagerField ButtonType="Button" ShowFirstPageButton="True"
ShowLastPageButton="True" />
</Fields>
</asp:DataPager>
</td>
</tr>
</table>
</LayoutTemplate>
<EditItemTemplate>
<tr style="background-color: #FFCC66;color: #000080;">
<td>
<asp:Button ID="UpdateButton" runat="server" CommandName="Update" Text="更新" />
<asp:Button ID="CancelButton" runat="server" CommandName="Cancel"
Text="キャンセル" />
</td>
<td>
<asp:DropDownList ID="DropDownList7" runat="server"
DataSourceID="SqlDataSource6"
DataTextField="商品名"
DataValueField="商品id"
SelectedValue='<%# Bind("商品id") %>'>
</asp:DropDownList>
</td>
<td>
<asp:TextBox ID="注文数TextBox" runat="server" Text='<%# Bind("注文数") %>' />
</td>
<td>
N/A (入力不可)
</td>
<td>
N/A (入力不可)
</td>
</tr>
</EditItemTemplate>
<SelectedItemTemplate>
<tr style="background-color: #FFCC66;font-weight: bold;color: #000080;">
<td>
<asp:Label ID="商品idLabel" runat="server" Text='<%# Eval("商品id") %>' />
</td>
<td>
<asp:Label ID="商品名Label" runat="server" Text='<%# Eval("商品名") %>' />
</td>
<td>
<asp:Label ID="注文数Label" runat="server" Text='<%# Eval("注文数") %>' />
</td>
<td>
<asp:Label ID="単価Label" runat="server" Text='<%# Eval("単価") %>' />
</td>
<td>
<asp:Label ID="金額Label" runat="server" Text='<%# Eval("金額") %>' />
</td>
<td>
<asp:Button ID="DeleteButton" runat="server" CommandName="Delete" Text="削除" />
<asp:Button ID="EditButton" runat="server" CommandName="Edit" Text="編集" />
</td>
</tr>
</SelectedItemTemplate>
</asp:ListView>
<asp:SqlDataSource ID="SqlDataSource5" runat="server"
ConnectionString="<%$ ConnectionStrings:MyDB %>"
DeleteCommand="DELETE FROM Tchumon_meisai WHERE (伝票id = @伝票id) AND (行番号 = @行番号)"
InsertCommand="INSERT INTO Tchumon_meisai(伝票id, 商品id, 注文数) VALUES (@伝票id, @商品id, @注文数) "
SelectCommand="SELECT Tchumon_meisai.伝票id, Tchumon_meisai.行番号, Tchumon_meisai.商品id,
Tsyohin.商品名, Tchumon_meisai.注文数, Tsyohin.単価, Tchumon_meisai.注文数 * Tsyohin.単価
AS 金額 FROM Tsyohin INNER JOIN Tchumon_meisai ON Tsyohin.商品ID = Tchumon_meisai.商品id
WHERE (伝票id = @伝票id)"
UpdateCommand="UPDATE Tchumon_meisai SET 商品id = @商品id, 注文数 = @注文数
WHERE (伝票id = @伝票id) AND (行番号 = @行番号)">
<SelectParameters>
<asp:ControlParameter ControlID="DropDownList1" Name="伝票ID"
PropertyName="SelectedValue" />
</SelectParameters>
<DeleteParameters>
<asp:Parameter Name="伝票id" />
<asp:Parameter Name="行番号" />
</DeleteParameters>
<UpdateParameters>
<asp:Parameter Name="商品id" />
<asp:Parameter Name="注文数" />
<asp:Parameter Name="伝票id" />
<asp:Parameter Name="行番号" />
</UpdateParameters>
<InsertParameters>
<asp:ControlParameter ControlID="DropDownList1" Name="伝票ID"
PropertyName="SelectedValue" />
<asp:Parameter Name="商品id" />
<asp:Parameter Name="注文数" />
</InsertParameters>
</asp:SqlDataSource>- 編集済み ちい 2010年5月10日 5:40 急に質問内容を変更してしまったので、元にもどします。
回答
-
> 結果をラベルに表示する方法なのですが、いまいちわからずこのよう
> に書いてみたのですが、エラーになってしまいました。どの行でエラーが出ているかと、エラーメッセージの内容ぐらいは書い
てくださいね。> この中身を見てみるとNothingとなっていて、きちんと値を取
> 得出来ていないようなのですが、どのようにしたら値を取得できるの
> かわかりませんでした。紹介したページで見てほしかったのは、金額を含む行全体のデータが入
っている DataRowView を取得し、それから金額データを取得する方法
だったのですが・・・ちいさんのコードでは、金額Label から値を取得ようにしていますが、
そこで[編集]ボタンをクリックするとどうなるでしょう? 例外が
スローされるはずです。以下のように修正して試してみてください。
(1) まず、先にレスしたように、ハンドラは2つ必要です。DataBound
イベントのハンドラを追加してください。(2) 追加した DataBound イベントのハンドラの中に ItemDataBound
イベントのハンドラから以下の2行を移動してください。Dim 総計 As Label = e.Item.FindControl("合計La")
総計.text = Ctype(sum, string)(3) ItemDataBound イベントのハンドラの中の If 文を以下のように変
更してください。If e.Item.ItemType = ListViewItemType.DataItem Then
(4) 紹介した「ListViewDataItem クラス」のページのコードを参考に、
DataRowView を取得し、その中から金額データを取得し、それを
sum に足しこんでいくようにしてください。(5) 型変換がうまくいかなかったら、Parse するなりキャストするなり
して適宜修正してください。- 回答としてマーク ちい 2010年5月12日 9:14
すべての返信
-
> ListViewでフッタを表示させる方法がわからず質問させて
> いただいています。LayoutTemplate の中の、
> <tr ID="itemPlaceholder" runat="server">
> </tr>の直下に一行追加してはいかがですか? 一行追加というのは、具体的に
は <tr> <td> タグを記述して、その中の一つの <td> タグの中に「総計」
という文字を記述し、その横の <td> タグの中に Label を配置するとい
うことです。挿入のための行が邪魔な感じなので、InsertItemPosition="FirstItem"
とした方がよいかもしれません。それだけで自動的に総計が表示されるわけではもちろんなく、各行に含
まれる「金額」データを取得して合計し、結果を上記で配置した Label
に表示するという操作が必要です。「金額」データを取得して合計するのは ListView.ItemDataBound イベ
ントのハンドラで行うと良いと思います。具体的な例は、以下のページ
が参考になると思います。ListViewDataItem クラス
http://msdn.microsoft.com/ja-jp/library/system.web.ui.webcontrols.listviewdataitem.aspx#MtViewDropDownText結果をラベルに表示するのは、ListView.DataBound イベントのハンドラ
で、FindControl メソッドで Label を取得し、その Text プロパティに
合計を設定することで可能です。 -
SurferOnWwwさんへ
返信ありがとうございました。
>質問の内容を、最初に質問をアップして何時間か経ってから大幅に変更しましたよね?>それをすると、質問と回答の内容の整合が取れなくなって、訳がわからなくなってしまいます。
>他のユーザーのことも考えて、変更する場合はいつどのように変更したかが分かるようにしていただきたく。
質問の変更をいきなりしてしまい、すみません。
他のユーザーの方が混乱してしまいますね。
質問は最初のものに戻しておきました。ご迷惑おかけしました。上記のことを参考にListViewでのフッタの表示と合計を計算するコードを書いて見ました。
結果をラベルに表示する方法なのですが、いまいちわからずこのように書いてみたのですが、エラーになってしまいました。
この中身を見てみるとNothingとなっていて、きちんと値を取得出来ていないようなのですが、どのようにしたら値を取得できるのかわかりませんでした。すみませんが、教えていただいてもよろしいでしょうか?
★コード'合計計算
Dim sum As Integer = 0
Protected Sub ListView1_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ListViewItemEventArgs)If ListView1.EditIndex < 0 Then
Dim 合計 As Label = e.Item.FindControl("金額Label")
Dim goukei As Integer = 合計.Textsum += goukei
Dim 総計 As Label = e.Item.FindControl("合計La")
総計.text = Ctype(sum, string)
End If
End Sub
<asp:ListView ID="ListView1" runat="server" DataSourceID="SqlDataSource5"
DataKeyNames="伝票id,行番号" InsertItemPosition="FirstItem"
OnItemDataBound="ListView1_ItemDataBound"
onselectedindexchanged="ListView1_SelectedIndexChanged">
<ItemTemplate>
<tr style="background-color: #FFFBD6;color: #333333;">
<td>
<asp:Label ID="商品名Label" runat="server" Text='<%# Eval("商品名") %>' />
</td>
<td>
<asp:Label ID="注文数Label" runat="server" Text='<%# Eval("注文数") %>' />
</td>
<td>
<asp:Label ID="単価Label" runat="server" Text='<%# Eval("単価") %>' />
</td>
<td>
<asp:Label ID="金額Label" runat="server" Text='<%# Eval("金額") %>' />
</td>
<td>
<asp:Button ID="DeleteButton" runat="server" CommandName="Delete" Text="削除"
OnClientClick="return confirm("削除してもよろしいですか?")" />
<asp:Button ID="EditButton" runat="server" CommandName="Edit" Text="編集" />
</td>
</tr>
</ItemTemplate>
<AlternatingItemTemplate>
<tr style="background-color: #FAFAD2;color: #284775;">
<td>
<asp:Label ID="商品名Label" runat="server" Text='<%# Eval("商品名") %>' />
</td>
<td>
<asp:Label ID="注文数Label" runat="server" Text='<%# Eval("注文数") %>' />
</td>
<td>
<asp:Label ID="単価Label" runat="server" Text='<%# Eval("単価") %>' />
</td>
<td>
<asp:Label ID="金額Label" runat="server" Text='<%# Eval("金額") %>' />
</td>
<td>
<asp:Button ID="DeleteButton" runat="server" CommandName="Delete" Text="削除"
OnClientClick="return confirm("削除してもよろしいですか?")"/>
<asp:Button ID="EditButton" runat="server" CommandName="Edit" Text="編集" />
</td>
</tr>
</AlternatingItemTemplate>
<EmptyDataTemplate>
<table runat="server"
style="background-color: #FFFFFF;border-collapse: collapse;border-color: #999999;border-style:none;border-width:1px;">
<tr>
<td>
データは返されませんでした。</td>
</tr>
</table>
</EmptyDataTemplate>
<InsertItemTemplate>
<tr style="">
<td>
<asp:DropDownList ID="DropDownList6" runat="server"
AppendDataBoundItems="true"
DataSourceID="SqlDataSource6"
DataTextField="商品名"
DataValueField="商品id">
<asp:ListItem>選択してください</asp:ListItem>
</asp:DropDownList>
</td>
<td>
<asp:TextBox ID="注文数TextBox" runat="server" Text='<%# Bind("注文数") %>' />
</td>
<td>
N/A (入力不可)
</td>
<td>
N/A (入力不可)
</td>
<td>
<asp:Button ID="InsertButton" runat="server" CommandName="Insert" Text="挿入" />
<asp:Button ID="CancelButton" runat="server" CommandName="Cancel" Text="クリア" />
</td>
</tr>
</InsertItemTemplate>
<LayoutTemplate>
<table runat="server">
<tr runat="server">
<td runat="server">
<table ID="itemPlaceholderContainer" runat="server" border="1"
style="background-color: #FFFFFF;border-collapse: collapse;border-color: #999999;border-style:none;border-width:1px;font-family: Verdana, Arial, Helvetica, sans-serif;">
<tr runat="server" style="background-color: #FFFBD6;color: #333333;">
<th runat="server">
商品名</th>
<th runat="server">
注文数</th>
<th runat="server">
単価</th>
<th runat="server">
金額</th>
</tr>
<tr ID="itemPlaceholder" runat="server">
</tr>
'フッタの表示
<tr>
<td >総計:<asp:Label ID="合計La" runat="server" /></td>
</tr>
</table>
</td>
</tr>
<tr runat="server">
<td runat="server"
style="text-align: center;background-color: #FFCC66;font-family: Verdana, Arial, Helvetica, sans-serif;color: #333333;">
<asp:DataPager ID="DataPager1" runat="server">
<Fields>
<asp:NextPreviousPagerField ButtonType="Button" ShowFirstPageButton="True"
ShowLastPageButton="True" />
</Fields>
</asp:DataPager>
</td>
</tr>
</table>
</LayoutTemplate>
<EditItemTemplate>
<tr style="background-color: #FFCC66;color: #000080;">
<td>
<asp:DropDownList ID="DropDownList7" runat="server"
DataSourceID="SqlDataSource6"
DataTextField="商品名"
DataValueField="商品id"
SelectedValue='<%# Bind("商品id") %>'>
</asp:DropDownList>
</td>
<td>
<asp:TextBox ID="注文数TextBox" runat="server" Text='<%# Bind("注文数") %>' />
</td>
<td>
N/A (入力不可)
</td>
<td>
N/A (入力不可)
</td>
<td>
<asp:Button ID="UpdateButton" runat="server" CommandName="Update" Text="更新" />
<asp:Button ID="CancelButton" runat="server" CommandName="Cancel"
Text="キャンセル" />
</td>
</tr>
</EditItemTemplate>
<SelectedItemTemplate>
<tr style="background-color: #FFCC66;font-weight: bold;color: #000080;">
<td>
<asp:Label ID="商品idLabel" runat="server" Text='<%# Eval("商品id") %>' />
</td>
<td>
<asp:Label ID="商品名Label" runat="server" Text='<%# Eval("商品名") %>' />
</td>
<td>
<asp:Label ID="注文数Label" runat="server" Text='<%# Eval("注文数") %>' />
</td>
<td>
<asp:Label ID="単価Label" runat="server" Text='<%# Eval("単価") %>' />
</td>
<td>
<asp:Label ID="金額Label" runat="server" Text='<%# Eval("金額") %>' />
</td>
<td>
<asp:Button ID="DeleteButton" runat="server" CommandName="Delete" Text="削除" />
<asp:Button ID="EditButton" runat="server" CommandName="Edit" Text="編集" />
</td>
</tr>
</SelectedItemTemplate>
</asp:ListView>
<asp:SqlDataSource ID="SqlDataSource5" runat="server"
ConnectionString="<%$ ConnectionStrings:MyDB %>"
DeleteCommand="DELETE FROM Tchumon_meisai WHERE (伝票id = @伝票id) AND (行番号 = @行番号)"
InsertCommand="INSERT INTO Tchumon_meisai(伝票id, 商品id, 注文数) VALUES (@伝票id, @商品id, @注文数) "
SelectCommand="SELECT Tchumon_meisai.伝票id, Tchumon_meisai.行番号, Tchumon_meisai.商品id,
Tsyohin.商品名, Tchumon_meisai.注文数, Tsyohin.単価, Tchumon_meisai.注文数 * Tsyohin.単価
AS 金額 FROM Tsyohin INNER JOIN Tchumon_meisai ON Tsyohin.商品ID = Tchumon_meisai.商品id
WHERE (伝票id = @伝票id)"
UpdateCommand="UPDATE Tchumon_meisai SET 商品id = @商品id, 注文数 = @注文数
WHERE (伝票id = @伝票id) AND (行番号 = @行番号)">
<SelectParameters>
<asp:ControlParameter ControlID="DropDownList1" Name="伝票ID"
PropertyName="SelectedValue" />
</SelectParameters>
<DeleteParameters>
<asp:Parameter Name="伝票id" />
<asp:Parameter Name="行番号" />
</DeleteParameters>
<UpdateParameters>
<asp:Parameter Name="商品id" />
<asp:Parameter Name="注文数" />
<asp:Parameter Name="伝票id" />
<asp:Parameter Name="行番号" />
</UpdateParameters>
<InsertParameters>
<asp:ControlParameter ControlID="DropDownList1" Name="伝票ID"
PropertyName="SelectedValue" />
<asp:Parameter Name="商品id" />
<asp:Parameter Name="注文数" />
</InsertParameters>
</asp:SqlDataSource>
<br />
-
> 結果をラベルに表示する方法なのですが、いまいちわからずこのよう
> に書いてみたのですが、エラーになってしまいました。どの行でエラーが出ているかと、エラーメッセージの内容ぐらいは書い
てくださいね。> この中身を見てみるとNothingとなっていて、きちんと値を取
> 得出来ていないようなのですが、どのようにしたら値を取得できるの
> かわかりませんでした。紹介したページで見てほしかったのは、金額を含む行全体のデータが入
っている DataRowView を取得し、それから金額データを取得する方法
だったのですが・・・ちいさんのコードでは、金額Label から値を取得ようにしていますが、
そこで[編集]ボタンをクリックするとどうなるでしょう? 例外が
スローされるはずです。以下のように修正して試してみてください。
(1) まず、先にレスしたように、ハンドラは2つ必要です。DataBound
イベントのハンドラを追加してください。(2) 追加した DataBound イベントのハンドラの中に ItemDataBound
イベントのハンドラから以下の2行を移動してください。Dim 総計 As Label = e.Item.FindControl("合計La")
総計.text = Ctype(sum, string)(3) ItemDataBound イベントのハンドラの中の If 文を以下のように変
更してください。If e.Item.ItemType = ListViewItemType.DataItem Then
(4) 紹介した「ListViewDataItem クラス」のページのコードを参考に、
DataRowView を取得し、その中から金額データを取得し、それを
sum に足しこんでいくようにしてください。(5) 型変換がうまくいかなかったら、Parse するなりキャストするなり
して適宜修正してください。- 回答としてマーク ちい 2010年5月12日 9:14
-
SurferOnWwwさんへ
返信ありがとうございました。
全く検討違いのことをしてしまいすみませんでした。
質問させてください。ListView.DataBoundのイベントの書き方がわからないのです。
イベント作るときはオブジェクトを選択し、イベントの種類を選択することで自分で書くのではなく、
自動的に書かれたものを使っていました。しかしListViewを選択してもDataBoundイベントが出てこなく、質問させて
いただいております。
ライブラリーを見て、ListViewのイベントとしてDataBoundがあること、サーバー コントロールがデータ ソースにバインドした後に発生するイベントではあることはわかりました。
ListViewのDataBoundイベントの具体的なコードを教えていただいてもよろしいでしょうか?
合計は教えていただいたサイトを参考に作成してみました。合計計算は出来ているようですが、DataRowViewの使い方はこのような形であっていますか?
*コードDim sum As Integer = 0
Protected Sub ListView1_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ListViewItemEventArgs)If e.Item.ItemType = ListViewItemType.DataItem Then
'ListVeiw1のitem objectを取得
Dim dataItem As ListViewDataItem = CType(e.Item, ListViewDataItem)
'DataitemのdataItemを取得する
Dim rowview As Data.DataRowView = CType(dataItem.DataItem, Data.DataRowView)
Dim title As String = rowview("金額").ToString()Dim goukei As Integer = CType(title, Integer)
sum += goukeiEnd If
End Sub- 編集済み ちい 2010年5月11日 8:35 作成したコードを追加します。
-
> 自動的に書かれたものを使っていました。しかしListViewを
> 選択してもDataBoundイベントが出てこなく、質問させてい
> ただいております。コード画面の上の方にドロップダウンリストが2つ並んでいると思いま
すが、左のドロップダウンリストからコントロールを選択し、右のドロ
ップダウンリストで該当するイベントをクリックしてやると、ハンドラ
のコードは自動生成されませんか?デザイン画面で見ても、プロパティウィンドウの中にありますけど。
DataBound の代わりに PreRender でも OK ですので、DataBound が見
つからなければ PreRender でやってみてください。どうしても分からなければ ASP.NET ListView Total あたりをキーワー
ドにググってみればサンプルコードが見つかると思います。> 合計は教えていただいたサイトを参考に作成してみました。合計計算
> は出来ているようですが、DataRowViewの使い方はこのよ
> うな形であっていますか?合計が正しく出ているならコードは間違っていないと思います。ただし、
たぶん、rowview("金額") は Integer 型にキャストして直接 sum に足
しこめるのではないかと思います。後は、DataBound イベント(または PreRender イベント)のハンドラ
で、Label.Text に結果を表示してやればいいはずです。 -
ちいさんに返信
> Dim sum As Integer = 0
値の不整合が生じるかもしれないので ListView.DataBinding イベントのハンドラにて
変数 sum の初期化を行ったほうが善いかと思います。
Private sum As Integer
Private Sub ListView1_DataBinding( _
ByVal sender As Object, _
ByVal e As System.EventArgs) Handles ListView1.DataBinding
sum = 0
End Sub
SurferOnWww さんに返信
> DataBound の代わりに PreRender でも OK ですので、DataBound が見つからなけれ
> ば PreRender でやってみてください。
ListView のデータとは関連がないポストバックを行った場合に ViewState からデータが復元さ
れて ItemDataBound イベントは発生せず PreRender イベントのみ発生することがある
ので、PreRender イベントを利用する場合はデータバインドが行われましたよフラグが必要
になるかもしれないですね。
Private CalledDataBinding As Boolean = False
Private Sub ListView1_DataBinding( _
ByVal sender As Object, _
ByVal e As System.EventArgs) Handles ListView1.DataBinding
CalledDataBinding = True
...
End Sub
Private Sub ListView1_PreRender( _
ByVal sender As Object, _
ByVal e As System.EventArgs) Handles ListView1.PreRender
If CalledDataBinding = True Then
ShowTotal()
End If
End Sub
Sub ShowTotal()
...
End Sub -
SurferOnWwwさんへ
返信ありがとうございました。
>コード画面の上の方にドロップダウンリストが2つ並んでいると思いま
>すが、左のドロップダウンリストからコントロールを選択し、右のドロ
>ップダウンリストで該当するイベントをクリックしてやると、ハンドラ
>のコードは自動生成されませんか?
イベントの中にDataBoundもPreRenderも表示されませんでした。
表示されたのはItemDeletingなどItemに関するイベントしか表示されませんでした。
>デザイン画面で見ても、プロパティウィンドウの中にありますけど。
デザイン画面のプロパティにはあったので、そこから自動生成できました。
>ただし、たぶん、rowview("金額") は Integer 型にキャストして直接 sum に足
>しこめるのではないかと思います。
おしゃっる通りに直接足しこむことが出来ました。
明確なやり方を教えていただけたので、無事実装することができました。
ありがとうございました。
以上の方法を使い作成したコードを載せておきます。★コード
'sumの初期化
Dim sum As IntegerProtected Sub ListView1_DataBinding(ByVal sender As Object, ByVal e As System.EventArgs) Handles ListView1.DataBinding
sum = 0
End Sub'総計計算処理
Protected Sub ListView1_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ListViewItemEventArgs)'itemTypeはDataItemか判定
If e.Item.ItemType = ListViewItemType.DataItem Then'ListVeiw1のitem objectを取得
Dim dataItem As ListViewDataItem = CType(e.Item, ListViewDataItem)
'DataitemのdataItemを取得する
Dim rowview As Data.DataRowView = CType(dataItem.DataItem, Data.DataRowView)
sum += CType(rowview("金額"), Integer)
End If
End Sub'総計表示処理(DataBound→サーバー コントロールがデータ ソースにバインドした後に発生する)
Protected Sub ListView1_DataBound(ByVal sender As Object, ByVal e As System.EventArgs)
Dim 総計 As Label = ListView1.FindControl("総計La")
総計.Text = CType(sum, String)
End Sub -
もりおさん>
> 値の不整合が生じるかもしれないので ListView.DataBinding イ
> ベントのハンドラにて変数 sum の初期化を行ったほうが善いか
> と思います。「値の不整合を生じる」ケースとしてはどのようなものがあり
ますでしょうか?> ListView のデータとは関連がないポストバックを行った場合に
> ViewState からデータが復元されて ItemDataBound イベントは
> 発生せず PreRender イベントのみ発生することがあるので、
> PreRender イベントを利用する場合はデータバインドが行われま
> したよフラグが必要になるかもしれないですね。そのとおりです。フラグで対応するぐらいなら DataBound イベン
トを使ってください。 -
ちいさん>
> イベントの中にDataBoundもPreRenderも表示されませんでした。
> 表示されたのはItemDeletingなどItemに関するイ
> ベントしか表示されませんでした。使っているのは何ですか? Visual Studio 2008 Professional な
ら間違いなく表示されてますけど。設定の違いでしょうか?> おしゃっる通りに直接足しこむことが出来ました。
今回の質問とは関係ないことで、今さらながらの話ですが、金額は
Integer でよいのかどうか(Decimal を使ってはどうか)検討され
たでしょうか? -
SurferOnWwwさんへ
返信ありがとうございました。
>使っているのは何ですか? Visual Studio 2008 Professional な
>ら間違いなく表示されてますけど。設定の違いでしょうか?
わたしが使っているのはVisual Web Developer 2008です。
設定の違いなのですかね?
でもプロパティにはあったのですけどね。>今回の質問とは関係ないことで、今さらながらの話ですが、金額は
>Integer でよいのかどうか(Decimal を使ってはどうか)検討され
>たでしょうか?まったく検討してはいなかったのですが、調べてみました。
Decimalを調べてみると
Decimal 値型は、多数の有効な整数桁と小数桁を必要とし、丸め誤差を使用しない財務計算に適しています。と書かれているので、今回は少数桁を必要としてないのでIntegerでいいのかと思っているのですが、Decimalのほうが良いのでしょうか? -
SurferOnWww さんに返信
>「値の不整合を生じる」ケースとしてはどのようなものがあり
> ますでしょうか?
インスタンス変数宣言時にセットする初期値を期待することで不整合が起こるケー
スとしては ListView.EnableViewState プロパティに False をセットして
Select, Delete, Edit いずれかのコマンドを実行する場合を想定します。
ListView の ViewState を無効にしてコマンドボタンを押下した場合、本来
ViewState からの値の復元が行われるタイミングでデータバインドが行われます。
そして、コマンド実行に伴うデータバインドが行われるので都合2回データバイ
ンドが行われます。
それに対してインスタンス変数への初期値のセットは Page のコンストラクタが
呼ばれる前の1回のみなので、ItemDataBound イベントでインスタンス変数への
足しこみを行うと、期待する合計値とは異なってしまう可能性があります。
もちろん、ちいさんの掲示されたコードでは ViewState は無効になっていませ
んし、ViewState を無効にする予定も無いのかもしれませんが、予防策としてデー
タバインドの度に、使用する変数を初期化した方が善いという考えです。 -
ちいさん>
> わたしが使っているのはVisual Web Developer 2008です。
Express Edition でしょうか。そのあたりに違いがあるのかもしれ
ません。その他言語の違い(自分は C# です)も影響するようです。
何にせよ、すでに解決しているようですし、これ以上原因を追究し
ても意味がなさそうなので、この話は終わりにしていいですね?> 今回は少数桁を必要としてないのでIntegerでいいのかと
> 思っているのですが、Decimalのほうが良いのでしょうか?個人的には金額は Decimal でと思っているのですが、それもケース
バイケースでしょうし、日本のピザ屋さん限定で、DB のテーブルの
定義で単価の型が int なら、いまさらコードのほうを Decimal に
変更する必要性は低そうです。でも、もし、DB のテーブルの定義で単価が decimal 型なら、コード
の方もそれに合わせておいてはいかがですか? (SELECT クエリで
decimal * int で得られた結果は、DataRowView から Decimal で取
得できるので、sum は Decimal として宣言し、rowview("金額") は
Decimal にキャストして sum に足し込むという意味です)。 -
もりおさん>
> 不整合が起こるケースとしては ListView.EnableViewState プロパ
> ティに False をセットして回答を有難うございました。そのようなケースでは必要な処置である
ことが理解できました。今回のようなケースで EnableViewState を False にするの自分とし
ては想定外でしたが、パフォーマンスの向上などのメリットがあるの
でしょうか? 予防策を講じるのはある程度納得できますが、False
にするような場合もその予防策が必要かが分かりません。- 編集済み SurferOnWww 2010年5月13日 14:58 宛先追記
-
SurferOnWww さんに返信
> 今回のようなケースで EnableViewState を False にするの自分とし
> ては想定外でしたが、パフォーマンスの向上などのメリットがあるの
> でしょうか?ListView の ViewState を無効にすることのメリットでしょうか。
ViewState は hidden コントロールとして出力されるので ViewState を無効に
することで転送量が減るなどですか?
そうであれば、以下の記事が参考になるかと思います。ASP.NET ビューステートの概要
http://msdn.microsoft.com/ja-jp/library/bb386448(VS.90).aspx> 予防策を講じるのはある程度納得できますが、False
> にするような場合もその予防策が必要かが分かりません。ListView の ViewState を無効にした場合に必要になる可能性があって予防した
方が善いということを私は言いたいのです。ViewState を無効にするかはわかり
ませんし、予防策が必要かどうかはわかりません。論理的に有り得るのであれば
事前に防御しておきましょうという意味で予防という言葉を使っています。予防
策をとることが必定であれば予防ではなく防止です。SurferOnWww さんの質問を読み取れているか少し自信がありません。違っている
ようでしたらお教えいただけると幸いです。 -
SurferOnWwwさんへ
返信ありがとうございます。
>個人的には金額は Decimal でと思っているのですが、それもケース
>バイケースでしょうし、日本のピザ屋さん限定で、DB のテーブルの
>定義で単価の型が int なら、いまさらコードのほうを Decimal に
>変更する必要性は低そうです。>でも、もし、DB のテーブルの定義で単価が decimal 型なら、コード
>の方もそれに合わせておいてはいかがですか? (SELECT クエリで
>decimal * int で得られた結果は、DataRowView から Decimal で取
>得できるので、sum は Decimal として宣言し、rowview("金額") は
>Decimal にキャストして sum に足し込むという意味です)。
金額はDecimalなのですか。今後の参考にさせていただいきたいと思います。
今回の場合ですと、DBテーブルの定義で単位をint型にしたので、
今回はintegerにキャストする方法でやりたいと思います。
色々ありがとうございました。 -
もりおさん>
返答いただき有難うございました。
> ListView の ViewState を無効にすることのメリットでしょうか。
> ViewState は hidden コントロールとして出力されるので ViewState
> を無効にすることで転送量が減るなどですか?レスが分かりにくかったようですみません。
ネットワークへの負荷もありますが、サーバへの負荷の方が気になる
ところです。今回のケースで、ViewState を無効にすると、ListView 内のボタンク
リックでデータバインドが2回起こります。そのうち1回は全く無駄
です。先のレスの質問は、ViewState を無効にすることによって、データバ
インド1回分の無駄を補う以上のメリットがあって、トータルでパフ
ォーマンスの向上を見込めるのでしょうか・・・という意味でした。
自分は、パフォーマンスの改善はない、というより逆に悪くなると思
っています。だから、2回データバインドが起こらないようにコーデ
ィングすべきであって、2回起こってもいいように DataBinding イベ
ントでゼロに初期化するのは本末転倒と思います。今回のケースに限らず、一般的にも(今回のケースもかなり一般的だ
と思います)ViewState を無効にしてメリットがあるケースはほとん
どないように思われます。MSDN ライブラリに、DB から取得したデータを表示する場合、ViewSate
のデータをコントロールにロードする時間を節約するため(DB のデー
タで上書きするので無駄)、EnableViewState プロパティを false に
することは有効と書いてありました。でも、それは今回ようなケースには当てはまらないと思います。
> ListView の ViewState を無効にした場合に必要になる可能性があっ
> て予防した方が善いということを私は言いたいのです。ViewState を
> 無効にするかはわかりませんし、予防策が必要かどうかはわかりませ
> ん。論理的に有り得るのであれば事前に防御しておきましょうという
> 意味で予防という言葉を使っています。予防策をとることが必定であ
> れば予防ではなく防止です。先の自分のレスの「その予防策が必要かが分かりません」というのは、
ViewState を無効にするなら、今回のように2回もデータバインドが
起こることがないケースに限られる・・・すなわち「予防策」が必要
にならないケースに限られるはずという意味です。それはさておいても、DataBinding イベントでゼロに初期化するという
「予防策」には賛成できません。理由は以下の通りです。少なくとも今回のケースでは、2回もデータバインドが起こらないよう
にする(すなわち ViewState を有効にしておく)のが正しい対応です
よね。もし、DataBinding イベントで初期化することを予防策として用いて
いると、今回のようなケースで ViewState を無効にすると問題が隠蔽
されてしまい、正しい対応が取られない恐れがあるのではいでしょうか。今回のケースに限らず、一般的にもそうだと思います。
ASP.NET は ViewState とポストバックがキモだと思っています。そ
れを使わないと、何らかの好ましくない副作用があるはずなので、普
通はそういうことはしない、やるなら事前に十分な検討・検証が必要
だと思っています。従って、特別な理由がない限り EnableViewState プロパティは true
(デフォルト)にしておくことを徹底し、「予防策」はとらないこと
が予防策だと思います。
自分の限られた経験では外しているところがあるかもしれません。そ
の場合はご指摘いただけると幸いです。長々と失礼しました。
-
SurferOnWww さんに返信
返信ありがとうございます。
ふんふん。SurferOnWww さんの考えていらっしゃることが遅まきながらわかりま
した。
ListView の ViewState は有効にするべきである。
ViewState が有効であれば1回のポストバックで2回データバインドが行われるこ
とはない。
2回データバインドが行われないので ListView.DataBinding イベントのタイミ
ングで変数を初期化する必要は無い。
それどころか ViewState が無効であることの確認が遅れるので
ListView.DataBinding のタイミングで変数の初期化はしない方が良い。
ということですか。
> 先のレスの質問は、ViewState を無効にすることによって、データバ
> インド1回分の無駄を補う以上のメリットがあって、トータルでパフ
> ォーマンスの向上を見込めるのでしょうか・・・という意味でした。
質問はまだ有効でしょうか。私の回答としては、そこまで考えていなかったので
わかりません。
> 少なくとも今回のケースでは、2回もデータバインドが起こらないよう
> にする(すなわち ViewState を有効にしておく)のが正しい対応です
> よね。
正しいの定義がわからないので正しいとは思いません。
正しい対応というのは何に憑拠するのでしょうか?
> 自分は、パフォーマンスの改善はない、というより逆に悪くなると思
> っています。だから、2回データバインドが起こらないようにコーデ
> ィングすべきであって、2回起こってもいいように DataBinding イベ
> ントでゼロに初期化するのは本末転倒と思います。
私は2回データバインドが行われる可能性が有ることの説明に例を挙げましたが
、その例を回避しても2回データバインドが行われる可能性が無いことの保証に
はならないです。いわゆる悪魔の証明と言われるものです。2回データバインド
が起こらないようにコーディングすべきというのは事実上難しいのではないかと
思います。 -
もりおさん>
どうも観点・論点が違うようで、話が噛み合っていないように思います。
自分の考えは、「ViewState を無効にすることによってトータルでパフォーマン
スの向上を見込めるのか?」という疑問に対して、答えが Yes なら ViewState
を無効にしてそれによって起こる問題に対応することも可、No なら当然デフォ
ルトのまま有効にしておくということに尽きます。それに対して、
> 私の回答としては、そこまで考えていなかったのでわかりません。
とのことですが、自分は「わからない」という状況でどうすべきかの議論はして
いません。わからないのであれば、ViewState 有効・無効の是非もわからないし、正しい対
応もわかりません。それで議論をしてもあまり意味はなさそうです。#もりおさんが、わからなくてもとりあえず無効にして試してみるのが自分のや
り方というなら、「そうですか、そういうのもアリでしょうね」と言って議論
は終わりです。あまり意味はなさそうというのはそういう理由です。> 2回データバインドが起こらないようにコーディングすべきというのは事実上
> 難しいのではないかと思います。たとえそうだとしても、自分ならば、2回データバインドを許してそれよって起
こる問題の回避策をコーディングするようなことはしませんし(必要最低限のデ
ータバインドですむように修正する方を選びます)、まして「予防策」として最
初から含めておくようなことはしません。それは上記の疑問に対する答えが No だと思っているからですが、このあたりも、
Yes or No が明確にならないと議論が噛み合わないところと思います。 -
SurferOnWww さんに返信
なんだか誤解を与えてしまったようで弁明させてください。
>>私の回答としては、そこまで考えていなかったのでわかりません。
>
>とのことですが、自分は「わからない」という状況でどうすべきかの議論はして
>いません。
今回のようなケースで EnableViewState を False にするの自分とし
ては想定外でしたが、パフォーマンスの向上などのメリットがあるの
でしょうか?
という SurferOnWww さんから私への質問があったので、質問時点での私の考え
を回答とすることで帰結することを想定していました。
延長線上に議論は考えていません。