目前沒想到什麼應用範例,所以學習一下MSDN現有的範本改寫一下,範本實作的是,把GridView的資料列「加入到ListBox」或「從ListBox移除」
◎以上程式範例AspNet45.aspx,如在頁框下不能操作,請開新視窗操作
◎如果有問題歡迎您提出,dnowba很需要有人和我一起討論
畫面設定:
加入一個GridView,完成和資料庫的資料繫結(要啟用進階功能)。
編輯資料行→加入TemplateField,.NET自動幫你在HTML上寫好<asp:TemplateField></asp:TemplateField>標記。(所以你對「按按按」很反感的話,也可以直接在GridView裡寫<asp:TemplateField></asp:TemplateField>的標記。不過在一般情況下不可以自已加特殊名稱的標記,比如把上面改成<asp:myField></asp:myField>,會顯示「未知的伺服器標記」的錯誤。反正GridView裡的東西是被包裝再包裝的,用的關鍵字就是不能亂改,不然都會發生識別錯誤。
再來在樣板的ItemTemplate加入二個按鈕,一個Button控制項作加入的功能,一個ListBox控制項作移除的功能
重點在這邊,設定Button按鈕的CommandName="Add" , CommandArgument="<%# Container.DataItemIndex %>"
LinkButton也是類似的設定,CommandName="Delete" , CommandArgument="<%# Container.DataItemIndex %>
CommandArgument="<%# Container.DataItemIndex %>若要用中文解釋的話,就是設定CommandArgument屬性和資料行索引(Container.DataItemIndex)繫結。這樣按鈕按下就可以透過 CommandArgument 間接得知我們按的是哪一資料列的按鈕。
這邊放二個不同的按鈕,目的只是要告訴大家…Button、LinkButton、ImageButton都有CommandName和CommandArgument 可以設定。
程式碼:
Protected Sub GridView1_RowCommand(sender As Object, e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles GridView1.RowCommand If e.CommandName = "Add" Then ' 設計一個add_item物件,屬性繼承ListItem,方便使用 Dim add_item As New ListItem() ' 設定add_item的文字=GridView裡被點選的某個資料料的第三個欄位 add_item.Text = Me.GridView1.Rows(CInt(e.CommandArgument)).Cells(2).Text ' 如果ListBox上不包含add_item這個項目的的話 If Not Me.ListBox1.Items.Contains(add_item) Then '把add_item加入到ListBox裡 Me.ListBox1.Items.Add(add_item) End If End If If e.CommandName = "Delete" Then Dim remove_item As New ListItem() remove_item.Text = Me.GridView1.Rows(CInt(e.CommandArgument)).Cells(2).Text If ListBox1.Items.Contains(remove_item) Then Me.ListBox1.Items.Remove(remove_item) End If End If '以上改寫自MSDN範例 'http://msdn.microsoft.com/zh-tw/library/system.web.ui.webcontrols.gridview.rowcommand.aspx 'If e.CommandName = "Add" Then ' Dim index As Integer = Convert.ToInt32(e.CommandArgument) ' Dim row As GridViewRow = Me.GridView1.Rows(index) ' Dim item As New ListItem() ' item.Text = Server.HtmlDecode(row.Cells(2).Text) & " " & _ ' Server.HtmlDecode(row.Cells(3).Text) ' If Not Me.ListBox1.Items.Contains(item) Then ' Me.ListBox1.Items.Add(item) ' End If 'End If End Sub Protected Sub GridView1_RowDeleting(sender As Object, e As System.Web.UI.WebControls.GridViewDeleteEventArgs) Handles GridView1.RowDeleting If Me.GridView1.Rows(e.RowIndex).Cells(1).Text <> " " Then e.Cancel = True Me.Label1.Text = "大膽,你用了.NET 在CommandName預設的保留字…直呼名諱的結果就是滿門抄斬,還好我擋住了,不然資料列就被你砍掉了。" End If End Sub
程式碼解釋:
◎ 只要是GridView裡頭的按鈕都可以 引發RowCommand 事件。我們可以把程式範例中對CommandName的判斷句拿掉 (行2),這樣,不管是點選哪個按鈕都會啟動事件。換句話說,CommandName在這裡的功能就是一種辨識的作用。當然你也可以用別的方式識別,比如說用Button.Text。
◎ 行18 Dim remove_item As New ListItem(),定義為ListItem而不用ListBox當繼承的容器,這樣的話,不只是ListBox適用這個方式,像DropDownList、CheckBoxList都可以用。
◎行38-43,這是重點,因為我們在設計「移除」功能時用了 .NET 在 CommandName 的內建字「Delete」,所以當按下按鈕時,網頁會邊進行我們給的RowCommand事件處理常式,一邊引發RowDeleting事件按照 .NET 的設計去做資料列刪除的動作,為了讓範例在部落格上存活,我就在RowDeleting 裡取消刪除。大家實作時可以把這段刪掉試試看動用CommandName 的內建字的下場是什麼。而Button1的CommandName「Add」其實也是保留字,但它是作用在DetailsView身上的,所以這邊拿來用是沒關係的。
從MSDN提供的範例來看,我想RowCommand事件在GridView進行刪除、新增資料時…應該多多少少有一些關聯。
例如:GridView整個刪除的流程是:
按一下GridView的刪除按鈕 → (GridView的RowDeleting 事件) →刪除資料列 → (GridView的RowDeleted事件)。
前一篇文章 GridView中和「刪除」事件有關的事件常式 已經交待了在 RowDeleting 事件與RowDeleted事件中,利用二個重要的參數來撰寫常式。
這篇文章的重點就放在 按GridView的刪除按鈕→刪除資料列,控制項和資料庫是如何完成聯繫並達成工作的。
我們在頁面上加入GridView控制項,並繫結資料,整個都是交給ADO.NET來自動生成。當完成資料的綁定,HTML 碼上其實就幫我們寫好了和資料庫繫結的要項了。如圖,紅色的框線是與資料庫連結的資料,底下有DeleteCommand、InsertComman、SelectCommand、UpdateCommand,後面接寫的是資料庫使用的陳述式。
在browser端,當GridView的某個按鈕按下去的時候,要怎麼讓系統知道現在按的是要呼叫資料庫的Delete 陳述式還是Update陳述式呢?這就要使用Button的CommandName和CommandArgument屬性了,如果有興趣請看
活用Button 控制項:CommandName、CommandArgument屬性介紹
但判別哪個CommandName用哪個CommandArgument 的判斷程式要寫在哪?我想「應該」就是寫在RowCommand事件的處理常式底下。
上面只是個臆測,從使用Button控制項得來的經驗來推測,但是只能說是猜測,因為我們在ADO.NET幫我們和資料庫聯繫完畢後,ASP.NET底下的RowCommand事件下也沒有自已生成像 if CommandName = “Update” then CommandArgumet 的常式。不過也不是子虛烏有,在MSDN裡的GridView.RowCommand 事件寫著
按一下 GridView 控制項中的按鈕時,會引發 RowCommand 事件。 這可讓您在每次發生這個事件時,提供執行自訂常式的事件處理方法。GridView 控制項內的按鈕也可以叫用此控制項的某些內建功能。 若要執行這些作業的其中一個,請將按鈕的 CommandName 屬性設為「Cancel / Delete / Edit / Page / Select / Sort / Update」其中一個值。
所謂的內建功能,就是那幾個Command的值,我們在使用CommandField 的編輯按鈕、刪除按鈕…時,可以把這個欄位轉成TemplateField,然後去看看這些按鈕原來的樣子 (註:不轉成樣板的話看不到)
前面提到,不把CommandField轉成TemplateField是看不到的CommandName的
在GridView上「編輯資料行」中,加入CommandField (或是CommandField下的子項目),右側的屬性也是針對整個欄位(Field)提供外觀、行為…等設定。
在GridView的HTML上也只會呈現CommandField,標記裡找不到CommandName的蹤跡。
只有把欄位轉成Template 的時候,才能讓這些Button原形畢露,Button標記下也才可以看得到CommandName
由MSDN的資料、以及從實作GridView、ListView等控制項得來的心得看來,當使用者按下編輯的按鈕,系統會由RowCommand去分析是哪一個資料列引發,(分析的依據是???又是sender這個物件吧 ) ,然後透過CommandName來判斷是要執行什麼動作,因為編輯按鈕的CommandName 是 Edit,所以會觸發GridView的RowEditing事件,進入編輯模式。
進入編輯模式後,如果使用者按下更新按鈕,因為CommandName是Update,就去執行SqlDataSource的UpdateCommand…
以上還是推論(我還是看不到ASP.NET怎麼完成這個工作的),不過至少我們可以應用像RowCommand這樣的事件,去設計一個像內建Command按鈕的處理常式。不過使用的時候,我們就要避免去使用系統內建的關鍵字。
以下整理一下這些大型控制項的CommandName
參考資料:
GridView的 RowCommand 事件、ListView的ItemCommand 事件、FormView的ItemCommand 事件、DetailsView的ItemCommand 事件
整理完畢後,其實可以發現GridView和其他控制項的最大差異,就是GridView是以資料列(ROW)方式來呈現的,所以像在辨別CommandName時,也需要考慮是哪一「列」觸發的,不像其他控制項,只要管好一個資料項「Item」就好了,而GridView也是ASP.NET控制項裡提供功能比較複雜的,學習完GridView的事件後 (尤其熟悉每個事件可以使用的二大參數),後面再去學其他的控制項就容易理解許多。
沒有留言:
張貼留言