DOBON.NET DOBON.NETプログラミング掲示板過去ログ

ツリービューコントロール コンテキストメニュー

環境/言語:[.NET Framework1.1]
分類:[.NET]

こんにちわ。ML、.NET Tipsでいつもお世話になっております。

質問なんですが、

ツリービューコントロール(Windowsフォーム)のノードにコンテキストメニューを設定することはできないのでしょうか?

ノードを選択し、選択しているノード上で右クリックしたときにコンテキストメニューを表示したいと考えております。

ツリービューコントロール自体のコンテキストメニューを設定してしまうと、
ツリービューコントロールのあらゆる場所で、右クリックすると出てきてしまって
困っています。

開発環境は

.NET Framework 1.1 SP1
Visual Studio 2003
VB.NET

です。よろしくお願いします。
> ツリービューコントロール(Windowsフォーム)のノードにコンテキストメニューを設定することはできないのでしょうか?

TreeViewのMouseUpイベントハンドラなどでTreeView.GetNodeAtメソッドを使ってNodeがクリックされたかを調べ、NodeがクリックされたならばContextMenuを表示させるというような方法になるかと思います。

Private Sub TreeView1_MouseUp(ByVal sender As Object, _
ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles TreeView1.MouseUp
If e.Button = MouseButtons.Right Then
Dim tv As TreeView = CType(sender, TreeView)
'クリックされたNodeを調べる
Dim node As TreeNode = tv.GetNodeAt(e.X, e.Y)
If Not (node Is Nothing) Then
'ContextMenuの設定
'ここでは意味もなく一番上のメニュー項目名を変更している
ContextMenu1.MenuItems(0).Text = node.Text
'ContextMenuを表示
ContextMenu1.Show(tv, New Point(e.X, e.Y))
End If
End If
End Sub
ありがとうございます。

私も掲示板に書き込んだ後、ContextMenu.Show()メソッドをみつけて、
座標を取得して表示すれば良いんだなと踏んでためしていたのですが、
ContextMenu.Show(treeview,New Point(treeview.MousePosition))
で行っていたため、変なところへコンテキストメニューが表示されていました。

本当に夜中なのにありがとうございます。たすかりました。
後はコンテキストメニューごとの処理を記述するだけだ。
また明日がんばります。
ツリービューのコンテキストメニューについて、本当にありがとうございました。

今度はどうしてもツリービューへのノードの追加ロジックが思いつかないため、できたらお助けいただきたいと想い投稿させてもらいました。

[実現したいツリー]
1---
  2---
     4

  3

5---
  6


[ツリーの元となるテーブル(DataSetのDataTable)]
CD      親CD
1       *
2       1
3       1
4       2
5       *
6       5


宜しくお願いします。
私は頭が固いとつくづく実感しました。。。(涙)
■No6870に返信(kiyoさんの記事)
> 今度はどうしてもツリービューへのノードの追加ロジックが思いつかないため、できたらお助けいただきたいと想い投稿させてもらいました。
> 
> [ツリーの元となるテーブル(DataSetのDataTable)]
> CD      親CD
> 1       *
> 2       1
> 3       1
> 4       2
> 5       *
> 6       5
> 

DataSetを親CD⇒CDの優先順位で昇順ソートして、
親CD  CD
*   1
*   5
1   2
1   3
2   4
5   6
として、上から順に作っていくか、
親CD  CD
*   1
*   5
だけ調べておいて、
親CD  CD
*   1
を作った直後に、それに続くのを検索してあれば作成・・・
と続けるとか。

大まかにいえば、
一つのルートノードを作ったら、その子ノードをすべて作成してから
次のルートノードを作るか、
データをソートして、一つずつ位置を指定して作っていくか、になるかと。

簡単なのは前者でしょうか。
そのためにはまず、DataSetを親CD⇒CDの順で昇順ソートして、
そこからは順次必要なデータを再度DataSetから検索、という流れになるかと思います。
rakiさんありがとうございます。

両方の案を検討していたのですが、
TreeViewのTreeNodeコレクションの森に
はまってしまいました(涙)

>データをソートして、一つずつ位置を指定して作っていくか、になるかと。

TreeNodeの位置を指定して追加するのはどのようにしたら良いのか
ヘルプ、インターネット等でしらべたのですが、
検討がつきませんでした。

引き続きご教授願います。
> 両方の案を検討していたのですが、
> TreeViewのTreeNodeコレクションの森に
> はまってしまいました(涙)

階層構造は見た目と同じ形になりますので、
難しくはありませんよ。
TreeView
 狼reeNode(ルートノード)
   狼reeNode(子ノード)
     狼reeNode(子ノード)
 狼reeNode(ルートノード)
のような感じになります。
ルートノード・子ノードというのは
Parentプロパティに親TreeNodeがあるかないか(TreeViewが親か)の違いだけで、
別物というわけではありません。どちらも同じTreeNodeです。


> TreeNodeの位置を指定して追加するのはどのようにしたら良いのか

ルートノードからファイル検索のように該当ノードを検索していくしかないです。
それか、CD、親CD、該当TreeNodeの情報を持つ一次元配列などを作っていき、
そちらから検索するとか。

サンプルを載せておきます。
CD      親CD
1       *
2       1
3       1
4       2
5       *
6       5
と格納されている二次元配列
Dim CDData(6, 2) As String
があるという前提で。

    Private Sub Form1_Load( _
            ByVal sender As System.Object, ByVal e As System.EventArgs) _
                Handles MyBase.Load
        For i As Integer = 0 To UBound(CDData) - 1
            If CDData(i, 1) = "*" Then
                Dim node As TreeNode

                node = TreeView1.Nodes.Add(CDData(i, 0))

                Call AddChildNode(node)
            End If
        Next
    End Sub

    Private Sub AddChildNode(ByRef node As TreeNode)
        For i As Integer = 0 To UBound(CDData) - 1
            If CDData(i, 1) = node.Text Then
                Dim childNode As TreeNode

                childNode = node.Nodes.Add(CDData(i, 0))

                AddChildNode(childNode)
            End If
        Next
    End Sub

これは、先のレスの前者の方法になります。
サンプルということで、特にデータ操作も行っていませんが、
データ件数が多くなった場合は、処理速度を上げるため、
先のレスのように、DataSetの中から必要な形で必要な分だけの
DataSetを取得し、それを使ってループ処理をするといった、
テクニックが必要になると思います。
rakiさんありがとうございます。
サンプルコードまでつけていただいて。
おかげさまでできました。
私が作成したのは以下のとおりです。

Private Sub Form1_Load( _
ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles MyBase.Load

      Dim trnParent As TreeNode ' ルートノード
      Dim dtrRootRow As DataRow() ' DataSet内のルートノードの集まり

      '--- ツリービュー追加処理 ---
      With DataSet.Tables("DATATABLE")

        '--- ルートノードのDataRowを抽出 ---
        dtrRootRow = .Select("親CD = *")

        '--- ルートノードの追加 ---
        For intCnt As Integer = 0 To dtrRootRow.Length - 1

          trnParent = Me.TreeView.Nodes.Add(dtrRootRow(intCnt).Item("CD")

          '子探し
          If .Select("親CD <> *").Length <> 0 Then

            Call AddChildNode(trnParent)

          End If

        Next

      End With

End Sub

Private Sub AddChildNode(ByRef trnParent As TreeNode)

    Dim dtrChildRow As DataRow() ' 子の集まり
    Dim trnChild As TreeNode    ' 子のツリーノード


    With DataSet.Tables("DATATABLE")

      dtrChildRow = .Select("親CD = '" & trnParent.text & "'")

      If dtrChildRow.Length <> 0 Then

        For intCnt As Integer = 0 To dtrChildRow.Length - 1

          trnChild = trnParent.Nodes.Add(dtrChildRow(intCnt).Item("CD")

          AddChildNode(trnChild)

        Next

      End If

    End With
End Sub


こんな感じで作成したいツリーが完成しました。
rakiさん本当にありがとうございました。
これで大分ツリービューについて理解が深まりました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板