[ASP.NET 控制項實作 Day30] 整合 jQuery ContextMenu plugin 的右鍵選單控制項

jQuery 是一個非常精簡強大的 JavaScript 函式庫,最近看到一個消息,未來微軟的 ASP.NET 也會全面支援 jQuery,詳見「 微軟將在 ASP.NET 相關產品中全面支援 jQuery」一文。筆者在之前就被 jQuery 簡短有力的程式語法所吸引,也把 jQuery 套用在伺服器控制項中,在本文將示範如何將 jQuery 的 ContextMenu plugin 封裝成伺服器控制項,使開發人員在使用上更為簡便。

jQuery 是一個非常精簡強大的 JavaScript 函式庫,最近看到一個消息,未來微軟的 ASP.NET 也會全面支援 jQuery,詳見「 微軟將在 ASP.NET 相關產品中全面支援 jQuery」一文。筆者在之前就被 jQuery 簡短有力的程式語法所吸引,也把 jQuery 套用在伺服器控制項中,在本文將示範如何將 jQuery 的 ContextMenu plugin 封裝成伺服器控制項,使開發人員在使用上更為簡便。

程式碼下載:ASP.NET Server Control - Day30.rar

 

一、jQuery ContextMenu plugin

ContextMenu plugin 是基於 jQuery 開發的右鍵選單插件,它只需要非常簡短的程式碼,就可以建立出相當美觀的右鍵選單,詳細說明請參閱以下網址。

http://www.trendskitchens.co.nz/jquery/contextmenu/

 

image

以上圖右鍵選單為例,我們看一下它的 HTML 原始碼及 JavaScript 程式碼。

HTML 原始碼

 


    <div class="contextMenu" id="myMenu1">
      <ul>
        <li id="open"><img src="folder.png" /> Open</li>
        <li id="email"><img src="email.png" /> Email</li>
        <li id="save"><img src="disk.png" /> Save</li>
        <li id="close"><img src="cross.png" /> Close</li>
      </ul>
    </div>

 

JavaScript 程式碼

 


   $('span.demo1').contextMenu('myMenu1', {

      bindings: {

        'open': function(t) {
          alert('Trigger was '+t.id+'\nAction was Open');
        },

        'email': function(t) {
          alert('Trigger was '+t.id+'\nAction was Email');
        },

        'save': function(t) {
          alert('Trigger was '+t.id+'\nAction was Save');
        },

        'delete': function(t) {
          alert('Trigger was '+t.id+'\nAction was Delete');
        }
      }
    });

 

 

二、實作 ContextMenu 控制項

接下來我們將開始實作,把 ContextMenu plugin 封裝為伺服器控制項,想辨法輸出所需的 HTML 原始碼及 JavaScript 程式碼。

step1. 定義選單項目集合類別

我們定義 TBMenuItem 類別來描述選單項目,TBMenuItemCollection 類別為選單項目集合。伺服器控制項會依這個選單項目的集合類別,來輸出 HTML 碼中 <ul> Tag 的內容。

image

 

step2. 實作 TBContextMenu 控制項

繼承 WebControl 命名為 TBContextMenu,因為這個控制項是沒有 UI,所以自訂控制項 Designer 來呈現設計階段的控制項外觀。

 


    ''' <summary>
    ''' 右選選單控制項。
    ''' </summary>
    < _
    Description("右選選單控制項"), _
    Designer(GetType(TBContextMenuDesigner)), _
    ToolboxData("<{0}:TBContextMenu runat=server></{0}:TBContextMenu>") _
    > _
    Public Class TBContextMenu
        Inherits WebControl

    End

 

TBContextMenuDesigner 只是單純顯示設計階段的控制項外觀。

 


    ''' <summary>
    ''' 擴充 TBContextMenu 控制項的設計模式行為。
    ''' </summary>
    Public Class TBContextMenuDesigner
        Inherits System.Web.UI.Design.ControlDesigner

        ''' <summary>
        ''' 用來在設計階段表示控制項的 HTML 標記。
        ''' </summary>
        Public Overrides Function GetDesignTimeHtml() As String
            Dim sHTML As String

            sHTML = MyBase.CreatePlaceHolderDesignTimeHtml()
            Return sHTML
        End Function

    End Class

 

image

 

step3. 覆寫 RenderContents 方法

覆寫 RenderContents 方法,依 Items 集合屬性定義的內容,來建立相關控制項,以便輸出符合的 HTML 碼。


        Protected Overrides Sub RenderContents(ByVal writer As System.Web.UI.HtmlTextWriter)
            Dim oItem As TBMenuItem
            Dim oULTag As HtmlControls.HtmlGenericControl
            Dim oLITag As HtmlControls.HtmlGenericControl
            Dim oImage As HtmlControls.HtmlImage

            Me.Controls.Clear()
            oULTag = New HtmlControls.HtmlGenericControl("ul")
            Me.Controls.Add(oULTag)

            For Each oItem In Me.Items
                oLITag = New HtmlControls.HtmlGenericControl("li")
                oULTag.Controls.Add(oLITag)
                oLITag.ID = oItem.Key

                oImage = New HtmlControls.HtmlImage()
                oLITag.Controls.Add(oImage)
                oImage.Src = Me.ResolveUrl(oItem.ImageUrl)

                oLITag.Controls.Add(New LiteralControl(oItem.Text))
            Next

            MyBase.RenderContents(writer)
        End Sub


step4. 覆寫 AddAttributesToRender 方法

因為選單預設是隱藏的,按下右鍵才會呈現,所以我們要覆寫 AddAttributesToRender 方法加上 style="display:none;"。


        Protected Overrides Sub AddAttributesToRender(ByVal writer As HtmlTextWriter)
            MyBase.AddAttributesToRender(writer)
            '預設為隱藏
            writer.AddStyleAttribute(HtmlTextWriterStyle.Display, "none")
        End Sub

 

step5. 覆寫 Render 方法

在 TBContextMenu 加入一個 ControlID 屬性,用來設定要呈現右鍵選單的目標控制項 ID。然後覆寫 Render 方法,來輸出相關的 JavaScript 程式碼。


        Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
            Dim oScript As StringBuilder
            Dim sScript As String
            Dim oItem As TBMenuItem
            Dim bFlag As Boolean
            Dim sClientID As String
            Dim oControl As Control

            oControl = WebFunc.FindControlEx(Me.Page, Me.ControlID)
            If oControl IsNot Nothing Then
                sClientID = oControl.ClientID
            Else
                sClientID = String.Empty
            End If

            oScript = New StringBuilder()
            oScript.AppendLine("$(document).ready(function() {")
            oScript.AppendLine("$('#" & sClientID & "').contextMenu('" & Me.ClientID & "',{")
            oScript.AppendLine("bindings: {")
            bFlag = False
            For Each oItem In Me.Items
                If StrIsNotEmpty(oItem.OnClientClick) Then
                    If bFlag Then
                        oScript.AppendLine(",")
                    End If
                    oScript.AppendLine("'" & oItem.Key & "': function(t) {")
                    oScript.AppendLine(oItem.OnClientClick)
                    oScript.AppendLine("}")
                    bFlag = True
                End If
            Next

            oScript.AppendLine("}")
            oScript.AppendLine("});")
            oScript.AppendLine("});")

            sScript = oScript.ToString
            Me.Page.ClientScript.RegisterStartupScript(Me.GetType, "menu", sScript, True)

            MyBase.Render(writer)
        End Sub

 

三、測試程式

接下來要測試 TBContextMenu  控制項,首先在 HTML 碼中加入引用相關的 jqeruy.js 及 jquery.contextmenu.js。

 


    <script type="text/javascript" src="js/jquery.js"></script>
    <script type="text/javascript" src="js/jquery.contextmenu.js"></script>

 

在頁面放置一個 Label 及一個  TBContextMenu  控制項,TBContextMenu 的 ControlID 設定為此 Label,即在該 Label 按右鍵會出現我們設定的右鍵選單。


        <asp:Label  class="demo"  ID="Label1" runat="server" 
            Text="RIGHT CLICK FOR DEMO (TBContextMenu)" Font-Bold="True"></asp:Label>
        <br />
        <bee:TBContextMenu ID="TBContextMenu1" runat="server" ControlID="Label1"  >
            <Items>
                <bee:TBMenuItem Key="open" Text="Open" ImageUrl="~/image/folder.png" OnClientClick="alert('open');"/>
                <bee:TBMenuItem Key="email" Text="Email" ImageUrl="~/image/email.png" OnClientClick="alert('email');" />
                <bee:TBMenuItem Key="save" Text="Save" ImageUrl="~/image/disk.png" OnClientClick="alert('save');" />
                <bee:TBMenuItem Key="delete" Text="Delete" ImageUrl="~/image/cross.png" OnClientClick="alert('delete');" />
            </Items>
        </bee:TBContextMenu>

執行程式,在 Label 上按右鍵就會出現我們在 TBContextMenu  控制項設定 Items 集合屬性的選單內容。

image

備註:本文同步發佈於「第一屆iT邦幫忙鐵人賽」,如果你覺得這篇文章對您有幫助,記得連上去推鑒此文增加人氣 ^^
http://ithelp.ithome.com.tw/question/10013501
http://ithelp.ithome.com.tw/question/10013503

ASP.NET 魔法學院