2014年2月15日 星期六

[ASP.NET]如何抓到頁面中不是ASP.NET控制項的HTML資料

最近碰到一個超奇怪的程式

裡面一堆奇奇怪怪的問題跟限制

這次遇到的其中一個問題是請你用現有的搜尋找出資料後

判斷資料欄位中是否全部都是"未繳款"的狀態

如果全部都是"未繳款"才可以刪除否則不給使用者刪

一開始想到的解法是用ADO.NET下SQL指令

select count(status) as count from bill where status!='0'

計算status不等於0的欄位有多少

如果不等於0就表示有其中一筆資料已繳款用這樣的方式做判斷

結果後來才知道禁止直接跟對方資料庫做連結

只能用現有的東西Orz

後來想到之前寫的人資料呈現在網頁上是用ListView

ListView可以直接帶出資料來

我直接抓網頁上的資料來判斷就行(題外話,為啥有人要用ListView做出一個很像GridView的東西,你直接用GridView不就好了......)

而在每筆資料進行databound時都會觸發ItemDataBound()這個方法

我就在這方法抓每筆資料裡面我要的資料就行

結果看他網頁原始檔發現他的資料並沒有指派給ASP.NET的控制項

一般如果是用ASP.NET幫你建起來的表單裡面每列資料大致上都會長的類似這樣

<asp:Label> ID="co_vidLabel" runat="server" Text='<%# Eval("co_vid") %>' />

Eval("co_vid")代表進行DataBind的資料庫欄位

另一種方式是Bind("co_vid")

前者是單向繫結後者是雙向繫結

就是前者只能讀後者如果你網頁上會觸發Edit的功能那麼該欄位除了讀也能寫

看到的網頁只有<td><%# Eval("co_vid") %></td>

並沒有像我上面寫的還有個<asp:Label>可以接住Eval("co_vid")的值

因為如果有ASP.NET的控制項那我只要用下面方法就可以抓到控制項的值

protected void ListView1_ItemDataBound(object sender, ListViewItemEventArgs e)
{
    //方法一 有asp.net控制項的抓法
    Label covid = e.Item.FindControl("co_vidLabel") as Label;
    if (covid != null)
    Response.Write(covid.Text + "<br>");
}

如果是用GridView也有類似的RowDataBound方法

以上方法行不通只能另想辦法了

一開始在網路上看到這個方法二抓取資料來源控制項的資料

但我試了之後...自己電腦上可以伺服器上行不通

這個程式一堆地方都是謎

更別說知道他資料是不是DataSet或DataTable來的

後來翻到其他程式突然看到某個寫法

ListViewItem item = e.Item;
HtmlTableCell td = item.FindControl("tdCancelFlag") as HtmlTableCell;

看了之後上MSDN查才知道ASP.NET除了提供抓取控制項的方法也有提供抓取HTML ID元件的方法

最後解法如下

protected void ListView1_ItemDataBound(object sender, ListViewItemEventArgs e)
{
    //方法三,使用HtmlTableCell的InnerText屬性跟InnerText屬性
    ListViewItem item = e.Item;
    HtmlTableCell td = item.FindControl("tdCancelFlag") as HtmlTableCell;

    if (!td.InnerText.Trim().Equals("未繳款"))
    {
        DelButton.Enabled = false;
    }
}

其中HtmlTableCell類別有提供InnerText跟InnerHtml這兩個屬性

依照MSDN上面HtmlTableCell類別的對於兩個屬性的定義

InnerHtml 取得或設定在指定的 HTML 伺服器控制項的開始和結尾標記之間的內容。
InnerText 取得或設定在指定的 HTML 伺服器控制項的開始和結尾標記之間的文字。

字面上的意思來看應該InnerHtml會回傳整個Html標籤包含內容InnerText則是純內文

不過看回傳值都一樣

我還怕是不是顯示在網頁所以被網頁給解碼

所以輸出成txt文字檔

可是看起來兩個輸出完全一樣

InnerHtml並沒有如我預期出現HTML標籤

不曉得有哪位高手知道這兩者到底差在哪裡嗎Orz


一開始用這方法有遇到一個bug

Equals("未繳款")這邊怎樣都是false

回家後才想到該不會是回傳值中間有空白...

所以用Trim()去頭去尾就解決這個問題了

另外注意用這個方法你要抓的HTML標籤必須加上runat="server"他才能按圖索驥抓到該ID

<td id="tdCancelFlag" runat="server">
    <%# cancel_flagToCh(Eval("cancel_flag").ToString()) %>
</td>

沒有留言:

張貼留言