- PR -

ListViewでデータを動的に表示する方法

1
投稿者投稿内容
シンヤ
会議室デビュー日: 2004/07/07
投稿数: 5
投稿日時: 2004-07-08 00:42
OS :WINDOWS2000
言語:VB.Net
DB :MSDE

VB.NetでListViewを使いたいのですがデータベースの同一テーブルの
データ毎に結合し、表示できますでしょうか?

■テーブル定義
ID  親ID  子ID
1 null 2
2 1 3
3 2 null
4 2 null
5 null 6
6 5 null

■表示したいデータ
root
├−1
│ └−2
│ ├−3
│ └−4
└−5
└−6

上記の様に表示したいのですが、
子IDがn件、最上位層の親IDがnull、
最下位層の子IDがnullとなる為、
データセットでの自己結合際にエラーが
発生してしまい上手く表示できません。
SQL側での制御、コードでの制御の両面を
考慮しておりますがなにか良い手段は
ありましでしょうか?
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-07-08 09:25
引用:

シンヤさんの書き込み (2004-07-08 00:42) より:

■表示したいデータ
コード:
root
  ├−1
  │ └−2
  │    ├−3
  │    └−4
  └−5
     └−6




 こういうデータは、このようにテーブルを定義します。
コード:
CREATE TABLE SELFLINK_TABLE (
 ID NUMBER PRIMARY KEY,
 PARENT NUMBER REFERENCES SELFLINK_TABLE (ID) ON DELETE CASCADE,
 other columns definition
);



データは、次のように入れます。
コード:
ID PARENT LABEL
 1  NULL  ROOT
 2     1  1
 3     2  2
 4     2  3
 5     2  4
 6     1  5
 7     1  6

シンヤ
会議室デビュー日: 2004/07/07
投稿数: 5
投稿日時: 2004-07-08 12:41
Jittaさんのご指摘を参考にし、以下の様に組んだのですが、
上手く2階層目以降が表示されません。

--------------------------------------------------------------->

'親ID用SQL
Dim strSQL1 As String = "SELECT TBL1.ID,TBL1.NAME, " _
& "TBL1.PARENT_ID FROM TBL TBL1 "

'子ID用SQL
Dim strSQL2 As String = "SELECT TBL2.ID,TBL2.NAME, " _
& "TBL2.PARENT_ID FROM TBL TBL2 "
'コネクション確立
cnn = New SqlConnection(strConnectionString)
ds = New DataSet
cnn.Open()
'親IDデータ取得
cmAuthors = New SqlDataAdapter(strSQL1, cnn)
cmAuthors.Fill(ds, "TBL1")

'子IDデータ取得
cmTitles = New SqlDataAdapter(strSQL2, cnn)
cmTitles.Fill(ds, "TBL2")

'親IDと子IDでリレーションデータセット作成
ds.Relations.Add("TBL3", _
ds.Tables("TBL1").Columns("ID"), _
ds.Tables("TBL2").Columns("PARENT_ID"))

For Each rowAuthor In ds.Tables("TBL1").Rows
nodeAuthor = New TreeNode
nodeAuthor.Text = rowAuthor("NAME")
If rowAuthor.IsNull("PARENT_ID") Then
'ノードの追加
TreeView1.Nodes.Add(nodeAuthor)
End If
'子ノードの展開
For Each rowTitle In rowAuthor.GetChildRows("TBL3")
nodeTitle = New TreeNode
nodeTitle.Text = rowTitle("NAME")
nodeAuthor.Nodes.Add(nodeTitle)
Next
Next

--------------------------------------------------------------->


root
├−1
│ └−2
│ ├−3
│ └−4
└−5
└−6
と表示したいのに

root
├−1
│ └−2
└−5
└−6
と表示されてしまいます。

初歩的な質問で恐縮ですが、ご教授お願い致します。
えんぞ@?
ぬし
会議室デビュー日: 2004/07/06
投稿数: 271
お住まい・勤務地: はまっこ
投稿日時: 2004-07-08 14:38
引用:

Jittaさんのご指摘を参考にし、以下の様に組んだのですが、
上手く2階層目以降が表示されません。



親ID⇒子ID とその次は、子ID⇒孫IDのリレーションを行わないと、
2階層で終わってしまうのでは...
なので、もう1つリレーションをはる必要があると思います。

と、そもそもこの手法だと表示する階層は制限かかってしまいさらに
下位階層(4階層目以降)が存在する場合、そのたんびにリレーション
を行わないといけなくなってしまいます。
私の場合は、階層4階層まで等の仕様が決まっているため、SQL文で
回避してますが、無限に続く階層の場合はどうなるんでしょ...
-------------
@日々勉強
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-07-08 15:00
シンヤさん&えんぞ@見習さん
引用:

シンヤさんの書き込み (2004-07-08 12:41) より:

Jittaさんのご指摘を参考にし、以下の様に組んだのですが、
上手く2階層目以降が表示されません。


 まず、取得するときに「親」とか「子」は考えません。Oracleでは、自己参照テーブルをたどって取得するSELECT文の拡張句があるのですが、SQL Server(MSDE)にはありません。仕方がないので、とりあえず、そのままDataTableに持ってきます。

SELECT ID, PARENT, NAME FROM TABLE1

 TreeView(ListsViewではなく、TreeViewですよね?)に表示するには、1行ずつ取り出しながら、PARENTを見て、PARENTがnullならルート要素として、nullでないならそのIDを持つ要素の子として追加します。

テキトーなコード
コード:
for each row in table.Rows
    if (row.Parent is null) {
        TreeViewのルート要素に追加
    } else {
        TreeViewから、IDがParentと同じ要素を探す
        要素の子として追加
    }



 DataSet中のDataTableにリレーションシップを張るには、自己参照させます。
私のウェブページ、「.NET FrameworkおよびVS.NETに関するTips→階層問い合わせの類似」より:
コード:
Dim dset As New System.Data.DataSet("HierarchicalDataSet")
Dim tbl As New System.Data.DataTable("HierarchicalTable")
Dim adpt As System.Data.DbDataAdapter = New あれ?作ってね

' 階層構造を作る
adpt.SelectCommand.CommandText("SELECT * FROM HIERARCHICALTABLE")
adpt.Fill(dset, tbl)
' 外部制約を追加する
dset.Relations.Add(
    "SelfReference",
    tbl.Columns("ID"),
    tbl.Columns("PARENT")) ' 第2引数と第3引数が反対?

' 使う
Dim cnt As Integer
Dim rows() As System.Data.DataRow
Dim row As System.Data.DataRow
Dim queue As New System.Collections.Queue
rows = tbl.Select(階層のトップを問い合わせる条件)
' 階層のトップをキューに入れる。これは準備
For cnt = 0 To rows.Length - 1
    queue.Enqueue(rows(cnt))
Next
' 実際に吐き出す処理はここから
While Not (queue.Peek() Is Nothing)
    row = queue.Dequeue
    ' 取り出した行の操作をここに追加する
    ' このデータの子を取り出して、キューに追加する
    rows = row.GetChildRows("SelfReference")
    For cnt = 0 To rows.Length - 1
        queue.Enqueue(rows(cnt))
    Next
End While;

シンヤ
会議室デビュー日: 2004/07/07
投稿数: 5
投稿日時: 2004-07-12 23:06
Jittaさん、えんぞ@見習さん、ありがとうございます。

ご指摘どおり、2階層で終わってしまうので、
データの取得時に「親・子」を考えずに、再帰処理を行う
事で解決できました。

コード:
For each row in table.Rows
    If rowAuthor.IsNull("FOLDER_PARENT") Then
    if (row.Parent is null) {
      親ノード追加
   Add_Parent(親ノード)
    End If
Next

Sub Add_Parent(親ノード)
    子ノード追加
  Add_Parent(親ノード)
End Sub



ご指摘ありがとうございました。
1

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