最近寫了幾個asp.net的項目。其中,Asp.Net的控制項DataGrid使用的最多了,前幾天需要一個功能,我研究了很長時間,發現一個方法,應該是最簡單的實現。現表述如下。
DataGrid的html定義很簡單,如下
<Asp:DataGrid ID="myDatagrid" runat="server" datakeyfield="fID" AutoGenerateColumns="False">
<Columns>
<Asp:TemplateColumn itemstyle-width=".." ..>
<ItemTemplate>
.
</ItemTemplate>
</Asp:TemplateColumn>
</Columns>
</Asp:DataGrid>
功能的要求是在 ItemTemplate中,有可能是一個綁定資料來源的:
<a href="...">...</a>
連結代碼,也有可能是一個
<span>...</span>
顯示文本代碼,而判斷的根據是綁定到DataGrid中資料來源的DataTable中每行的某一特定列的內容。
說白了,功能就是DataGrid在綁定資料產生行的時候,判斷資料來源DataTable每行DataRow中一個欄位的內容,這個欄位類型是bool類型,如果為true,則這個列顯示的是<a href="...">...</a>連結,而如果是false,則顯示<span>...</span>文本。而顯示的連結內指向的地址必須執行資料繫結。就是這個DataGrid的列有的行要資料繫結,有的行不要資料繫結。
功能需求分析到這裡,那麼現在該思考如何?了。
我當時瞭解需求後,馬上反應出來,使用DataGrid內建的BoundColumn、HyperLinkColumn肯定是不行的。而且,使用TemplateColumn也有麻煩。他只能放一些固定的控制項,如html控制項或伺服器控制項等。後來我沒有辦法了,準備繼承ITemplate介面自己開發一個模版列。後來又覺得麻煩。因為綁定的時候需要一個類似於BoundColumn功能的綁定資料來源內容的東西。後來我發現了這個方法。
在查看.Net Framework SDK 文檔的時候,我發現在<Asp:TemplateColumn>中的<ItemTemplate>中可以放類似於
<%# DataBinder.Eval(Container.DataItem, "fID") %>
這樣的資料繫結代碼,我就想是否可以再加入代碼呢
我做了一個實驗,實驗結果發現上面的代碼(包括前面和後面的<% %>符號)輸出的實際上是一個object對象,然後DataGrid顯示的時候把它轉換成字串。後來我就想,是否可以前面再加入代碼,調用這個頁面的後台代碼中的方法。
我們都知道,在asp.net1.1中,一個名稱為aaa.aspx的asp.net頁在asp.net內部處理時是一個名叫ASP.aaa_aspx的類,這個類繼承它的後台代碼aaa.aspx.cs中的類,這個類繼承System.Web.UI.Page類,從而實現需要的功能。這就是說,在asp.net 1.1中,我們在.aspx中的以<% %> 包含的代碼可以調用後台cs類中的以public 和protected生命的任何方法。
這就好辦了,既然從上面的資料繫結代碼可以擷取主鍵內容(是個字串),那麼我可以在後台寫一個方法,這個方法有一個字串參數,返回的也是字串。這個返回的字串就是顯示在列中的內容。
首先說一下綁定表的內容,如下
列名 |
類型 |
用途 |
fID |
System.String |
表主鍵 |
hasSub |
System.Boolean |
判斷的依據 |
contentUrl |
System.String |
連結的地址 |
然後是後台代碼中C#代碼
protected string GetDGColumn(string id)
{
// 從資料來源擷取DataTable內容略
DataTable dt = .;
// 定義DataTable的主鍵列
DataColumn[] key = {dt.Columns["fID"]};
dt.PrimaryKey = key;
// 根據傳入的id開始找資料行
DataRow row = dt.Rows.Find(id);
// 找到後開始判斷
if((bool)row["hasSub"])
{
// hasSub為 true,表示返回<span>
return "<span style=\"\">內容內容</span>";
}
else
{
// hasSub列為false,返回連結
return "<a href=\"XXXX.aspx?id="+id+"\" target=\"_blank\">連結內容</a>";
}
}
然後在.aspx中的DaaGrid內這樣定義:
<Asp:DataGrid ID="myDatagrid" runat="server" datakeyfield="fID" AutoGenerateColumns="False">
<Columns>
<Asp:TemplateColumn itemstyle-width=".." ..>
<ItemTemplate>
<%# base.GetDGColumn((object)DataBinder.Eval(Container.DataItem, "fID")) %>
</ItemTemplate>
</Asp:TemplateColumn>
</Columns>
</Asp:DataGrid>
利用了DataGrid綁定時內部使用的資料繫結方法擷取結果,然後把結果傳遞給GetDGColumn()方法,DataGrid列的內容實際上是使用的這個方法返回的字串。
好了,一個隨心所欲產生DataGrid列內容的方法說完了,不知道大家有沒有更好的方法。
我這個方法的缺點就是產生的內容沒有辦法執行伺服器提交,它無法被伺服器段區分開,所以只能是使用靜態連結,文本等。還有就是可以調用用戶端的js指令碼。如果誰有更好的方法,如產生的連結按鈕的單擊事件可以被伺服器端區分,請指教。如果大家有更好的方法,也請指教。我在這裡謝謝大家了。