2014年3月18日 星期二

[ASP.NET]如何知道目前按下的按鈕是哪一個?

常常我們在網頁中都需要按下按鈕來執行某些動作

ASP.NET也有提供Button、ImageButton、LinkButton三種按鈕

這三種控制項都是按鈕

只是長的不太一樣而已

假設現在有一種情況是三個按鈕都會觸發同一種方法時

那麼我們要怎麼知道目前的使用者按下去的是哪一個?

一般的作法是這樣

網頁部份我們會設定一個OnClick去呼叫這個方法
<asp:Button ID="Button1" runat="server" OnClick="CallMe_Click" Text="Button" />
CodeBehind的部份這樣寫
protected void CallMe_Click(object sender, EventArgs e)

在這邊特別提一下

當觸發OnClick的時候

他會傳入本身物件跟觸發事件給CallMe_Click

重點在object sender

你用Button btn=sender as Button就能取得觸發這個方法的Button object

這個方法以前在VB也有看過

不過一直不知道可以這樣用

後來看了MIS2000的書才知道還有這招

後來我遇到不同類型的按鈕也理所當然就想用這招解決

當然你不會知道目前是哪個按鈕被按下

所以取得sender自然要轉型成正確型態才能使用他

不然他對C#來講就是個object

你也只能用object才有的東西

所以我是這樣寫的

var btn = (sender.GetType().Name == "LinkButton") ? sender as LinkButton : sender as Button;

但一直有型態錯誤的訊息

後來上網問人才知道原來?:運算子的:左右兩邊的結果強制規定不能不同型態

又學到一個觀念!

而且就算是用if來做還是不行

LinkButton、Button也沒有父子類別的關係不能互轉

後來人家有提供一個方法就是用OnCommand

OnCommand根據MSDN的定義只要頁面上的任何按鍵按下都會觸發此方法

重點在於OnCommand提供的引數

protected void CallMe_Click(object sender, CommandEventArgs e)

其中的CommandEventArgs e它代表著包含資料的相關Command事件

他包含著Button本身的一些訊息像是CommandArgument或是CommandName之類的屬性

所以我們可以將一些訊息寫進CommandArgument中就可以用來判斷目前你按的按鍵要傳什麼訊息進來了

<asp:Button ID="Button1" runat="server" OnCommand="CallMe_Click" Text="Button1" CommandArgument="Button1" />
<asp:Button ID="Button2" runat="server" OnCommand="CallMe_Click" Text="Button2" CommandArgument="Button2" /><br />
<br />
<asp:ImageButton ID="ImageButton1" runat="server" OnCommand="CallMe_Click" CommandArgument="ImageButton1" />
<asp:ImageButton ID="ImageButton2" runat="server" OnCommand="CallMe_Click" CommandArgument="ImageButton2" />
<br />
<br />
<asp:LinkButton ID="LinkButton1" runat="server" OnCommand="CallMe_Click" CommandArgument="LinkButton1" >LinkButton1</asp:LinkButton>
<asp:LinkButton ID="LinkButton2" runat="server" OnCommand="CallMe_Click" CommandArgument="LinkButton2">LinkButton2</asp:LinkButton>

protected void CallMe_Click(object sender, CommandEventArgs e)
{
    Response.Write("<script>alert('你按下的是" + e.CommandArgument.ToString() + "');</script>");
}



問題是解決了不過還是有個小小的缺憾

沒想到不能直接用sender來轉型取得按下按鈕的物件

不過後來網路上的AllenKuo提供了一個方法

因為Button、LinkButton跟ImageButton都會implement IButtonControl這個interface

而CommandArgument、CommandName、PostBackUrl、Command()、Click()這些屬性跟方法也是從IButtonControl來的

所以我們可以把sender轉型成IButtonControl型態

解法如下

protected void CallMe_Click(object sender, CommandEventArgs e)
{
    var btn = sender as IButtonControl;
    Response.Write("<script>alert('你按下的是" + btn.CommandArgument+ "');</script>");
}

如此就能使用共同的界面來呼叫不同的屬性跟方法了

非常漂亮的解法!

沒有留言:

張貼留言