DataGrid的html定義很簡單,如下
<Asp:DataGrid ID="myDatagrid" runat="server" datakeyfield="fID" AutoGenerateColumns="False">
<Columns>
<Asp:TemplateColumn itemstyle-width=".." ..>
<ItemTemplate>
.
</ItemTemplate>
</Asp:TemplateColumn>
</Columns>
</Asp:DataGrid>
<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>";
}
}
{
// 從數據源獲取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>
<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腳本。如果誰有更好的方法,如生成的鏈接按鈕的單擊事件可以被服務器端區分,請指教。如果大家有更好的方法,也請指教。我在這裏謝謝大家了。