Insert Row in GridView
אחד החסרונות של GridView הוא שאין תמיכה מובנית בהוספת שורות חדשות (קצת מצחיק שיש לו אופצייה של InsertItemTemplate אבל אין לו שום משמעות).
בפוסט הזה אני אדגים איך אפשר להוסיף לו פונקציונליות של הוספת שורה. (ניתן להוריד את דוגמת הקוד
מכאן)
אנחנו צריכים לחשוב של שני מצבים.
1. כשהטבלה שמקושרת לגריד יש בה כבר שורות.
2. כשהטבלה שמקשורת לגריד אין בה עדיין שורות.
נניח לטבלה שלנו יש שלוש עמודות, מספר שם וגיל. הנה קוד צד השרת שמקשר את הטבלה לגריד
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
BindGrid();
}
}
private void BindGrid()
{
if (Session["table"] == null)
{
DataTable table = new DataTable();
table.Columns.Add("Id");
table.Columns.Add("Name");
table.Columns.Add("Age");
Session["table"] = table;
}
gv.DataSource = Session["table"];
gv.DataBind();
}
קוד מאוד פשוט, בפעם הראשונה שנגיע לעמוד נפעיל את מתודת BindGrid
נוודא שאין ב - Ssesion את הטבלה, ניצור אותה.
נקשר את הגריד לטבלה.
כעת הגריד במצב שאין לו שום שורה מה שאומר שהגריד לא יוצג ב - html.
בשביל זה יש Template מיוחד שנקרא EmptyDataTemplate שבו נכניס מה שאנחנו רוצים שיראו בזמן שאין שורות בגריד.
אחרי שיהיו שורות אנחנו נשים את הפקדים עבור הוספת שורות בתחתית הגריד.
קוד ה - html:
<asp:GridView ID="gv" runat="server" AutoGenerateColumns="false" ShowFooter="true">
<EmptyDataTemplate>
<table>
<tr>
<th>
Id
</th>
<td>
<asp:TextBox ID="txtNewId" runat="server"></asp:TextBox>
</td>
<th>
Name
</th>
<td>
<asp:TextBox ID="txtNewName" runat="server"></asp:TextBox>
</td>
<th>
Age
</th>
<td>
<asp:TextBox ID="txtNewAge" runat="server"></asp:TextBox>
<asp:Button ID="btnInsert" runat="server" Text="Insert" OnClick="btnInsert_Click" />
</td>
</tr>
</table>
</EmptyDataTemplate>
<Columns>
<asp:TemplateField HeaderText="Id">
<ItemTemplate>
<%# Eval("Id") %>
</ItemTemplate>
<EditItemTemplate>
<%# Eval("Id") %>
</EditItemTemplate>
<FooterTemplate>
<asp:TextBox ID="txtNewId" runat="server"></asp:TextBox>
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Name">
<ItemTemplate>
<%# Eval("Name") %>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtEditName" runat="server" Text='<%# Eval("Name") %>'></asp:TextBox>
</EditItemTemplate>
<FooterTemplate>
<asp:TextBox ID="txtNewName" runat="server"></asp:TextBox>
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Age">
<ItemTemplate>
<%# Eval("Age") %>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtEditAge" runat="server" Text='<%# Eval("Age") %>'></asp:TextBox>
</EditItemTemplate>
<FooterTemplate>
<asp:TextBox ID="txtNewAge" runat="server"></asp:TextBox>
<asp:Button ID="btnInsert" runat="server" Text="Insert" OnClick="btnInsert_Click" />
</FooterTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
בהתחלה יש את ה - EmptyDataTemplate שמכיל שלושה תיבת טקסט ולחצן.
לאחר מכן יש את העמודות שלכל אחד מהם מוגדר ItemTemplate שיראו את התוכן של העמודה
EditItemTemplate עם תיבת טקסט שיוכלו לערוך את העמודה (אין בדוגמת הקוד כאן טיפול בעריכה)
FooterTemplate עם תיבת טקסט שיוכלו להוסיף שורה חדשה. (וכמובן בעמודה האחרונה יש לחצן Insert)
מה שנשאר כעת זה לראות את הקוד של btnInsert_click
protected void btnInsert_Click(object sender, EventArgs e)
{
Control currentRow;
if (gv.Rows.Count == 0)
{
currentRow = ((Control)sender).Parent;
}
else
{
currentRow = gv.FooterRow;
}
string id = ((TextBox)currentRow.FindControl("txtNewId")).Text;
string name = ((TextBox)currentRow.FindControl("txtNewName")).Text;
string age = ((TextBox)currentRow.FindControl("txtNewAge")).Text;
((DataTable)Session["table"]).Rows.Add(id, name, age);
BindGrid();
}
במידה ואין שורות זה אומר שצריך לקחת את הפקדים ממה שהוגדר ב - EmptyDataTemplate (לא מצאתי דרך יותר יפה מאשר לעשות casting ל - sender ואז לתפוס את ה - Parent - אשמח לשמוע על דרך הגיונית יותר)
במידה ויש שורות ניקח את ה - FooterRow
נשתמש ב - FindControl כדי למצוא את תיבות הטקסט.
נוסיף שורה לטבלה ב - Session.
ונקשר את הגריד מחדש.