﻿# 利用 ASP.NET 2.0 的 Control Adapter 架構實做「刪除」按鈕

在設計管理介面時，一定會做「刪除」功能，我想很多人都會在「刪除」按鈕加上一個 JavaScript 確認的程式，以確保使用者沒有誤觸刪除按鈕而導致資料直接被刪除。

對一個普通的按鈕來說，要加上「刪除確認」的程式是很容易的，只要在 Button 控制項的 OnClientClick 屬性加上 confirm() 函數就可以做倒刪除確認的功能：

```
<asp:Button ID="mDelete_Button" runat="server" Text="刪除"
    OnClientClick="if(!confirm('你確定要刪除嗎?')) return false;"  />
```

而對於最常用需要用到刪除功能的地方不外乎是 GridView、DetailsView 或 FormView 控制項中，如果你要在這些控制項裡增加「刪除」功能是很容易的，一般來說會有兩種作法：

第一種：新增一個 CommandField 宣告，就可以新增一個刪除的按鈕：

```
<asp:CommandField ButtonType="Button" ShowDeleteButton="true"
    DeleteText="刪除" HeaderText="刪除" />
```

但是第一種作法很不容易加上 OnClientClick 屬性，以 GridView 控制項為例，真的要替 CommandField 的刪除按鈕加上 onclick 屬性必須實做 RowDataBound 事件，並在事件中找到這個 Button 控制項 ( 如果你 CommandField 中的 ButtonType 屬性設定為 Button 的話 )，再手動加入 onclick 屬性(Attribute)，這真是太麻煩了。

第二種：新增一個 TemplateField 宣告，並自己新增 Button 控制項進去，有經驗的人就知道只要將 CommandName 設定成 Delete 就可以讓這個按鈕跟使用 CommandField 的刪除功能一模一樣，其實 CommandField 輸出的控制項就是將 CommandName 設定為 Delete。如果要加上刪除確認功能，這時就不需要再寫 Code Behind 的程式了，直接在 \*.aspx 頁面的刪除按鈕加上 OnClientClick 屬性就好了，就如同本篇文章最上面的那個範例一樣。

```
<asp:TemplateField>
    <ItemTemplate>
        <asp:Button ID="mDelete_Button" runat="server" CommandName="Delete"            Text="刪除" OnClientClick="if(!confirm('你確定要刪除嗎?')) return false;" />
    </ItemTemplate>
</asp:TemplateField>
```

不過，我今天要講的技巧更厲害，是透過 ASP.NET 2.0 的 Control Adapter 機制，直接設定「全站」所有的 Button 控制項只要遇到 CommandName 為 Delete 的，就自動加上 OnClickClick 屬性進行刪除確認的功能。

首先，你必須在你的網站專案加上 App\_Browsers 目錄，並新增一個 ControlAdapters.browser 檔案 (檔名可以改，副檔名不能改)，並輸入以下內容：

```
<browsers>
  <browser refID="Default">
    <controlAdapters>
      <adapter controlType="System.Web.UI.WebControls.Button" adapterType="ButtonAdapter" />
      <adapter controlType="System.Web.UI.WebControls.LinkButton" adapterType="ButtonAdapter" />
      <adapter controlType="System.Web.UI.WebControls.ImageButton" adapterType="ButtonAdapter" />
    </controlAdapters>
  </browser>
</browsers>
```

這裡我定義了 3 個不同的按鈕控制項配置器(Control Adapter)，並且都指定到 ButtonAdapter 類別。

然後再到 App\_Code 目錄下新增一個  ButtonAdapter.cs 類別檔，程式也很短，如下：

```
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
public class ButtonAdapter : System.Web.UI.WebControls.Adapters.WebControlAdapter {
    protected override void OnPreRender(EventArgs e)    {
       IButtonControl btn = Control as IButtonControl;
       // mDelete 是我自訂的 CommandName 名稱，你也可以改成你自己的名稱
        if (btn.CommandName == "Delete" || btn.CommandName == "mDelete") {
           Control.Attributes["onclick"] = "if(!confirm('你確定要刪除嗎？')) return false;";
       }
       base.OnPreRender(e);
    }
}
```

這樣就做完了！

整個網站完全不需要再特別定義 **OnClientClick="if(!confirm('你確定要刪除嗎?')) return false;"** 指令，只要你的 CommandName 設定成 Delete 或 mDelete 都會自動加上 onclick 屬性，是不是一勞永逸呢！^\_^

ASP.NET 2.0 的 Control Adapter 架構是我非常喜歡的一個架構，他可以針對不同的 Browser 以及針對不同的控制項進行客製化的修正，也可以用在像我今天講的這個開發技巧上，真的可以將程式碼的量降低，也降低專案的複雜度。

如果有興趣瞭解 Control Adapter 架構的人可以下載 [ASP.NET 2.0 CSS Friendly Control Adapters 1.0](http://www.asp.net/cssadapters/) 範例回來好好研究一下，相信會有更多的創意出現，記得回來跟我分享喔。:-)

**相關連結**

-   [Extreme ASP.NET - Control Adapters](http://msdn2.microsoft.com/en-us/magazine/cc163543.aspx)
-   [ASP.NET 2.0 Control Adapter Architecture](https://weblogs.asp.net/scottgu/433692)
-   [Architecture Overview of Adapters](http://msdn2.microsoft.com/en-us/library/67276kc5.aspx)
-   [Browser Definition Files](http://msdn2.microsoft.com/en-us/library/ms228122.aspx)
-   [Sample code to a simple adapter in the ASP.NET 2.0 QuickStarts](http://www.asp.net/QuickStart/aspnet/doc/extensibility.aspx#A)
-   [CSS Control Adapter Toolkit for ASP.NET 2.0](https://weblogs.asp.net/scottgu/444850)
-   [CSS Control Adapter Toolkit Update](https://weblogs.asp.net/scottgu/css-control-adapter-toolkit-update)
-   [Using a Control Adapter to Properly Display PNG Images in IE](http://www.codeproject.com/KB/web-image/IePngControlAdapter.aspx)
