ASP.NET 2.0のGridView
ASP.NET 2.0で追加されたGridViewだが、気に入らない点が二つあった。
- 編集と削除は出来るが新しいデータの挿入は出来ない。
- DataSourceが0件(Empty)のとき、コントロール自体が表示されない。
これに対して、以下の機能を追加した。
- Footerを使って新しいデータを挿入できるようにした。
- EmptyTemplateを使って、データ0件の時は新規データの挿入だけ出来るようにした。
実装のポイント
- FooterTemplateを使ってGridViewの下部にInsert用入力欄を追加した。
- FooterTemplateを使うことでデフォルトのasp:BoundFieldが使えなくなった。
- 表示用にItemTemplateを使った。DataSourceを結びつけるのにEvalを使った。
- 編集用にEditItemTemplateを使った。DataSourceと結びつけるのにBindを使った。また、BindするためにはIDを付けないといけなかった。
- FooterTemplateを使った影響で、編集、削除、更新、キャンセルのボタンも自動で追加できなくなった。asp:ButtonのCommandNameにそれぞれEdit, Delete, Update, Cancelを指定してボタンを作成した。
- DataSourceのデータが0件(Empty)の時のために、EmptyDataTemplateを使ってデータ入力領域を作成した。
- Insert処理はGridViewと同じDataSourceのInsert機能を使った。
Default.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" Trace="false"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Untitled Page</title> </head> <body> <form id="form1" runat="server"> <div> <asp:GridView ID="GridView1" runat="server" AllowPaging="True" AutoGenerateColumns="False" CellPadding="4" DataKeyNames="column1" DataSourceID="SqlDataSource1" ForeColor="#333333" ShowFooter="True"> <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" /> <RowStyle BackColor="#EFF3FB" /> <Columns> <%-- 1列目:ボタン用 --%> <asp:TemplateField HeaderText=""> <ItemTemplate> <%-- 編集/削除ボタン --%> <asp:Button CommandName="Edit" Text="Edit" runat="server" /> <asp:Button CommandName="Delete" Text="Delete" runat="server" /> </ItemTemplate> <EditItemTemplate> <%-- 更新/キャンセルボタン --%> <asp:Button CommandName="Update" Text="Update" runat="server" /> <asp:Button CommandName="Cancel" Text="Cancel" runat="server" /> </EditItemTemplate> <FooterTemplate> <asp:Button ID="FooterInsert" runat="server" OnClick="Insert_Click" Text="Insert" /> </FooterTemplate> </asp:TemplateField> <%-- 2列目:Column1用 --%> <asp:TemplateField HeaderText="Column1"> <ItemTemplate> <asp:Label ID="column1" Text='<%# Eval("column1") %>' runat="server" /> </ItemTemplate> <EditItemTemplate> <%-- Column1はキーなのでEdit時もLabelのまま。Evalのままで良い。 --%> <asp:Label ID="column1" Text='<%# Eval("column1") %>' runat="server" /> </EditItemTemplate> <FooterTemplate> <asp:TextBox ID="TextBox1a" runat="server"></asp:TextBox> </FooterTemplate> </asp:TemplateField> <%-- 3列目:Column2用 --%> <asp:TemplateField HeaderText="Column2"> <ItemTemplate> <%-- 表示時はEvalでDataSourceと結びつける --%> <asp:Label Text='<%#Eval("column2") %>' runat="server" /> </ItemTemplate> <EditItemTemplate> <%-- 更新時はBindでDataSourceと結びつける。IDも必要。 --%> <asp:TextBox ID="column2" Text='<%# Bind("column2") %>' runat="server" /> </EditItemTemplate> <FooterTemplate> <asp:TextBox ID="TextBox2a" runat="server"></asp:TextBox> </FooterTemplate> </asp:TemplateField> <%-- 4列目:Column3用 --%> <asp:TemplateField HeaderText="Collumn3"> <ItemTemplate> <asp:Label Text='<%#Eval("column3") %>' runat="server" /> </ItemTemplate> <EditItemTemplate> <asp:TextBox ID="column3" Text='<%# Bind("column3") %>' runat="server" /> </EditItemTemplate> <FooterTemplate> <asp:TextBox ID="TextBox3a" runat="server"></asp:TextBox> </FooterTemplate> </asp:TemplateField> </Columns> <PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" /> <%-- データ0件の時 --%> <EmptyDataTemplate> <table cellspacing="0" cellpadding="4" rules="all" border="1" style="color:#333333;border-collapse:collapse;"> <tr style="color:White;background-color:#507CD1;font-weight:bold;"> <th></th> <th>Column1</th> <th>Column2</th> <th>Column3</th> </tr> <tr style="background-color:#EFF3FB;"> <td><asp:Button ID="EmptyInsert" runat="server" OnClick="Insert_Click" Text="Insert" /></td> <td><asp:TextBox ID="TextBox1" runat="server"></asp:TextBox></td> <td><asp:TextBox ID="TextBox2" runat="server"></asp:TextBox></td> <td><asp:TextBox ID="TextBox3" runat="server"></asp:TextBox></td> </tr> </table> </EmptyDataTemplate> <SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" /> <HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" /> <EditRowStyle BackColor="#D1DDF1" /> <AlternatingRowStyle BackColor="White" /> </asp:GridView> <%-- エラーメッセージ表示用 --%> <asp:Label ID="MsgBox1" runat="server" Text="Label"></asp:Label> <%-- データソース --%> <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConflictDetection="OverwriteChanges" ConnectionString="<%$ ConnectionStrings:mydbConnectionString %>" DeleteCommand="DELETE [Table1] WHERE [column1] = @original_column1" InsertCommand="INSERT INTO [Table1] ([column1], [column2], [column3]) VALUES (@column1, @column2, @column3)" SelectCommand="SELECT [column1], [column2], [column3] FROM [Table1]" UpdateCommand="UPDATE [Table1] SET [column2] = @column2, [column3] = @column3 WHERE [column1] = @original_column1"> <DeleteParameters> <%-- カラム名にoriginal_とPrefixが付くと更新前データを表すようだ。 Deleteの時はoriginal_column1にしか値がないので、間違えてwhere句にcolumn1を指定していたらdeleteが空振りした。 --%> <asp:Parameter Name="original_column1" Type="String" /> </DeleteParameters> <UpdateParameters> <asp:Parameter Name="original_column1" Type="String" /> <asp:Parameter Name="column2" Type="String" /> <asp:Parameter Name="column3" Type="String" /> </UpdateParameters> <InsertParameters> <asp:Parameter Name="column1" Type="String" /> <asp:Parameter Name="column2" Type="String" /> <asp:Parameter Name="column3" Type="String" /> </InsertParameters> </asp:SqlDataSource> </div> </form> </body> </html>
Default.aspx.cs
using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { //エラーメッセージをクリア MsgBox1.Text = ""; } protected void Insert_Click(object sender, EventArgs e) { Control cnt = ((Control)sender).Parent; string id = ((Control)sender).ID; string id1 = "TextBox1"; string id2 = "TextBox2"; string id3 = "TextBox3"; //Footerから呼ばれたときとEmptyDataTemplateから呼ばれたときの振り分け if (id.Equals("FooterInsert")) { id1 += "a"; id2 += "a"; id3 += "a"; } string key = ((TextBox)cnt.FindControl(id1)).Text.Trim(); if (key.Length == 0) { MsgBox1.Text = "column1は入力必須です。"; return; } SqlDataSource1.InsertParameters["Column1"].DefaultValue = key; SqlDataSource1.InsertParameters["Column2"].DefaultValue = ((TextBox)cnt.FindControl(id2)).Text; SqlDataSource1.InsertParameters["Column3"].DefaultValue = ((TextBox)cnt.FindControl(id3)).Text; try { SqlDataSource1.Insert(); } catch (System.Data.SqlClient.SqlException ex) { if (ex.Class == 14 && ex.Number == 2627) { MsgBox1.Text = "column1が重複しています。"; } else { throw; } } } }