2008年1月8日火曜日

DataGridViewでセル間のドラッグドロップ

よくある質問としては「DataGridViewで行の並び替えをマウスで行いたい」というのがあるんだけど、
意外と少ないのは「同じDataGridViewの中でセルの値をドラッグドロップしたい」というやつ。

どうしても業務AP作っている時間が長ければ長いほど、キーボードメインになってしまうので
こういった発想自体出てこないというか、やったらいけないと思い込んでしまうんだよね。
完全にオペレータ向けのGUIならともかく、一般的な社員も使うなら問題ない、むしろ歓迎されるんだけどw

ということでセル間のドラッグドロップだけど、その前に注意点が。

編集モードはEditOnEnter禁止

当たり前だけど編集状態=編集コントロールがアクティブだからセルを操作することができないんで。
くだらなさそうだけど、実際にひっかかってしまった人がここにいますw

処理としてはDataGridViewのDrag~系イベントのみの記述で事足りるね。
DragOverイベントで引数として渡ってくるdrgeventのEffectプロパティに対して適切なエフェクトを設定してあげて、DragDropイベントで元セルから先セルへ値をコピーなり移してあげればOK。

ただ一点面倒なことがあって、ドラッグ元セルの値の種類を判断してうんぬんしようとすると大変なことになるのよ。
というのもデフォルトで用意されている各種Cellクラスでは保持する値のTypeがどれもこれもObjectでありやがるからで、
ここでは割り切ってセルの値を移動(またはコピー)としてしまった方がいいね。

それであれば、(先セル).Value = (元セル).Valueと書くだけでいけるから。アクションが移動なら、その後に(元セル).Value = Nothingとかそんな類の処理をいれてあげれば大丈夫。

4 件のコメント:

  1. 最近、c#を始めた者です。
    2つのDataGriDview(AとB)があり
    AからBへセルの値をdrag&dropする処理を行いたくて
    探していたら、このページにたどり着きました。

    可能であれば
    具体的に実装方法を教えていただけないでしょうか?

    返信削除
  2. コメントありがとうございます。
    ちょっと手元に VB 環境しかないのでサンプルといっても VB になってしまいますが、これでどうでしょう?


    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    'サンプルデータの設定
    With DataGridView1
    .Rows.Add("1", "2", "3")
    .Rows.Add("4", "5", "6")
    .Rows.Add("7", "8", "9")
    End With
    With DataGridView2
    .AllowDrop = True
    .Rows.Add("11", "12", "13")
    .Rows.Add("14", "15", "16")
    .Rows.Add("17", "18", "19")
    End With

    End Sub

    Private Sub dgvMouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles DataGridView1.MouseMove
    If e.Button = Windows.Forms.MouseButtons.Left Then
    '別DataGridViewへの移動の際は Effects.All
    DataGridView1.DoDragDrop(DataGridView1.CurrentCell.Value, DragDropEffects.All)
    End If
    End Sub

    Private Sub dgvDragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles DataGridView2.DragDrop
    '本来はHItTest等を利用してセル位置を判定する
    If e.Data.GetDataPresent(GetType(String)) Then
    Dim dgvCellValue = e.Data.GetData(GetType(String))
    DataGridView2.CurrentCell.Value = dgvCellValue
    End If
    End Sub

    Private Sub dgvDragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles DataGridView2.DragEnter
    e.Effect = DragDropEffects.Copy
    End Sub

    ポイントとしては、指定するエフェクトをCopyでやってしまうと、別コントロールにはDragDropできなかったので、
    Allを指定しているところかな、と思います。

    返信削除
  3. このコメントは投稿者によって削除されました。

    返信削除
  4. コメント欄はTabも空白も勝手に調整されるので非常にみずらくて、申し訳ないです・・・

    返信削除