- PR -

[ASP.NET/C#]縦横スクロール時のDataGridのIndex固定

1
投稿者投稿内容
夏姫☆
会議室デビュー日: 2003/12/11
投稿数: 15
投稿日時: 2004-02-23 10:22

おはようございます。いつも参考にさせていただいております。
現在、ASP.NET/C#にてWebアプリケーションを開発中なのですが、
行き詰まってしまい、良い方法を御教授願えないかと投稿させて戴きました。

DataGridを使用して、DBからの検索結果を表示しています。
テンプレートは表示時にプログラム中で動的に作成する造りになっています。
データの表示項目、件数共に多い為、GridLayoutPanelを用いて
スクロールさせています。
データスクロール時にIndexの固定が行いたく、過去の投稿を参考に
Index部をTableタグ使用で固定表示しているのですが、この方法は
縦スクロールには有効なのですが、横スクロールには対応出来ず
困っています。

親GridLayoutPanelの上にIndex部の固定表示と、子GridLayoutPanelに
DataGridを貼ったもの(スクロールはAuto指定)をのせてみたり〜と
試してみましたが、思ったような動きにはなりませんでした。

表示項目数の分割等の対応方法も検討の一つだと思いますが、
縦横スクロール時にDataGridのIndexの固定は出来ないものでしょうか。

良い方法をご存じの方がいらっしゃいましたら、何卒御教授下さい。
宜しくお願い致します。
todo
ぬし
会議室デビュー日: 2003/07/23
投稿数: 682
投稿日時: 2004-02-25 13:57
引用:

夏姫☆さんの書き込み (2004-02-23 10:22) より:

Index部をTableタグ使用で固定表示しているのですが、この方法は
縦スクロールには有効なのですが、横スクロールには対応出来ず
困っています。



<DIV onscroll>で同期させればよいでしょう。

http://ptvi.hp.infoseek.co.jp/mi/dhtml_00002.html
http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art141.asp
夏姫☆
会議室デビュー日: 2003/12/11
投稿数: 15
投稿日時: 2004-03-02 10:50
おはようございます。
todoさん、アドバイスしていただき、ありがとうございました。
なかなか上手くできず遅くなりましたが、ご報告致します。

引用:


todoさんの書き込み(2004-02-25 13:57)より:

<DIV onscroll>で同期させればよいでしょう。

http://ptvi.hp.infoseek.co.jp/mi/dhtml_00002.html




最初、この方法を参考にしてやってみたのですが、
自分のJavaScriptの組み方がマズかったようで
上手くいきませんでした。

引用:


todoさんの書き込み(2004-02-25 13:57)より:

http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art141.asp




そこで、↑のIndex部用とItem部用にDataGridを2つ使う方法に
変えたところ、スクロールはできるようになりました。
ありがとうございました。

自分でもMSDNで調べてみたのですが、日本語、英語以外では
調べていなかったので、びっくりでした。
#これからのSEはスペイン語も必要なのでしょうか


ご報告が遅くなったのは、上記方法でスクロールはできるように
なった変わり!?にセル幅の指定が効かなくなったためです。

このサンプルはDataGridのテンプレートをHTML側で定義していますが、
当方が作成中のものはコードビハインド側で動的に作成しているため、
サンプルを見本に同内容になるように組み込んでみました。

すると、スクロールはできるのですが、Index側のセル幅の指定が
効かなくなり、Index部とItem部でセル幅が合わないまま
スクロールはちゃんとするというような表示になってしまいました。

表示時のHTMLソースには(Index部のソース抜粋)

<div style="OVERFLOW: hidden; WIDTH: 400px">
<table cellspacing="0" rules="all" bordercolor="Gray"
border="1" id="DataGrid1" style="background-color:Moccasin;
border-color:Gray;border-style:Solid;width:1200px;
border-collapse:collapse;POSITION:relative">
<tr>
<td style="width:30px;"><B>No.</B></td>
<td style="width:50px;"><B>ProductID</B></td>
    :
</tr>
</table>
</div>

のようにstyleでセル幅指定が入っているにも関わらず、
指定が効かない現象になっています。
なんだか些細なことが原因のような気もするのですが

記載されているにも関わらず、指定が効かないということは
ブラウザに解釈されるときの順番とか何かあるのかな〜などと、
現在も苦戦中です。

解決いたしましたら改めてご報告したいと思いますが、
何か思い当たるような事をご存知の方がいらっしゃいましたら
ぜひアドバイスしていただければと思います。
よろしくお願いいたします。
todo
ぬし
会議室デビュー日: 2003/07/23
投稿数: 682
投稿日時: 2004-03-02 12:59
<table>のwidthを指定しているのが拙いのでは?

あるいは、
http://ptvi.hp.infoseek.co.jp/mi/dhtml_00002.html
のようにクライアント側で列幅を調整してやればよいでしょう。
夏姫☆
会議室デビュー日: 2003/12/11
投稿数: 15
投稿日時: 2004-03-02 14:35

できました〜
todoさん本当にありがとうございました!!

引用:

todoさんの書き込み(2004-03-02 12:59)より:

<table>のwidthを指定しているのが拙いのでは?



todoさんにご指摘いただいた<table>のwidth指定の解除と、
DataGrid側のword-breakをbreak-all指定にすることで
上手くいきました。

数週にわたる悩みの種がやっと解決できました
#ここにUPする前にかなり悩んだ


ご参考までに

<HTML>
<HEAD>
<title>IndexTest</title>
<meta name="GENERATOR" Content="Microsoft Visual Studio 7.0">
<meta name="CODE_LANGUAGE" Content="C#">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
<STYLE>
.Esconder { ZOOM: 1% }
</STYLE>
<Script language="JScript">
function DoScroll()
{
document.all("DataGrid1").style.pixelLeft = divScroll.scrollLeft * -1;
}
</Script>
</HEAD>
<body>
<form id="Form1" method="post" runat="server">
<div style="OVERFLOW: hidden; WIDTH: 400px" runat="server">
<asp:datagrid id="DataGrid1" style="word-break: break-all; POSITION:relative"
runat="server" AutoGenerateColumns="False" GridLines="Both"
BorderStyle="Solid" BorderColor="Gray"></asp:datagrid>
</div>
<div id="divScroll" onscroll="DoScroll()"
style="OVERFLOW:auto;WIDTH:400px;HEIGHT:200px">
<asp:datagrid id="DataGrid2" style="word-break: break-all" runat="server"
AutoGenerateColumns="False" GridLines="Both" BorderStyle="Solid"
BorderColor="Gray" ShowHeader="True"></asp:datagrid>
</div>
</form>
</body>
</HTML>


private void Page_Load(object sender, System.EventArgs e)
{
dataSet1 = new DataSet();
dataSet2 = new DataSet();
dataSet2.ReadXml( "D:\\Work\\TestXmlData.xml" );

// Header表示用にテンプレートだけのDataSet作成
DataTable dataTable = new DataTable();
dataTable.TableName = dataSet2.Tables[0].TableName;

dataSet1.DataSetName = dataSet2.DataSetName;

for ( int i=0; i<dataSet2.Tables[0].Columns.Count; i++ )
{
DataColumn dataColumn = new DataColumn();
dataColumn.DataType = dataSet2.Tables[0].Columns[i].DataType;
dataColumn.ColumnName = dataSet2.Tables[0].Columns[i].ColumnName;
dataTable.Columns.Add( dataColumn );
}
dataSet1.Tables.Add( dataTable );

// Indexデータセット
DataGrid1.DataSource = dataSet1;
DataGrid1.DataMember = dataSet1.Tables[0].TableName;
DataGrid1.BackColor = Color.FromName( "Moccasin" );
SetDataGrid( DataGrid1, dataSet1 );

// Itemデータセット
DataGrid2.DataSource = dataSet2;
DataGrid2.DataMember = dataSet2.Tables[0].TableName;
DataGrid2.BackColor = Color.FromName( "White" );
SetDataGrid( DataGrid2, dataSet2 );

DataGrid1.DataBind();
DataGrid2.DataBind();
}

// 一覧表示のデータをセット
private void SetDataGrid( DataGrid dataGrid, DataSet dataSet )
{
for ( int i=0; i<dataSet.Tables[0].Columns.Count; i++ )
{
string columnName = dataSet.Tables[0].Columns[i].ColumnName;
int columnWidth = ( int )dataWidth[i];

TemplateColumn tempColumn = new TemplateColumn();
tempColumn.HeaderTemplate
= new DataGridTemplate( ListItemType.Header, columnName );
tempColumn.ItemTemplate
= new DataGridTemplate( ListItemType.Item, columnName );
dataGrid.Columns.Add( tempColumn );

dataGrid.Columns[i].HeaderStyle.Width = new Unit( columnWidth );
dataGrid.Columns[i].HeaderStyle.Wrap = false;
dataGrid.Columns[i].ItemStyle.Width = new Unit( columnWidth );
dataGrid.Columns[i].ItemStyle.Wrap = false;
}
}

// 一覧表示のセル幅獲得
private static void setWidthData()
{
// 省略 一覧表示用のセル幅のリストを定義ファイルから
// 獲得しArrayList dataWidthに格納するMethod
}

// Template作成
public class DataGridTemplate : ITemplate
{
// 省略 DataGrid用のテンプレート作成クラス
}
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-03-05 16:55
引用:

夏姫☆さんの書き込み (2004-03-02 14:35) より:

できました〜
todoさん本当にありがとうございました!!

ご参考までに


 ありがとうございます。参考にさせていただきました。

> style="POSITION: relative"
 これがないとoffsetTopが常に0なのね
夏姫☆
会議室デビュー日: 2003/12/11
投稿数: 15
投稿日時: 2004-03-08 10:39

ちなみに、ネスケではスクロールは出来るのですが、
Index部の表示が二重に表示されてダメでした。
IE6では表示&動作確認できています。

今回の要件はクライアントがIE6だったから問題ないのですが、
ネスケで〜とかになると、また考えなきゃです…。
上手く行かないものですね。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-03-08 15:31
引用:

夏姫☆さんの書き込み (2004-03-08 10:39) より:

今回の要件はクライアントがIE6だったから問題ないのですが、
ネスケで〜とかになると、また考えなきゃです…。
上手く行かないものですね。


 まぁ、スクリプトの仕様が違うので、仕方のないところです。

 私の方はヘッダ行、ヘッダ列固定だったのですが、ヘッダ列の方が苦労しました。データ用のDataGridの「幅」がなかなか取れずに。。。


     大まかには、
  • テーブルを3つ使用する。1つは全体をまとめるためのテーブル。これを2行2列とし、(0列,0行)は使用しない。(1,0)はヘッダ行、(0,1)はヘッダ列、(1,1)はデータとする。
  • 全体テーブルはborder、cellpading、cellspaceすべて0にして、余分なスペースを使わないようにする(計算が面倒)。
  • ヘッダ列にもdiv要素を付け、幅を固定する。
  • 大きさや幅についてはMSDNのトピック『エレメントの大きさと位置を測定する』を参照する。
  • データの表示可能な幅は、document.body.clientWidth - ヘッダ列のdiv要素.clientWidth - α;。αは不明。
  • onloadとonresizeで、動的に幅を計算すること。
  • 列の高さは後述のソースでセットする。

私のところでは列の幅は固定(環境ファイルに固定値を定義)だったので、サーバ側で設定してしまいました。動的に幅を変更する場合、次のソースを少し変更すれば使えると思います。
コード:

// copybookのデータグリッド(HTMLのtable要素)のセルの高さに、
// targetのデータグリッドのセルの高さを合わせる
function table_height_fit(copybook, target) {
var cbRows = copybook.rows;
var tgRows = target.rows;
var rowCount = 0;

for (rowCount = 0; rowCount < tgRows.length; rowCount++) {
if (tgRows(rowCount).cells(0).clientHeight
< cbRows(rowCount).cells(0).clientHeight) {
tgRows(rowCount).cells(0).style.height
= cbRows(rowCount).cells(0).clientHeight;

} else if (tgRows(rowCount).cells(0).clientHeight
> cbRows(rowCount).cells(0).clientHeight) {
cbRows(rowCount).cells(0).style.height
= tgRows(rowCount).cells(0).clientHeight;
}
}
}




 ネスケでは、table要素とCSSを次のように定義すれば、ヘッダ行固定は実現できます。(IEとOperaは不可)

CSS:
tbody {
OVERFLOW: scroll;
Height: テキトー;
}

<table>
<thead>略</thead>
<tbody>略</tbody>
</table>

問題は、DataGridのレンダーがこのようには出力してくれないこと。。。


※ヘッダー列にボタンを表示していて、データ列が1行しかないとき、
 ボタンの方が「高い」ので位置がずれるという不具合が発生。なおしました。

[ メッセージ編集済み 編集者: Jitta 編集日時 2004-03-08 17:44 ]
1

スキルアップ/キャリアアップ(JOB@IT)