C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[8]: DataGridViewの複数セル選択について


(過去ログ 92 を表示中)

[トピック内 12 記事 (1 - 12 表示)]  << 0 >>

■55062 / inTopicNo.1)  DataGridViewの複数セル選択について
  
□投稿者/ チョーさん (1回)-(2010/11/16(Tue) 12:59:46)

分類:[VB.NET/VB2005 以降] 

DataGridView(VB 2008)で、MultiSelect=Trueにして、
複数セルを選択できるようにしているのですが、
複数セルの内容をドラッグで他のコントロールに持っていけるようにするため、
複数セルが選択状態の時、任意の選択セルをマウスダウンした時には
セル選択が変更されないようにしたいのですが、
どうすればよいでしょうか?
現状では、複数セルが選択状態の時、任意の選択セルをマウスダウンした時点で、
選択状態が変わり、マウスダウンしたセルのみの選択になってしまいます。

宜しくお願いします。
引用返信 編集キー/
■55067 / inTopicNo.2)  Re[1]: DataGridViewの複数セル選択について
□投稿者/ 魔界の仮面弁士 (1935回)-(2010/11/16(Tue) 13:57:29)
2010/11/16(Tue) 13:57:51 編集(投稿者)
No55062 (チョーさん さん) に返信
> 複数セルの内容をドラッグで他のコントロールに持っていけるようにするため、
ドラッグでの範囲選択と、選択範囲のドラッグの両方を実現したいなら、
処理を単純化するために、
 「セルの選択は左ボタン」
 「ドラッグは右ボタン」
という仕様にしてしまうのが簡単かと。


> 現状では、複数セルが選択状態の時、任意の選択セルをマウスダウンした時点で、
> 選択状態が変わり、マウスダウンしたセルのみの選択になってしまいます。

どのようなコードになっていますか?


'手抜きコードなので、マウスドラッグでの選択はできません。
'複数選択には Ctrl や Shift キーを併用して行ってください。
Public Class Form1

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
        DataGridView1.AllowUserToAddRows = False
        DataGridView1.ColumnCount = 10
        DataGridView1.RowCount = 20
        DataGridView1.EditMode = DataGridViewEditMode.EditProgrammatically
        DataGridView1.MultiSelect = True
    End Sub

    Private Sub DataGridView1_MouseDown(ByVal sender As Object, _
      ByVal e As MouseEventArgs) Handles DataGridView1.MouseDown
        '実際に組み込む際には、SystemInformation.DragSize でのドラッグ開始判定や
        'クリックされた位置(ヘッダーは除外するなど)も判定条件に加えておいた方が良いかも。
        If CBool(e.Button And MouseButtons.Left) Then

            '選択されたセルの一覧
            Dim s As New List(Of String)()
            For Each c As DataGridViewCell In Me.DataGridView1.SelectedCells
                s.Insert(0, String.Format("{0}-{1}", c.RowIndex, c.ColumnIndex))
            Next

            '(テキストデータにしてあるので、メモ帳等にドロップしてください)
            DataGridView1.DoDragDrop(Join(s.ToArray(), vbCrLf), DragDropEffects.All)
        End If
    End Sub
End Class

引用返信 編集キー/
■55072 / inTopicNo.3)  Re[2]: DataGridViewの複数セル選択について
□投稿者/ チョーさん (2回)-(2010/11/16(Tue) 14:35:58)
No55067 (魔界の仮面弁士 さん) に返信
>>現状では、複数セルが選択状態の時、任意の選択セルをマウスダウンした時点で、
>>選択状態が変わり、マウスダウンしたセルのみの選択になってしまいます。
>
> どのようなコードになっていますか?

コードは特に特殊なことはしておりません。
まず、デザイナ上で、フォームにDataGridViewを貼り付け、Column1とColumn2の列を追加しました。
また、グリッドデータの書き換えができないよう、DataGridViewのReadOnlyプロパティはTrueにしてあります。
(他のDataGridViewのプロパティは変更していません。)
また、フォームのコードは以下の通りです(単純にデータをグリッドに追加しているだけ)。

Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
DataGridView1.Rows.Add("1", "あああああ")
DataGridView1.Rows.Add("2", "いいいいい")
DataGridView1.Rows.Add("3", "ううううう")
End Sub
End Class

このフォームを起動し、Ctrl・Shiftキーを使い、複数セルの選択ができるのですが、
複数セルが選択された状態で任意のセル左クリックでマウスダウンを行うと、
マウスダウンを行ったセルのみの選択になってしまいます。
※提示頂いたサンプルでは、ドラッグしたデータには複数セルのデータが含まれていると思いますが、
 結果、グリッド上では一つのセルの選択しか表示されません。
 ドラッグ中でも、選択したセルすべてが選択状態になっていてほしいのです。

例えば、エクスプローラーでは、

・選択されていないファイルのマウスダウン(Ctrl・Shiftキーなし)を行うと、今までの選択が解除され、
 マウスダウンを行ったファイルが選択状態となる。
・選択されていないファイルのマウスダウン(Ctrl・Shiftキーあり)を行うと、各キーの機能に応じて
 選択箇所を含めた範囲が選択状態となる。
・選択されているファイルのマウスダウン(Ctrl・Shiftキーなし)を行うと、選択箇所をドラッグできる。

という振る舞いになっていますが、まさにこれと同じことを実現したいのです。

説明が不足していて申し訳ございません。
宜しくお願いします。
引用返信 編集キー/
■55075 / inTopicNo.4)  Re[3]: DataGridViewの複数セル選択について
□投稿者/ マサヤ (176回)-(2010/11/16(Tue) 15:01:34)
CellClickイベント発生時に e.ColumnIndexとe.RowIndexをリストに格納してあげる方法はどうでしょう?
同じのがあったらリストから削除する。
リストにあるセルは全てフォーカスをセットする。
他のコントロールに移動するときはリストの中身をみてあげればいいのではないのでしょうか?

引用返信 編集キー/
■55076 / inTopicNo.5)  Re[3]: DataGridViewの複数セル選択について
□投稿者/ チョーさん (3回)-(2010/11/16(Tue) 15:02:12)
自己レスです。
DataGridView1_MouseDownイベント内でDataGridView1.DoDragDropを行うことで、
ドラッグ中はDataGridView上で複数選択状態(選択セルが反転表示)を保持したままになっていました。
ドラッグが終了あるいは中断するとセル選択は1セルのみになってしまいますが、
とりあえずこれはよしとします。

ありがとうございました。
解決済み
引用返信 編集キー/
■55082 / inTopicNo.6)  Re[3]: DataGridViewの複数セル選択について
□投稿者/ 魔界の仮面弁士 (1936回)-(2010/11/16(Tue) 16:06:01)
No55072 (チョーさん さん) に返信
> コードは特に特殊なことはしておりません。
DoDragDrop ぐらいは行っていませんか?


> (他のDataGridViewのプロパティは変更していません。)
DataGridView を複数用意しているのですね?


>> '(テキストデータにしてあるので、メモ帳等にドロップしてください)
間違えました、メモ帳にはドロップできません。
秀丸、ワードパッド、VS のエディタ上などにドロップしてみてください。
(メモ帳はファイルのドロップは受け付けるが、文字列のドロップは受け付けない)


>  結果、グリッド上では一つのセルの選択しか表示されません。
>  ドラッグ中でも、選択したセルすべてが選択状態になっていてほしいのです。
「ドラッグ終了時」には解除される(ので復元作業が必要)とはいえ、
「ドラッグ中」は複数セルが選択状態になっているかと思います。

それとも、DoDragDrop の実行中にも解除されてしまうのでしょうか?


> ・選択されていないファイルのマウスダウン(Ctrl・Shiftキーなし)を行うと、今までの選択が解除され、
>  マウスダウンを行ったファイルが選択状態となる。
これは現行通りですね。

> ・選択されていないファイルのマウスダウン(Ctrl・Shiftキーあり)を行うと、各キーの機能に応じて
>  選択箇所を含めた範囲が選択状態となる。
これも現行通り。


> ・選択されているファイルのマウスダウン(Ctrl・Shiftキーなし)を行うと、選択箇所をドラッグできる。
「選択されているセルのマウスダウン」なら、イメージコードで言うと、

 Dim ht = DataGridView1.HitTest(e.X, e.Y)
 If ht.Type = DataGridViewHitTestType.Cell AndAlso _
   ht.RowIndex <> -1 AndAlso _
   ht.ColumnIndex <> -1 AndAlso _
   DataGridView1(ht.ColumnIndex, ht.RowIndex).Selected Then

  If DataGridView1.DoDragDrop(…) = … Then

という感じのコードにすれば、それっぽい動きになるかと。
引用返信 編集キー/
■55083 / inTopicNo.7)  Re[4]: DataGridViewの複数セル選択について
□投稿者/ 魔界の仮面弁士 (1937回)-(2010/11/16(Tue) 16:08:06)
No55076 (チョーさん さん) に返信
> DataGridView1_MouseDownイベント内でDataGridView1.DoDragDropを行うことで、
> ドラッグ中はDataGridView上で複数選択状態(選択セルが反転表示)を保持したままになっていました。
だから、そういうコードを書いたのに…。(^_^;)


> ドラッグが終了あるいは中断するとセル選択は1セルのみになってしまいますが、
> とりあえずこれはよしとします。
無理矢理戻してみました。これでもまだ不十分な感はありますけれども。


Public Class Form1
    Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
        DataGridView1.AllowUserToAddRows = False
        DataGridView1.ColumnCount = 10
        DataGridView1.RowCount = 20
        DataGridView1.ReadOnly = True
        DataGridView1.MultiSelect = True
    End Sub

    Private Sub DataGridView1_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles DataGridView1.MouseDown
        If CBool(e.Button And MouseButtons.Left) Then
            Dim ht = DataGridView1.HitTest(e.X, e.Y)
            If ht.Type = DataGridViewHitTestType.Cell AndAlso ht.RowIndex <> -1 And ht.ColumnIndex <> -1 Then
                If DataGridView1(ht.ColumnIndex, ht.RowIndex).Selected Then
                    '選択されたセルの一覧
                    Dim cellList As New List(Of DataGridViewCell)()
                    Dim textList As New List(Of String)()
                    For Each c As DataGridViewCell In Me.DataGridView1.SelectedCells
                        cellList.Insert(0, c)
                        textList.Insert(0, String.Format("{0}-{1}", c.RowIndex, c.ColumnIndex))
                    Next

                    Dim data As String = Join(textList.ToArray(), vbCrLf)
                    DataGridView1.DoDragDrop(data, DragDropEffects.All)

                    BeginInvoke(New Foo(AddressOf ReSelect), cellList)
                End If
            End If
        End If
    End Sub

    Private Delegate Sub Foo(ByVal selectedCells As IEnumerable(Of DataGridViewCell))
    Private Sub ReSelect(ByVal selectedCells As IEnumerable(Of DataGridViewCell))
        For Each c In selectedCells
            c.Selected = True
        Next
    End Sub
End Class

引用返信 編集キー/
■55112 / inTopicNo.8)  Re[4]: DataGridViewの複数セル選択について
□投稿者/ チョーさん (4回)-(2010/11/17(Wed) 09:43:22)
No55083 (魔界の仮面弁士 さん) に返信
わざわざサンプルコードまで頂き、ありがとうございました。
しかしながら、以下の行およびFooとReSelectを入れると、
選択セルのCtrl+クリックでの選択解除ができません。

BeginInvoke(New Foo(AddressOf ReSelect), cellList)

これを解除するにはどうすればいいのでしょうか?
引用返信 編集キー/
■55113 / inTopicNo.9)  Re[5]: DataGridViewの複数セル選択について
□投稿者/ 魔界の仮面弁士 (1943回)-(2010/11/17(Wed) 10:03:49)
No55112 (チョーさん さん) に返信
> 選択セルのCtrl+クリックでの選択解除ができません。

とりあえず、
 If CBool(e.Button And MouseButtons.Left) Then
の部分を
 If CBool(e.Button And MouseButtons.Left) AndAlso Not CBool(ModifierKeys And Keys.Control) Then
に変えてみるとか。
引用返信 編集キー/
■55114 / inTopicNo.10)  Re[6]: DataGridViewの複数セル選択について
□投稿者/ チョーさん (5回)-(2010/11/17(Wed) 10:36:32)
No55113 (魔界の仮面弁士 さん) に返信
> とりあえず、
>  If CBool(e.Button And MouseButtons.Left) Then
> の部分を
>  If CBool(e.Button And MouseButtons.Left) AndAlso Not CBool(ModifierKeys And Keys.Control) Then
> に変えてみるとか。

ありがとうございます。
これを入れることによって、Ctrlキーを押した場合は選択/解除が行われるようになりました。
ここでまた質問なのですが、

・Ctrlキーの他、Shiftキーでも選択・解除が正しく行われるようにするには、
  If CBool(e.Button And MouseButtons.Left) AndAlso Not CBool(ModifierKeys And Keys.Control) Then
 の部分を
  If CBool(e.Button And MouseButtons.Left) AndAlso Not CBool(ModifierKeys And (Keys.Control Or Keys.Shift)) Then
 とすればいいのでしょうか?
 (ShiftキーらしきものにKeys.ShiftとKeys.ShiftKeyがあり、どちらを使えばいいか分かりませんでした。)

・Ctrlキーで複数選択/解除はできたのですが、ドラッグ&ドロップ完了後、あるいはドラッグ中止後に
 任意のセルをクリックしても状態が変わりませんでした。
 (例えば、ドラッグ後、未選択セルをクリックしても選択されない、選択セルをCtrl+クリックしても選択解除されない、等)
 ただし、二度目以降のクリックでは期待通りの振る舞いをします。
 これは何が原因なのでしょうか?

質問が増えて申し訳ありませんが、宜しくお願いします。
引用返信 編集キー/
■55116 / inTopicNo.11)  Re[7]: DataGridViewの複数セル選択について
□投稿者/ 魔界の仮面弁士 (1944回)-(2010/11/17(Wed) 11:38:41)
No55114 (チョーさん さん) に返信
> ・Ctrlキーの他、Shiftキーでも選択・解除が正しく行われるようにするには、

> とすればいいのでしょうか?
結果はどうでしたか?


> (ShiftキーらしきものにKeys.ShiftとKeys.ShiftKeyがあり、どちらを使えばいいか分かりませんでした。)
修飾子キー(ModifierKeys)の確認に使用するのは、Shiftの方です。

KeyEventArgs.Modifiers で使うのが、Keys.Shift で、
KeyEventArgs.KeyCode で使うのが、Keys.ShiftKey です。


> ただし、二度目以降のクリックでは期待通りの振る舞いをします。
本来の処理に無理矢理割り込ませた弊害ですね。。。
今のところ解決策が見つかりません。実のところ、この点が No55083
「これでもまだ不十分な感はありますけれども」と書いた理由の一つでもあります。

# ReleaseCapture や SendInput で回避できないものかな…。


> 質問が増えて申し訳ありませんが、宜しくお願いします。
このあたりの解決が面倒だったので、私は結局、
No55067 の冒頭に書いた方法で逃げてしまっていたりします。
引用返信 編集キー/
■55119 / inTopicNo.12)  Re[8]: DataGridViewの複数セル選択について
□投稿者/ チョーさん (6回)-(2010/11/17(Wed) 14:52:05)
No55116 (魔界の仮面弁士 さん) に返信
コメントありがとうございます。
とりあえず、今回の問題については、もう一度クリックすればいいので、保留とします。
ありがとうございました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -