none
DataGridViewからTreeViewにドラッグドロップするには RRS feed

  • 質問

  • OS:WindowsXP

    VisualStuido 2005(VB)

    はじめまして。

    タイトルの通りですが、DataGridViewっをドラックして

    TreeViewにドロップしたいと思っています。

    現状は色々な投稿サイトを真似て

    1レコードずつは何とか出来るようになったのですが

    複数レコードを選択してツリーに追加する所で苦戦しています。

    ご存知の方がいらっしゃいましたら

    教えて下さい。

    宜しくお願いします。

    2010年12月3日 9:00

回答

  • TreeViewへDataGridViewの複数行をドロップしたいという事ですが、

    現状では1レコードでは動作しているんですよね。

    質問文からは、現状がどのような実装か不明なので、大雑把な答えになりますが

    その箇所で、移動元DataGridViewの「SelectedCells」や「SelectedColumns」や

    「SelectedRows」あたりの情報を元に、選択しているセルや行分の処理を

    ループで行えばいいのではないでしょうか。


    • 回答としてマーク 山本春海 2010年12月10日 2:31
    2010年12月6日 1:26
  • 原因としては、複数行を選択していたとしても、以下の箇所

    DoDragDrop(DataGridView1.Rows(hit.RowIndex), DragDropEffects.Move)

    で、一行分しかドラッグドロップ対象のデータとして設定していない為です。

    DoDragDropには、「Me.DataGridView1.SelectedRows()」を渡すと良いです。

    一応確認のために書いたコードがあるので、参考として利用してください。

     

    前提は、フォームにDataGridView1とTreeView1を貼り付けるだけです。

    Public Class Form1
      Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ' TreeView初期データを作成
        TreeView1.Nodes.Add("あ")
        TreeView1.Nodes(TreeView1.Nodes.Count - 1).Nodes.Add("い")
        TreeView1.Nodes(TreeView1.Nodes.Count - 1).Nodes.Add("う")
        TreeView1.Nodes.Add("か")
        TreeView1.Nodes(TreeView1.Nodes.Count - 1).Nodes.Add("き")
        TreeView1.Nodes(TreeView1.Nodes.Count - 1).Nodes.Add("く")
        TreeView1.Nodes.Add("さ")
        TreeView1.Nodes(TreeView1.Nodes.Count - 1).Nodes.Add("し")
        TreeView1.Nodes(TreeView1.Nodes.Count - 1).Nodes.Add("す")
        ' DataGridView初期データを作成
        Me.DataGridView1.Columns.Add("column1", "column1")
        Me.DataGridView1.Columns.Add("column2", "column2")
        For i As Integer = 1 To 10
          Me.DataGridView1.Rows.Add("1_" + i.ToString(), "2_" + i.ToString())
        Next
        'TreeView1へドラッグを許可
        TreeView1.AllowDrop = True
        ' Drag&Drop関連のイベントを登録
        AddHandler DataGridView1.MouseDown, AddressOf DataGridView1_MouseDown
        AddHandler TreeView1.DragOver, AddressOf TreeView1_DragOver
        AddHandler TreeView1.DragDrop, AddressOf TreeView1_DragDrop
      End Sub
    
      Private Sub DataGridView1_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs)
        ' 左クリックの場合のみ処理
        If e.Button = MouseButtons.Left Then
          ' DataGridView1の行選択が存在すること
          If Me.DataGridView1.SelectedRows().Count > 0 Then
            ' 行選択全てをドラッグドロップデータに設定
            Me.DataGridView1.DoDragDrop(Me.DataGridView1.SelectedRows(), DragDropEffects.Copy)
          End If
        End If
      End Sub
    
      Private Sub TreeView1_DragOver(ByVal sender As Object, ByVal e As DragEventArgs)
        ' DataGridViewSelectedRowCollection以外は受け入れない
        If e.Data.GetDataPresent(GetType(DataGridViewSelectedRowCollection)) Then
          e.Effect = DragDropEffects.Copy
          ' DropするNodeを取得する
          Dim p As Point = Me.TreeView1.PointToClient(New Point(e.X, e.Y))
          Dim target As TreeNode = Me.TreeView1.GetNodeAt(p)
          If Not target Is Nothing Then
            ' DropするNodeを選択する
            Me.TreeView1.Focus()
            If target.IsSelected = False Then
              Me.TreeView1.SelectedNode = target
            End If
            ' 選択するNodeが子を持っている場合は展開
            If target.Nodes.Count > 0 And Not target.IsExpanded Then
              target.Expand()
            End If
          Else
            e.Effect = DragDropEffects.None
          End If
        Else
          e.Effect = DragDropEffects.None
        End If
      End Sub
    
      Private Sub TreeView1_DragDrop(ByVal sender As Object, ByVal e As DragEventArgs)
        ' DataGridViewSelectedRowCollection以外は受け入れない
        If e.Data.GetDataPresent(GetType(DataGridViewSelectedRowCollection)) Then
          ' DataGridView1の行選択データを取得
          Dim data As DataGridViewSelectedRowCollection = CType(e.Data.GetData( _
          GetType(DataGridViewSelectedRowCollection)), DataGridViewSelectedRowCollection)
          ' もし複数行の追加データを特定の順序で追加する必要があれば
          ' ここでdataをソートする
    
          ' Drop先のNodeの子Nodeとして、DataGridView1の行選択データを追加
          For Each row As DataGridViewRow In data
            ' column1とcolumn2の文字列を結合して追加する
            Me.TreeView1.SelectedNode.Nodes.Add(row.Cells(0).Value.ToString() + ":" + _
                              row.Cells(1).Value.ToString())
          Next
        Else
          e.Effect = DragDropEffects.None
        End If
      End Sub
    End Class
    
    

    • 回答としてマーク 山本春海 2010年12月10日 2:31
    2010年12月8日 6:36

すべての返信

  • TreeViewへDataGridViewの複数行をドロップしたいという事ですが、

    現状では1レコードでは動作しているんですよね。

    質問文からは、現状がどのような実装か不明なので、大雑把な答えになりますが

    その箇所で、移動元DataGridViewの「SelectedCells」や「SelectedColumns」や

    「SelectedRows」あたりの情報を元に、選択しているセルや行分の処理を

    ループで行えばいいのではないでしょうか。


    • 回答としてマーク 山本春海 2010年12月10日 2:31
    2010年12月6日 1:26
  • ご回答ありがとうございます。

    仰られている通り、「SelectedRows」を使って出来そうかなと思っていたのですが

    データの受け渡しの部分でうまく動きませんでした。

    (下記にしたりしました。

    DoDragDrop(DataGridView1.SelectedRows, DragDropEffects.Move)

    DataGridViewのマウスダウンイベント(DataGridView1_MouseDown)で選択されたレコードを取得し

    TreeViewのドラックドロップイベント(TreeView1_DragDrop)の引数

    「ByVal e As System.Windows.Forms.DragEventArgs」で受け取った時

    選択された複数レコードにしたいです。(現在は1レコードだけ)

    如何せん、Web上のサンプルを理解できず作ったプログラムなので

    改変が出来ませんでした。

    お手数をお掛けしますが、宜しくお願いします。

    ■受け渡しのソース抜粋しました。

    Private Sub DataGridView1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles DataGridView1.MouseDown

     Dim hit As DataGridView.HitTestInfo = DataGridView1.HitTest(e.X, e.Y)
     If hit.Type = DataGridViewHitTestType.Cell AndAlso (Me.DataGridView1.NewRowIndex = -1 OrElse Me.DataGridView1.NewRowIndex <> hit.RowIndex) Then
      DoDragDrop(DataGridView1.Rows(hit.RowIndex), DragDropEffects.Move)
     End If


    End Sub

    Private Sub TreeView1_DragDrop(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles TreeView1.DragDrop

        Dim strNode As String

        Dim pt As Point
        Dim DestinationNode As TreeNode
        pt = CType(sender, TreeView).PointToClient(New Point(e.X, e.Y))
        DestinationNode = CType(sender, TreeView).GetNodeAt(pt)

        ' ドロップするデータ
        Dim dgvr As DataGridViewRow = DirectCast(e.Data.GetData(GetType(DataGridViewRow)), DataGridViewRow)

        'ノード名を取得する
        strNode = ""
        For col As Integer = 0 To dgvr.Cells.Count - 1
            strNode = strNode & dgvr.Cells(col).Value
        Next

        '選択されたノードを追加する
        Dim NewNode As New TreeNode(strNode)

        '親ツリーにノードを追加する
        DestinationNode.Nodes.Add(NewNode.Clone)
        DestinationNode.Expand()

    End Sub

    2010年12月8日 5:04
  • 原因としては、複数行を選択していたとしても、以下の箇所

    DoDragDrop(DataGridView1.Rows(hit.RowIndex), DragDropEffects.Move)

    で、一行分しかドラッグドロップ対象のデータとして設定していない為です。

    DoDragDropには、「Me.DataGridView1.SelectedRows()」を渡すと良いです。

    一応確認のために書いたコードがあるので、参考として利用してください。

     

    前提は、フォームにDataGridView1とTreeView1を貼り付けるだけです。

    Public Class Form1
      Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ' TreeView初期データを作成
        TreeView1.Nodes.Add("あ")
        TreeView1.Nodes(TreeView1.Nodes.Count - 1).Nodes.Add("い")
        TreeView1.Nodes(TreeView1.Nodes.Count - 1).Nodes.Add("う")
        TreeView1.Nodes.Add("か")
        TreeView1.Nodes(TreeView1.Nodes.Count - 1).Nodes.Add("き")
        TreeView1.Nodes(TreeView1.Nodes.Count - 1).Nodes.Add("く")
        TreeView1.Nodes.Add("さ")
        TreeView1.Nodes(TreeView1.Nodes.Count - 1).Nodes.Add("し")
        TreeView1.Nodes(TreeView1.Nodes.Count - 1).Nodes.Add("す")
        ' DataGridView初期データを作成
        Me.DataGridView1.Columns.Add("column1", "column1")
        Me.DataGridView1.Columns.Add("column2", "column2")
        For i As Integer = 1 To 10
          Me.DataGridView1.Rows.Add("1_" + i.ToString(), "2_" + i.ToString())
        Next
        'TreeView1へドラッグを許可
        TreeView1.AllowDrop = True
        ' Drag&Drop関連のイベントを登録
        AddHandler DataGridView1.MouseDown, AddressOf DataGridView1_MouseDown
        AddHandler TreeView1.DragOver, AddressOf TreeView1_DragOver
        AddHandler TreeView1.DragDrop, AddressOf TreeView1_DragDrop
      End Sub
    
      Private Sub DataGridView1_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs)
        ' 左クリックの場合のみ処理
        If e.Button = MouseButtons.Left Then
          ' DataGridView1の行選択が存在すること
          If Me.DataGridView1.SelectedRows().Count > 0 Then
            ' 行選択全てをドラッグドロップデータに設定
            Me.DataGridView1.DoDragDrop(Me.DataGridView1.SelectedRows(), DragDropEffects.Copy)
          End If
        End If
      End Sub
    
      Private Sub TreeView1_DragOver(ByVal sender As Object, ByVal e As DragEventArgs)
        ' DataGridViewSelectedRowCollection以外は受け入れない
        If e.Data.GetDataPresent(GetType(DataGridViewSelectedRowCollection)) Then
          e.Effect = DragDropEffects.Copy
          ' DropするNodeを取得する
          Dim p As Point = Me.TreeView1.PointToClient(New Point(e.X, e.Y))
          Dim target As TreeNode = Me.TreeView1.GetNodeAt(p)
          If Not target Is Nothing Then
            ' DropするNodeを選択する
            Me.TreeView1.Focus()
            If target.IsSelected = False Then
              Me.TreeView1.SelectedNode = target
            End If
            ' 選択するNodeが子を持っている場合は展開
            If target.Nodes.Count > 0 And Not target.IsExpanded Then
              target.Expand()
            End If
          Else
            e.Effect = DragDropEffects.None
          End If
        Else
          e.Effect = DragDropEffects.None
        End If
      End Sub
    
      Private Sub TreeView1_DragDrop(ByVal sender As Object, ByVal e As DragEventArgs)
        ' DataGridViewSelectedRowCollection以外は受け入れない
        If e.Data.GetDataPresent(GetType(DataGridViewSelectedRowCollection)) Then
          ' DataGridView1の行選択データを取得
          Dim data As DataGridViewSelectedRowCollection = CType(e.Data.GetData( _
          GetType(DataGridViewSelectedRowCollection)), DataGridViewSelectedRowCollection)
          ' もし複数行の追加データを特定の順序で追加する必要があれば
          ' ここでdataをソートする
    
          ' Drop先のNodeの子Nodeとして、DataGridView1の行選択データを追加
          For Each row As DataGridViewRow In data
            ' column1とcolumn2の文字列を結合して追加する
            Me.TreeView1.SelectedNode.Nodes.Add(row.Cells(0).Value.ToString() + ":" + _
                              row.Cells(1).Value.ToString())
          Next
        Else
          e.Effect = DragDropEffects.None
        End If
      End Sub
    End Class
    
    

    • 回答としてマーク 山本春海 2010年12月10日 2:31
    2010年12月8日 6:36
  • ご回答ありがとうございました。

    バッチリ思い通りの事が出来るようになりました。

    とても感謝しております。

    頂いたコードを解読し、もっと勉強したいと思います。

    本当にありがとうございました。

    2010年12月8日 10:23
  • こんにちは、basser819 さん。

    MSDN フォーラムのご利用ありがとうございます。オペレーターの山本です。
    問題が解決したとのこと、よかったですね。

    honefai さんからの投稿が参考になったようでしたので、勝手ながら私のほうで回答としてマークさせていただきました。
    honefai さん、アドバイスありがとうございます。

    今後同じ問題でこのスレッドを参照される方にも有効な情報が分かりやすくなるかと思いますので、解決に役立った有効な情報や参考になった情報には、回答としてマークすることをお願いしています。
    ご協力よろしくお願いいたしますね。

    今後とも、MSDN フォーラムをよろしくお願いいたします。
                                                                                                                            
    マイクロソフト株式会社 フォーラム オペレーター 山本 春海

     

    2010年12月10日 2:31