利用單一事件處理程序(Event Handler)來減少程式碼及提高...生產力吧


Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
'Code...
End Sub


  以上就是今天的主角「Event Handler」,Event Handler簡單說,就是將物件事件與事件處理程序做關連,以上例來說,我們的物件是「Button1」,物件事件是「Button1.Click」(最後的地方),事件處理程序是「Button1_Click()」。其中的重點其實在「Handles」身上,Handles
,注意看這個單子,有加「s」哦,也就是說,這個Event Handler本身不只可以處理單一個事件,也可以同事處理多個物件的事件。

  我舉個簡單的例子,我們在寫資料庫程式時,Select自為一組,Insert、Update、Delete這三個通常也自成一組,但我們一般的寫法就是:


'Insert Button
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
'Insert Code...
End Sub

'Update Button
Protected Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button2.Click
'Update Code...
End Sub

'Delete Button
Protected Sub Button3_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button3.Click
'Delete Code...
End Sub


  看起來沒什麼問題,執行起來也會很順暢。但其實這三個功能的程式,我們常常是寫在一起的,很少寫了Insert確不寫Update和Delete程式碼,所以我們接下來要簡化程式碼而且還可以集中管理的方便性。

  第一件事,我們要使三個Button都使用同一個Event Handler,所以我們將上面三段合成一段:


Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click, Button2.Click, Button3.Click
'Code...
End Sub


  注意最後「Handles Button1.Click, Button2.Click, Button3.Click」,將三個Button物件Click事件與Button1_Click做關連,也就是說Button1, Button2, Button3的Click都交給Button1_Click處理常式來處理。這樣設定之後,接下來的問題只有一個,就是說,我們要如何分辨「我是誰?Who am i?」

  因為現在三個Button都關連同一事件處理程序,如不能分辦是「誰」,那程式怎麼知道我們要處理Button1的Click程式碼還是Button2或Button3的Click程式碼?這個Who am i的遊戲解法有二。

方法一:使用Button的Command事件



  在你將Button物件拉進ASP.NET網頁後,請在屬性視窗找一個「CommandName」的屬性,這個屬性能讓我們為Button物件進行命令關聯,我們進行以下設定:

  Button1 → CommandName → 新增
  Button2 → CommandName → 修改
  Button3 → CommandName → 刪除

  經過CommandName的設定後,我們就能在Button1_Click進行以下的處理:


Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click, Button2.Click, Button3.Click
  'CommandName Sample Code...
  'CType將sender轉換型別為Button,然後取得CommandName的值來比較
If CType(sender, Button).CommandName = "新增" Then
'Insert Code
ElseIf CType(sender, Button).CommandName = "修改" Then
'Update Code
ElseIf CType(sender, Button).CommandName = "刪除" Then
'Delete Code
End If
End Sub


  這樣的程式碼有沒有比每一個Button單獨一個事件處理程序來的好。但這樣的步驟還是太麻煩,因為還需要先設定每一Button的CommandName,然後在程式中還再透過CType()來轉換型別後才能取得CommandName的值。其實還有更快更簡便的方法,就是直接使用Sender.Text屬性。

方法二:使用Sender.Text加Select Case

  *不用設定CommandName


Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click, Button2.Click, Button3.Click
  'Sender.Text Sample Code...
  'Sender.Text取得傳入Button物件的Text屬性值
Select Case sender.text
Case "新增"
'Insert Code
Case "修改"
'Update Code
Case "刪除"
'Delete Code
End Select
End Sub


  程式碼就這樣,沒了,簡單吧!我們直接對sender.text做Select Case動作,而sender.text是直接取得Button(1-3).Text的屬性值。這樣的程式碼連CommandName都不用設定,而是直接判斷Button(1-3).Text的屬性值,然後依Button(1-3).Text的不同撰寫處理程式。

  由以上範例我們可以看出,一是透過簡單共用事件處理程序,我們就可以減少不少的程式碼,二是集中管理相同目標、目的的程式碼。

範例:MultiView使用單一事件管理程序來切換View


  我們先在畫面上拉一個MultiView控制項,然後在MultiView控制項裡拉三個View控制項,三個View控制項裡各打上一些文字,

  MultiView
    → View1 → "This is View 1"
    → View2 → "This is View 2"
    → View3 → "This is View 3"

  然後在MultiView下方拉三個LinkButton控制項,LinkButton文字設定為View1、View2、View3,

  LinkButton1.Text = View1
  LinkButton2.Text = View2
  LinkButton3.Text = View3

  我們利用這三個LinkButton來切換MultiView裡的View。原始方法就是在每一個LinkButton的Click事件中寫程式。但我們既然學了好用的單一事件處理程序,讓我們來試試看:


Protected Sub lb1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles lb1.Click, lb2.Click, lb2.Click
'mv代表MultiView、lb代表LinkButton
'ActiveViewIndex用來設定所要顯示的View控制項,0代表第一個View…
Select Case sender.text
Case "View1"
mv.ActiveViewIndex = 0
Case "View2"
mv.ActiveViewIndex = 1
Case "View3"
mv.ActiveViewIndex = 2
End Select
End Sub


  這樣的Code看起來是不是很舒服,我們把有相同目的、相同目標的程式碼集中起來,也減少了許多頁面裡的Code,這樣不僅僅是對Coding人員有好處,對執行效率也會能有所提升。想想,如果一個大專案裡,共有100萬行程式碼,如果透這像這樣的小技巧,減為95萬行好了,能減少5%的程式確能執行一樣的效果。

  如果沒有感覺,一樣的工作1000萬行減為950萬行,你如果可以化身為Server,請選擇?

  ps. Windows 95作業系統有高達一千一百萬行程式。

7 則留言:

  1. 你好,請問C#要如何達到相同方式

    回覆刪除
  2. 方法一CommandName 或方法二 sender都可以呀,差異只有語法的不同,Try it, 如果寫不出來,Post your code in there.

    回覆刪除
  3. 問題如一樓,請問C#要如何達到相同方式
    我都找步道相關介紹

    回覆刪除
  4. Code變得乾淨,心情也舒服許多!!
    非常感謝KKBruce老師分享!!讓我學到Clean Code的一些方法

    另外樓上的兩位仁兄 若是像我一樣剛接觸.NET不久(個人用VB.NET語法)
    語法上不熟悉可以找網路上一些C#轉VB.NET 或 VB.NET轉C#的工具 (例如:http://converter.telerik.com/)
    在進行文章的練習

    回覆刪除
  5. 想問一個問題 如果按鍵有數百萬 Handles lb1.Click, lb2.Click, lb2.Click ...
    該如何簡化 先感謝大大們的分享

    回覆刪除
  6. 想請問一下 如果按鍵有幾百個做類似的事 Handles lb1.Click, lb2.Click, lb2.Click.... lb1000.Click
    該如何簡化,小弟一直想不到方法,先感謝大大們的分享

    回覆刪除
    回覆
    1. 一個 Handles 處理百個,我覺得太過分了點。
      應該先大類的整理好,再區分幾個 Handles 來匯整。

      刪除

感謝您的留言,如果我的文章你喜歡或對你有幫助,按個「讚」或「分享」它,我會很高興的。