(原創)代碼分析-DataGrid實現增刪(帶提示)改和分頁

 


或許大家會說,網上已經很多類似文章了,包括孟子的,爲什麼要再寫一次?
我想我們不僅僅要會實現,更多的是需要理解。
下面先帖出代碼,再分析一下其中的一些關鍵代碼。
數據庫表名:tb1,其中有3個字段,分別是ID自增的主鍵、vName varchar(50)、iAge int
(以下代碼沒有做任何錯誤捕獲處理)

前臺

<%@ Page language="c#" Codebehind="WebForm5.aspx.cs" AutoEventWireup="false" Inherits="csdn.WebForm5" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
   
<HEAD>
       
<title>WebForm5</title>
       
<meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR">
       
<meta content="C#" name="CODE_LANGUAGE">
       
<meta content="JavaScript" name="vs_defaultClientScript">
       
<meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
   
</HEAD>
   
<body>
       
<form id="Form1" method="post" runat="server">
           
<asp:textbox id="TextBox1" runat="server" Width="88px"></asp:textbox>
           
<asp:TextBox id="TextBox2" runat="server" Width="40px"></asp:TextBox>
           
<asp:Button id="Button1" runat="server" Text="添加"></asp:Button>
           
<asp:datagrid id="DataGrid1" runat="server" AutoGenerateColumns="False" DataKeyField="ID" AllowPaging="True"
                PageSize
="5" OnEditCommand="edit" OnCancelCommand="cancel" OnUpdateCommand="update">
               
<Columns>
                   
<asp:TemplateColumn HeaderText="姓名">
                       
<ItemTemplate>
                           
<%# DataBinder.Eval(Container.DataItem,"vName") %>
                       
</ItemTemplate>
                       
<EditItemTemplate>
                           
<asp:TextBox id="name" Runat="server" Text='<%# DataBinder.Eval(Container.DataItem,"vName") %>' Width="88px">
                           
</asp:TextBox>

                       
</EditItemTemplate>
                   
</asp:TemplateColumn>
                   
<asp:TemplateColumn HeaderText="年齡">
                       
<ItemTemplate>
                           
<%# DataBinder.Eval(Container.DataItem,"iAge") %>
                       
</ItemTemplate>
                       
<EditItemTemplate>
                           
<asp:TextBox id="age" Runat="server" Text='<%# DataBinder.Eval(Container.DataItem,"iAge") %>' Width="40px">
                           
</asp:TextBox>

                       
</EditItemTemplate>
                   
</asp:TemplateColumn>
                   
<asp:EditCommandColumn UpdateText="更新" CancelText="取消" EditText="編輯"></asp:EditCommandColumn>
                   
<asp:ButtonColumn Text="刪除" CommandName="del"></asp:ButtonColumn>
               
</Columns>
               
<PagerStyle Mode="NumericPages"></PagerStyle>
           
</asp:datagrid></form>
   
</body>
</HTML>

後臺

  using System;
using
System.Collections;
using
System.ComponentModel;
using
System.Data;
using
System.Data.SqlClient;
using
System.Drawing;
using
System.Web;
using
System.Web.SessionState;
using
System.Web.UI;
using
System.Web.UI.WebControls;
using
System.Web.UI.HtmlControls;
namespace
csdn
{
   
/// <summary>
   
/// WebForm5 的摘要說明。
   
/// </summary>

    public class WebForm5 : System.Web.UI.Page
   
{
       
protected
System.Web.UI.WebControls.TextBox TextBox1;
       
protected
System.Web.UI.WebControls.TextBox TextBox2;
       
protected
System.Web.UI.WebControls.Button Button1;
       
protected
System.Web.UI.WebControls.DataGrid DataGrid1;
   
       
private void Page_Load(object
sender, System.EventArgs e)
       
{
           
// 在此處放置用戶代碼以初始化頁面

            if(!IsPostBack)
           
{
                SetBind();
            }

        }


       
protected void SetBind()
       
{
            SqlConnection conn
=new SqlConnection(System.Configuration.ConfigurationSettings.AppSettings["conn"
]);
            SqlDataAdapter da
=new SqlDataAdapter("select * from tb1"
,conn);
            DataSet ds
=new
DataSet();
            da.Fill(ds,
"table1"
);
           
this.DataGrid1.DataSource=ds.Tables["table1"
];
           
this
.DataGrid1.DataBind();
        }


       
Web 窗體設計器生成的代碼

       
private void Button1_Click(object sender, System.EventArgs e)
       
{
            SqlConnection conn
=new SqlConnection(System.Configuration.ConfigurationSettings.AppSettings["conn"
]);
            SqlCommand comm
=new SqlCommand("insert into tb1 (vName,iAge) values (@vName,@iAge)"
,conn);
            SqlParameter parm1
=new SqlParameter("@vName",SqlDbType.NVarChar,50
);
            parm1.Value
=this
.TextBox1.Text;
            SqlParameter parm2
=new SqlParameter("@iAge"
,SqlDbType.Int);
            parm2.Value
=this
.TextBox2.Text;
            comm.Parameters.Add(parm1);
            comm.Parameters.Add(parm2);
            conn.Open();
            comm.ExecuteNonQuery();
            conn.Close();
            SetBind();
        }


       
private void DataGrid1_ItemCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
       
{
           
if(e.CommandName=="del"
)
           
{
                SqlConnection conn
=new SqlConnection(System.Configuration.ConfigurationSettings.AppSettings["conn"
]);
                SqlCommand comm
=new SqlCommand("delete from tb1 where ID=@id"
,conn);
                SqlParameter parm1
=new SqlParameter("@id"
,SqlDbType.Int);
                parm1.Value
=this
.DataGrid1.DataKeys[e.Item.ItemIndex];
                comm.Parameters.Add(parm1);
                conn.Open();
                comm.ExecuteNonQuery();
                conn.Close();
                SetBind();
            }

        }


       
private void DataGrid1_PageIndexChanged(object source, System.Web.UI.WebControls.DataGridPageChangedEventArgs e)
       
{
           
this.DataGrid1.CurrentPageIndex=
e.NewPageIndex;
            SetBind();
        }


       
protected void edit(object sender,DataGridCommandEventArgs e)
       
{
           
this.DataGrid1.EditItemIndex=
e.Item.ItemIndex;
            SetBind();
        }


       
protected void cancel(object sender,DataGridCommandEventArgs e)
       
{
           
this.DataGrid1.EditItemIndex=-1
;
            SetBind();
        }


       
protected void update(object sender,DataGridCommandEventArgs e)
       
{
            SqlConnection conn
=new SqlConnection(System.Configuration.ConfigurationSettings.AppSettings["conn"
]);
            SqlCommand comm
=new SqlCommand("update tb1 set vName=@vName,iAge=@iAge where ID=@id"
,conn);
            SqlParameter parm1
=new SqlParameter("@vName",SqlDbType.NVarChar,50
);
            parm1.Value
=((TextBox)e.Item.FindControl("name"
)).Text;
            SqlParameter parm2
=new SqlParameter("@iAge"
,SqlDbType.Int);
            parm2.Value
=((TextBox)e.Item.FindControl("age"
)).Text;
            SqlParameter parm3
=new SqlParameter("@id"
,SqlDbType.Int);
            parm3.Value
=this
.DataGrid1.DataKeys[e.Item.ItemIndex];
            comm.Parameters.Add(parm1);
            comm.Parameters.Add(parm2);
            comm.Parameters.Add(parm3);
            conn.Open();
            comm.ExecuteNonQuery();
            conn.Close();
           
this.DataGrid1.EditItemIndex=-1
;
            SetBind();
        }


       
private void DataGrid1_ItemCreated(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e)
       
{
           
foreach(DataGridItem di in this
.DataGrid1.Items)
           
{
               
if(di.ItemType==ListItemType.Item||di.ItemType==ListItemType.AlternatingItem||di.ItemType==
ListItemType.EditItem)
               
{
                    ((LinkButton)di.Cells[
3].Controls[0]).Attributes.Add("onclick","return confirm('delete?');"
);
                }

            }

//一般不這麼寫,看下面說明第六點
        }

    }


(1)
大家可以看到SetBind()中的一些代碼,並沒有顯式的打開和關閉SqlConnection但是代碼確實是運作的,原因在於SqlDataAdqpter的Fill方法會自動打開或者關閉連接(當然它會先檢測是不是連接已經打開,如果已經打開的話不會重複打開導致出錯)。
(2)
再看一下Page_Load()中
if(!IsPostBack)
{
 SetBind();
}
很多初學者,不理解IsPostBack盲目的加或者不加這句話,其實加不加在於你的需求
IsPostBack爲真的時候表示網頁不是第一次加載也就是回傳的情況
只有在!IsPostBack爲真的時候用了SetBind();也就是綁定DataGrid的關鍵在於我們需要修改記錄,這往往是很多網友在修改記錄的時候發現向數據庫寫入的數據還是原來的TextBox中的內容。爲什麼會這樣呢?在修改的時候我們先按下“編輯”這個按鈕執行了protected void edit(object sender,DataGridCommandEventArgs e)裏面的代碼,在修改了TextBox中數據以後我們按下“更新”這個按鈕,這個時候也是一次PostBack如果沒有if(!IsPostBack)的話,其中的綁定代碼執行了一次,也就是對模板列中的TextBox進行了重新賦值,然後轉到
protected void update(object sender,DataGridCommandEventArgs e)中的代碼,你的代碼是執行的,但是((TextBox)e.Item.FindControl("name")).Text已經不是你修改的東西而是原來的東西了。
(3)
修改的代碼中
parm3.Value=this.DataGrid1.DataKeys[e.Item.ItemIndex]
對於e.Item.ItemIndex就是點擊的這個行(事件觸發的行)的行好,如果要用這個作爲主鍵來放進where子句update或者delete顯然是不合適的,比如你點擊的是第三行,數據庫內這個記錄的主鍵卻是20或者是字符,因此我們需要爲DataGrid指定一個DataKeyField(前臺代碼中)告訴它,我的表的主鍵就是這個字段,在綁定了以後DataGrid的DataKeys就存儲數據了列表控件中每個記錄的主鍵,所以取的時候用索引
this.DataGrid1.DataKeys[e.Item.ItemIndex]來取就可以得到主鍵
(4)
看一下private void DataGrid1_ItemCreated(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e)
中的一些代碼,首先ItemCreated這個事件是在當在DataGrid控件中創建項時在服務器上發生,這個時候還沒有綁定數據,所以如果在這個
ItemCreated中去取DataGrid中的值你是得不到的。
foreach(DataGridItem di in this.DataGrid1.Items)
{
if(di.ItemType==ListItemType.Item||di.ItemType==ListItemType.AlternatingItem||di.ItemType==ListItemType.EditItem)
{
((LinkButton)di.Cells[3].Controls[0]).Attributes.Add("onclick","return confirm('delete?');");//這裏的類型轉換爲LinkButton,在不指定ButtonColumn 的ButtonType的時候默認就是LinkButton,如果指定爲PushButton,這裏類型轉換應該寫Button而不是LinkButton否則會出錯
}
}
這段代碼爲所有的刪除按鈕增加客戶端的click事件,在循環所有的DataGrid1.Items的時候我們注意到,僅僅需要在ListItemType.Item和ListItemType.AlternatingItem中的第四列(Cells[3])中的第一個按鈕控件(Controls[0])上添加屬性,因爲在DataGrid的Header或者Footer中是找不到這個刪除按鈕的(雖然他們也是DataGrid1.Items)。設想一下如果不寫di.ItemType==ListItemType.EditItem會怎麼樣?結果就是在編輯的時候按刪除那個時候是沒有提示的,因爲沒有給編輯的行的按鈕加腳本。說到這裏想說一下對這個程序的改進,大家或許不想在編輯的時候允許刪除操作(也就是點擊了編輯按鈕卻沒有點擊取消或者更新按鈕的時候是不運行刪除操作),改進方法很簡單:把e.CommandName=="del"這個判斷改爲e.CommandName=="del"&&e.Item.ItemType!=ListItemType.EditItem,就可以達到這個目的了。
還有之所以在這裏沒有用((LinkButton)di.Cells[3].FindControl(刪除按鈕的id))來找到這個按鈕是因爲這個按鈕如果不寫是 <asp:ButtonColumn Text="刪除" CommandName="del"></asp:ButtonColumn>不能添加id的,如果這個按鈕是放在模板列中的,就可以有id了。
(5)
在編輯的時候
this.DataGrid1.EditItemIndex=e.Item.ItemIndex在取消編輯的時候this.DataGrid1.EditItemIndex=-1
當EditItemIndex!=-1的時候,DataGrid顯示的東西不再是ItemTemplate中的東西而是EditItemTemplate中的東西,所以在取消編輯的時候設定-1就可以了,同樣EditItemIndex和ItemIndex差不多是從0開始編號,表示的是編輯的這一行的索引號。
(6)
foreach(DataGridItem di in this.DataGrid1.Items)
            {
                if(di.ItemType==ListItemType.Item||di.ItemType==ListItemType.AlternatingItem||di.ItemType==ListItemType.EditItem)
                {
                    ((LinkButton)di.Cells[3].Controls[0]).Attributes.Add("onclick","return confirm('delete?');");
                }
            }
        }

這段代碼我爲了演示如果不對ItemType進行判斷會出錯,所以對DataGrid1.Items進行了循環讀取(可以通過調試看到當在設置了Footer以後DataGrid1.Items.Count>PageSize),一般情況下這麼寫就可以了
if(e.Item.ItemType==ListItemType.Item||e.Item.ItemType==ListItemType.AlternatingItem||e.Item.ItemType==ListItemType.EditItem)
    {
     ((LinkButton)e.Item.Cells[3].Controls[0]).Attributes.Add("onclick","return confirm('delete?');");
    }


暫時先說到這裏,以後繼續補充。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章