ASP.NET(C#)とJQuery+TableSorterを連携してみた。
対象はグリッド系コントロールのGridView・ListView・Repeater・DataList・DataGrid。
■開発・運用環境
- Visual Studio 2008 SP1
- .NET Framework 3.5 SP1
- ASP.NET3.5
■ブラウザ
- IE6,IE8
- Firefox3
- Opera9
- Chrome2.0
TableSorterではtableタグ内にtheadタグが必須である。
しかしASP.NETのグリッド系コントロールは「デフォルト設定ではtheadを出力しない」もしくは「theadを出力できない」。(下表参照)
コントロール |
出力可否(*1) |
設定方法 |
GridView |
○ |
プロパティで設定。 |
ListView |
○ |
Templateコントロールにtableタグを記述。 |
Repeater |
○ |
Templateコントロールにtableタグを記述。 |
DataList |
× |
「サーバサイド設定」「JavaScript(*2)」連携が必要。 |
DataGrid |
× |
「サーバサイド設定」「JavaScript(*2)」連携が必要。 |
(*1)出力可否の基準は「簡単に出力できるか?」である。サーバサイドでもtheadタグの出力方法はあると思う。(方法は不明)。
(*2)JavaScript処理内でtableタグのinnerHTMLとouterHTMLに対して読み書きしているが、
innerHTMLとouterHTMLにはブラウザ依存がある。
ASP.NETでTableSorterを利用する為には、この制限を突破しtheadタグを出力させる必要がある。
なお後述のサンプルソースではtheadのほかにtbodyも出力している。
本ページでは関係ないことだが他のテーブル操作プラグインでtbodyが必要な場合もあるため一応出力している。
■GridView
①Page_Load等で以下のプロパティ設定を行う。
GridView1.UseAccessibleHeader = true;
GridView1.HeaderRow.TableSection = TableRowSection.TableHeader;
②JavaScriptでtablesorter()関数呼び出し。
$(function () {
$("#GridView1").tablesorter();
};
■ListView
①aspxファイルでLayoutTemplate・ItemTemplateにtableタグを記述。
<asp:ListView ID="ListView1" runat="server">
<LayoutTemplate>
<table id="ListView1Table" class="tablesorter">
<thead>
<tr>
<th>No</th>
<th>文字列</th>
</tr>
</thead>
<tbody>
<asp:PlaceHolder runat="server" ID="itemPlaceholder" />
</tbody>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td><%# Eval("No") %></td>
<td><%# Eval("文字列") %></td>
</tr>
</ItemTemplate>
</asp:ListView>
②JavaScriptでtablesorter()関数呼び出し。
$(function () {
$("#ListView1Table").tablesorter();
};
■Repeater
①aspxファイルでHeaderTemplate・ItemTemplate・FooterTemplateにtableタグを記述。
<asp:Repeater ID="Repeater1" runat="server">
<HeaderTemplate>
<table id="Repeater1Table" class="tablesorter">
<thead>
<tr>
<th>No</th>
<th>文字列</th>
</tr>
</thead>
<tbody>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><%# Eval("No") %></td>
<td><%# Eval("文字列")%></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</tbody>
</table>
</FooterTemplate>
</asp:Repeater>
②JavaScriptでtablesorter()関数呼び出し。
$(function () {
$("#Repeater1Table").tablesorter();
};
■DataList
①aspxファイルでHeaderTemplate・ItemTemplate・FooterTemplateにtableタグを記述。
<asp:DataList ID="DataList1" runat="server">
<HeaderTemplate>
<table id="DataList1Table" class="tablesorter">
<thead>
<tr>
<th>No</th>
<th>文字列</th>
</tr>
</thead>
<tbody>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><%# Eval("No") %></td>
<td><%# Eval("文字列")%></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</tbody>
</table>
</FooterTemplate>
</asp:DataList>
②Page_Load等で以下のプロパティ設定を行う。
DataList1.RepeatLayout = RepeatLayout.Flow;
③JavaScriptで②の設定変更で出力されるspan・brタグを除去後、tablesorter()関数呼び出し。
$(function () {
var objDataList1Table = document.getElementById("DataList1Table")
if ($.browser.msie)
{
// IE
var sDataList1TableHTML = objDataList1Table.outerHTML;
sDataList1TableHTML = sDataList1TableHTML.replace(/[<]+SPAN[>]+/gi, "");
sDataList1TableHTML = sDataList1TableHTML.replace(/[<]+\/SPAN[>]+/gi, "");
sDataList1TableHTML = sDataList1TableHTML.replace(/[<]+BR[>]+/gi, "");
objDataList1Table.outerHTML = sDataList1TableHTML;
}
else
{
// FireFox,Opera,Chrome
var sDataList1TableHTML = objDataList1Table.innerHTML;
sDataList1TableHTML = sDataList1TableHTML.replace(/[<]+SPAN[>]+/gi, "");
sDataList1TableHTML = sDataList1TableHTML.replace(/[<]+\/SPAN[>]+/gi, "");
sDataList1TableHTML = sDataList1TableHTML.replace(/[<]+BR[>]+/gi, "");
objDataList1Table.innerHTML = sDataList1TableHTML;
}
$("#DataList1Table").tablesorter();
});
■DataGrid
①Page_Load等で以下のプロパティ設定を行う。
DataGrid1.ShowHeader = false;
②JavaScriptで「theadタグの付与」「ヘッダー列作成」「tableからstyle属性削除」後、tablesorter()関数呼び出し。
$(function () {
var objDataGrid1 = document.getElementById("DataGrid1")
if ($.browser.msie)
{
// IE
var sNewOuterHTML;
var sNewInnerHTML = "";
sNewInnerHTML += "<thead><th>No</th><th>文字列</th></thead>";
sNewInnerHTML += objDataGrid1.innerHTML;
sNewOuterHTML = objDataGrid1.outerHTML.replace(objDataGrid1.innerHTML, sNewInnerHTML);
objDataGrid1.outerHTML = sNewOuterHTML;
}
else
{
// FireFox,Opera,Chrome
var sNewInnerHTML = "";
sNewInnerHTML += "<thead><th>No</th><th>文字列</th></thead>";
sNewInnerHTML += objDataGrid1.innerHTML;
objDataGrid1.innerHTML = sNewInnerHTML;
}
$("#DataGrid1").removeAttr("style");
$("#DataGrid1").tablesorter();
});
ASP.NET(C#)とJQuery+TableSorterを連携したときのサンプルソースを記述する。
<%@ Page Language="C#" AutoEventWireup="true" %>
<%@ Import Namespace="System.Data" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>各種グリッド+TableSorter</title>
<script src="../js/jquery/jquery-1.3.2.js" type="text/ecmascript"></script>
<link href="../js/Tablesorter/blue/style.css" rel="stylesheet" type="text/css" />
<script src="../js/Tablesorter/jquery.tablesorter.js" type="text/javascript"></script>
<script type="text/C#" runat="server">
/// <summary>
/// Page_Load
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//-------------------------------------------------------------------------------------
// DataTable作成
//-------------------------------------------------------------------------------------
DataTable dt = new DataTable("DataTable");
dt.Columns.Add("No", typeof(int));
dt.Columns.Add("文字列", typeof(string));
for (int i = 1; i <= 3; i++)
{
DataRow dr = dt.NewRow();
dr[0] = i;
dr[1] = string.Format("文字{0}", 4-i);
dt.Rows.Add(dr);
}
//-------------------------------------------------------------------------------------
// テーブル系コントロール設定
//-------------------------------------------------------------------------------------
// GridView
GridView1.DataSource = dt;
GridView1.DataBind();
GridView1.UseAccessibleHeader = true;
GridView1.HeaderRow.TableSection = TableRowSection.TableHeader;
// ListView
ListView1.DataSource = dt;
ListView1.DataBind();
// Repeater
Repeater1.DataSource = dt;
Repeater1.DataBind();
// DataList
DataList1.DataSource = dt;
DataList1.DataBind();
DataList1.RepeatLayout = RepeatLayout.Flow;
// DataGrid
DataGrid1.DataSource = dt;
DataGrid1.DataBind();
DataGrid1.ShowHeader = false;
}
}
</script>
<script type="text/ecmascript">
$(function () {
//-------------------------------------------------------------------------------------
// Tablesorterの有効化
// <注意1>
// Tablesorterにはthead,tbodyが必要。しかしDataList,DataGridコントロールは
// サーバサイド処理でthead,tbodyを出すのが困難なため、クライアントスクリプトで
// 強引にthead,tbodyを付与している。
// <注意2>
// 注意1に関連することだがIE系はtableタグのinnerHTMLは読取専用である。
// このためinnerHTMLの代用としてouterHTMLを使っている。
// ちなみにFirefoxはouterHTMLがない。
// <注意3>
// DataListはHTML上部にspanタグをレンダリングする。これがレイアウトをおかしくする。
//-------------------------------------------------------------------------------------
// GridView
$("#GridView1").tablesorter();
// ListView
$("#ListView1Table").tablesorter();
// Repeater
$("#Repeater1Table").tablesorter();
// DataList
var objDataList1Table = document.getElementById("DataList1Table")
if ($.browser.msie)
{
// IE
var sDataList1TableHTML = objDataList1Table.outerHTML;
sDataList1TableHTML = sDataList1TableHTML.replace(/[<]+SPAN[>]+/gi, "");
sDataList1TableHTML = sDataList1TableHTML.replace(/[<]+\/SPAN[>]+/gi, "");
sDataList1TableHTML = sDataList1TableHTML.replace(/[<]+BR[>]+/gi, "");
objDataList1Table.outerHTML = sDataList1TableHTML;
}
else
{
// FireFox,Opera,Chrome
var sDataList1TableHTML = objDataList1Table.innerHTML;
sDataList1TableHTML = sDataList1TableHTML.replace(/[<]+SPAN[>]+/gi, "");
sDataList1TableHTML = sDataList1TableHTML.replace(/[<]+\/SPAN[>]+/gi, "");
sDataList1TableHTML = sDataList1TableHTML.replace(/[<]+BR[>]+/gi, "");
objDataList1Table.innerHTML = sDataList1TableHTML;
}
$("#DataList1Table").tablesorter();
// DataGrid
var objDataGrid1 = document.getElementById("DataGrid1")
if ($.browser.msie)
{
// IE
var sNewOuterHTML;
var sNewInnerHTML = "";
sNewInnerHTML += "<thead><th>No</th><th>文字列</th></thead>";
sNewInnerHTML += objDataGrid1.innerHTML;
sNewOuterHTML = objDataGrid1.outerHTML.replace(objDataGrid1.innerHTML, sNewInnerHTML);
objDataGrid1.outerHTML = sNewOuterHTML;
}
else
{
// FireFox,Opera,Chrome
var sNewInnerHTML = "";
sNewInnerHTML += "<thead><th>No</th><th>文字列</th></thead>";
sNewInnerHTML += objDataGrid1.innerHTML;
objDataGrid1.innerHTML = sNewInnerHTML;
}
$("#DataGrid1").removeAttr("style");
$("#DataGrid1").tablesorter();
});
</script>
</head>
<body>
<form id="form1" runat="server">
GridView:
<asp:GridView ID="GridView1" runat="server" CssClass="tablesorter"></asp:GridView>
ListView:<br />
<asp:ListView ID="ListView1" runat="server">
<LayoutTemplate>
<table id="ListView1Table" class="tablesorter">
<thead>
<tr>
<th>No</th>
<th>文字列</th>
</tr>
</thead>
<tbody>
<asp:PlaceHolder runat="server" ID="itemPlaceholder" />
</tbody>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td><%# Eval("No") %></td>
<td><%# Eval("文字列") %></td>
</tr>
</ItemTemplate>
</asp:ListView>
Repeater:<br />
<asp:Repeater ID="Repeater1" runat="server">
<HeaderTemplate>
<table id="Repeater1Table" class="tablesorter">
<thead>
<tr>
<th>No</th>
<th>文字列</th>
</tr>
</thead>
<tbody>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><%# Eval("No") %></td>
<td><%# Eval("文字列")%></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</tbody>
</table>
</FooterTemplate>
</asp:Repeater>
DataList:<br />
<asp:DataList ID="DataList1" runat="server">
<HeaderTemplate>
<table id="DataList1Table" class="tablesorter">
<thead>
<tr>
<th>No</th>
<th>文字列</th>
</tr>
</thead>
<tbody>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><%# Eval("No") %></td>
<td><%# Eval("文字列")%></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</tbody>
</table>
</FooterTemplate>
</asp:DataList>
DataGrid:<br />
<asp:DataGrid ID="DataGrid1" runat="server" CssClass="tablesorter" AutoGenerateColumns="false">
<Columns>
<asp:BoundColumn DataField="No" />
<asp:BoundColumn DataField="文字列" />
</Columns>
</asp:DataGrid>
</form>
</body>
</html>
上記ソースからASP.NETのグリッド系コントロールとTableSorterの有効な組み合わせなのは、GridView・ListView・Repeater
だと考えられる。
DataList・DataGridも利用可能だがJavaScriptによるタグ操作がある為、表示後にサーバサイド処理と連携すると
何らかの問題が発生する可能性が高い。
またDataListはspan・brタグの置換が発生するため画面自由度が低減する。
他にDataListはFirefox・Chromeでコントロール上部のレイアウトが崩れることも確認している。
最近のコメント