[ASP.NET & jQuery]tr(支援table、GridView與ListView)點選後highlight

  • 12229
  • 0
  • 2009-12-10

[ASP.NET & jQuery]tr(支援table、GridView與ListView)點選後highlight

前言

其實之前一直有類似的需求,就是GridView要能支援當click某一列的時候,該列要highlight,
點別列的時候,換別列highlight。

說穿了,就是table裡點選了某一筆tr,要套上highlight的css,點別列時要把原本那列CSS還原。
更簡單的作法,就是每次都先把highlight的css移除,再針對這次點的tr套上highlight。

如果需求只有這樣,css就可以搞定了。

然而使用jQuery,我們可以更輕鬆的處理網頁上的DOM。
 

Problem

問題來了,ASP.NET Webform裡的postback,沒錯!又是它…
因為每次postback都會重新Render,
要怎麼把這次client端的動作記起來?

又得用hidden來偷記東西了…

由於希望team member可以不用到處copy & paste,以前的作法都是直接做一個custom control繼承listview或gridview,
在物件本身把這件事做掉…

然而這次希望使用ASP.NET原生控制項…
所以我又得傷腦筋一下,怎麼樣可以做的更漂亮。
 

Solution

目前只是先生一版堪用的solution來使用,未來希望可以連hidden都動態產生,讓PGR使用時更加無感。

原本設計邏輯:

  1. 符合條件的table,裡面的tr,click的時候,先將此table裡所有tr的highlight class remove掉,接著再將click的這個tr加上highlight class
  2. click的同時,將click的這個tr的id,記到hidden裡面
  3. 每次符合條件的tr ready後,將hidden的那筆tr套上highlight class


結果,因為我這邊使用的是ListView,在LayoutTemplate裡面放個table。
但在ListView的Template裡面的Control,server端得用findcontrol才能定位,這樣太麻煩了…

所以,就不如直接搜尋ListView裡面的tr好了…

但是天不從人願,ListView Render出來後,是沒有一個DOM的id跟ListView的clientID一樣。
舉例來說:
<asp:ListView ID="lvSpec" runat="server" >裡
<table id="spec" runat="server" class="grid" cellpadding="0" cellspacing="0">

再套上MasterPage後,table的html ID是長的像這樣:
『ctl00_ContentPlaceHolder1_lvSpec_spec』

所以,我想要拿ListView.ClientID來當作jQuery Selector的容器和條件,就宣告失敗了。

後來決定使用div跟class,當在這個div裡面的table,所有tr就會被套上我們的邏輯。

為了方便team member開發上更加server化,
我這邊的範例就使用Panel來代替div,並且將那一堆javascript,透過BasePage的method,動態的註冊與使用。

 

Play it

BasePage的Method:

    /// ListView或table外,需要有一個panel包覆,在此panel內的tr被選取後,會套上"selected"的class,且將此tr的id塞到hidden裡
    /// postback後則讀取hidden的值,將該tr加上"selected"的class
    /// </summary>
    /// <param name="panel">The panel.</param>
    /// <param name="hidden">The hidden.</param>
    public void ListViewHiddenMapping(Panel panel, HiddenField hidden)
    {
        string CoverSelectedRowJS = @"
        function CoverSelectedRow(listViewID, hiddenID) {
            $('#' + listViewID + ' tr').ready(function() {
                var id = $('#' + hiddenID)[0].value;
                if (id != """") { $('#' + id).addClass(""selected""); }
            });
        }";


        string gridCoverBackSelectedJS = @"                
        $(document).ready(function() {
            $('#" + panel.ClientID + @" tr').click(function() {            
                $(this).parents(""table"").find(""tr"").removeClass(""selected"");
                $(this).toggleClass(""selected"", this.clicked);
                $('#" + hidden.ClientID+ @"')[0].value = $(this)[0].id;                
            });
        })";

         gridCoverBackSelectedJS = gridCoverBackSelectedJS+@" 
         CoverSelectedRow('" + panel.ClientID + "', '" + hidden.ClientID + "');";
        

        if (ExistSM())
        {            
            ScriptManager.RegisterClientScriptBlock(this.Page, this.Page.GetType(), panel.ID, gridCoverBackSelectedJS, true);
            ScriptManager.RegisterClientScriptBlock(this.Page, this.Page.GetType(), "CoverSelectedRowJS", CoverSelectedRowJS, true); 
        }
        else
        {
            
            Page.ClientScript.RegisterClientScriptBlock(Page.GetType(), panel.ID, gridCoverBackSelectedJS);
            Page.ClientScript.RegisterClientScriptBlock(Page.GetType(), "CoverSelectedRowJS", CoverSelectedRowJS); 
        }
    }

    /// <summary>
    /// 檢查頁面上是否存在ScriptManager
    /// </summary>
    /// <returns></returns>
    private bool ExistSM()
    {
        return (ScriptManager.GetCurrent(this.Page) != null);
    }

aspx上,要有三個東西才能達到我們需要的效果:

  1. <asp:Panel ID="divSpec" runat="server" CssClass="datatable">
  2. <asp:ListView>或<asp:GridView>或<asp:Table>或<table>
  3. <asp:HiddenField ID="HiddenField1" runat="server">


Panel要包住table,Panel的class設定為datatable。

接著要在code-behind使用BasePage的method:

沒了,就這樣一行,搞定。

畫面:

trHighLight

 

註:
如果切換頁要清除highlight,請自行在切換頁的事件,將hidden.value清空即可。

換句話說,如果切到別頁,再切回來如果還要留著highlight
就在tr ready的function裡面,額外加上頁碼的判斷,當id跟頁碼符合條件時,才套上highlight的class

如果啥都沒做,那就是現在選第二筆,切到第二頁,第二筆還保留著highlight。

 

 

結論

相信在很多大師眼中,這篇文章這個範例是相當可笑的,
因為用了jQuery,要處理postback花的功夫,真的沒啥意義…

不過沒法子,需求就是這樣,就當作練習,也希望對大家有幫助。


blog 與課程更新內容,請前往新站位置:http://tdd.best/