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

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

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

DataGridViewで選択した値を取得して別画面に表示し

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

■94128 / inTopicNo.1)  DataGridViewで選択した値を取得して別画面に表示し
  
□投稿者/ あい (9回)-(2020/03/18(Wed) 09:49:35)

分類:[.NET 全般] 

.Net 2010
フレームワーク4

Form1にDataGridView1、Form2にDataGridView2があります。
Form1にForm2の画面を表示するボタンを置きます。(DataGridView1のDataGridViewButtonColumn)
Form2には選択ボタンを置きます。
Form2から単体選択で行を選択し、選択ボタンを押すとForm1に戻り
Form2で選択した行の値を、Form1に反映させる処理をしたいと考えています。

下記URLを参考にやってみました。
https://okwave.jp/qa/q8306007.html

Form1

    Private Sub DataGridView1_SelectionChanged(ByVal sender As Object, ByVal e As EventArgs) Handles DataGridView1.SelectionChanged
        Form2.DataGridView2.SelectedRows(0).Cells(0).Value = Me.DataGridView1.Rows(0).Cells(0).Value
    End Sub

Form2

    '選択ボタン
    Private Sub ButtonSel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonSel.Click
        '選択データを各区分にセット
        For Each r As DataGridViewRow In Form1.DataGridView1.SelectedRows
            r.Cells(0).Value = Me.DataGridView2.SelectedRows(0).Cells(0).Value
        Next

        '画面閉じる
        Me.Close()
    End Sub

Form1のところで
インデックスが範囲を超えています。負でない値で、コレクションのサイズよりも小さくなければなりません。
パラメーター名:index

とエラーメッセージが表示されている状況です。

引用返信 編集キー/
■94130 / inTopicNo.2)  Re[1]: DataGridViewで選択した値を取得して別画面に表示し
□投稿者/ 魔界の仮面弁士 (2618回)-(2020/03/18(Wed) 10:40:40)
No94128 (あい さん) に返信
> Private Sub DataGridView1_SelectionChanged(ByVal sender As Object, ByVal e As EventArgs) Handles DataGridView1.SelectionChanged
>  Form2.DataGridView2.SelectedRows(0).Cells(0).Value = Me.DataGridView1.Rows(0).Cells(0).Value
> End Sub

別フォームの子コントロールを直接操作するのは悪手だと思いますが、それはさておき。


> インデックスが範囲を超えています。負でない値で、コレクションのサイズよりも小さくなければなりません。
> パラメーター名:index
まずは原因の切り分けの為、例外を発生させているのが、
どのコレクションの index が原因なのかを調査してください。


例外の発生個所が
 Form2.DataGridView2.SelectedRows(0).Cells(0).Value = Me.DataGridView1.Rows(0).Cells(0).Value
であるのなら、その処理を

Dim rightRow = Me.DataGridView1.Rows(0)
Dim rightCell = rightRow.Cells(0)
Dim rightValue = rightCell.Value

Dim leftRow = Form2.DataGridView2.SelectedRows(0)
Dim leftCell = leftRow.Cells(0)
leftCell.Value = right.Value

という形に分解してみましょう。


たとえば rightRow の取得時にエラーが起きるなら、
Me.DataGridView1.Rows.Count < 1 の時に、
Me.DataGridView1.Rows(0) を見ている可能性があります。

leftRow の取得時にエラーが起きるなら、
Form2.DataGridView2.SelectedRows.Count < 1 の時に、
Form2.DataGridView2.SelectedRows(0) を見ている可能性があります。
引用返信 編集キー/
■94138 / inTopicNo.3)  Re[2]: DataGridViewで選択した値を取得して別画面に表示し
□投稿者/ あい (10回)-(2020/03/19(Thu) 09:26:49)
No94130 (魔界の仮面弁士 さん) に返信
>>パラメーター名:index
> まずは原因の切り分けの為、例外を発生させているのが、
> どのコレクションの index が原因なのかを調査してください。

> 例外の発生個所が
>  Form2.DataGridView2.SelectedRows(0).Cells(0).Value = Me.DataGridView1.Rows(0).Cells(0).Value
> であるのなら、その処理を

> leftRow の取得時にエラーが起きるなら、
> Form2.DataGridView2.SelectedRows.Count < 1 の時に、
> Form2.DataGridView2.SelectedRows(0) を見ている可能性があります。


ご回答ありがとうございます。
leftRow の取得時にエラーが起きました。

えっと、つまり何もないデータを見ているという事でしょうか?

引用返信 編集キー/
■94140 / inTopicNo.4)  Re[3]: DataGridViewで選択した値を取得して別画面に表示し
□投稿者/ 魔界の仮面弁士 (2620回)-(2020/03/19(Thu) 10:33:36)
No94138 (あい さん) に返信
>> Dim leftRow = Form2.DataGridView2.SelectedRows(0)
> leftRow の取得時にエラーが起きました。
> えっと、つまり何もないデータを見ているという事でしょうか?

DataGridView2 で、1 つ以上の行が選択された状態になっていますか?
「現在の行」と「選択された行」は別物なので注意してください。


もし、行が選択されているにも関わらず、SelectedRows(0) にアクセスできないなら、
画面に表示されている Form2 と、プログラムで指定している Form2 が
別のインスタンスである可能性を疑った方が良いでしょう。

たとえば、Form2 を呼び出すときに、
 Dim f As New Form2()
 f.Show()
などと記述しているのであれば、
 Form2.DataGridView2.SelectedRows(0) = 〜
ではなく、
 f.DataGridView2.SelectedRows(0) = 〜
という記述が求められます。

※ただし先にも述べたように、別フォームの子コントロールを直接操作するのは悪手です。
引用返信 編集キー/
■94141 / inTopicNo.5)  Re[4]: DataGridViewで選択した値を取得して別画面に表示し
□投稿者/ あい (11回)-(2020/03/19(Thu) 10:49:11)
No94140 (魔界の仮面弁士 さん) に返信
> DataGridView2 で、1 つ以上の行が選択された状態になっていますか?
> 「現在の行」と「選択された行」は別物なので注意してください。
>
>
> もし、行が選択されているにも関わらず、SelectedRows(0) にアクセスできないなら、
> 画面に表示されている Form2 と、プログラムで指定している Form2 が
> 別のインスタンスである可能性を疑った方が良いでしょう。
>
> たとえば、Form2 を呼び出すときに、
>  Dim f As New Form2()
>  f.Show()
> などと記述しているのであれば、
>  Form2.DataGridView2.SelectedRows(0) = 〜
> ではなく、
>  f.DataGridView2.SelectedRows(0) = 〜
> という記述が求められます。
>
> ※ただし先にも述べたように、別フォームの子コントロールを直接操作するのは悪手です。

もしかしたら、初めから間違っていたような気もしていました…。
DataGridView2で選択した行の値をDataGridView1に表示させたいだけなのですが、いい方法はありませんでしょうか?

引用返信 編集キー/
■94143 / inTopicNo.6)  Re[5]: DataGridViewで選択した値を取得して別画面に表示し
□投稿者/ 魔界の仮面弁士 (2622回)-(2020/03/19(Thu) 13:00:18)
No94141 (あい さん) に返信
> DataGridView2で選択した行の値をDataGridView1に表示させたいだけなのですが、

Form2 をモーダルで開くのはどうですか?

わざわざ DataGridViewButtonColumn を設けたということは、
 ・ボタンセルが押された行の情報を、Form2 側に渡したい
 ・Form2 の ButtonSel_Click で、Form2.DataGridView2 の内容を
  DataGridView1 に書き戻したい
という状況を予想してみました。


【Form1 側】
Private Sub DataGridView1_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick
  'ボタン列がクリックされた時
  If e.RowIndex >= 0 AndAlso TypeOf DataGridView1.Columns(e.ColumnIndex) Is DataGridViewButtonColumn Then
    'その行を取得して
    Dim row = DataGridView1.Rows(e.RowIndex)
    ' Dim sourceRow As DataRow = DirectCast(row.DataBoundItem, DataRowView).Row
    '自作の共有メソッドに渡して、Form2 をモーダルダイアログとして開く
    Form2.ShowExampleDialog(Me, row)
  End If
End Sub


【Form2 側】
Public Class Form2
  Private parentRow As DataGridViewRow

  Public Shared Sub ShowExampleDialog(owner As IWin32Window, parentRow As DataGridViewRow)
    Using f2 As New Form2()
      f2.parentRow = parentRow
      f2.ShowDialog(owner)
    End Using
  End Sub

  Private Sub ButtonSel_Click(sender As Object, e As EventArgs) Handles ButtonSel.Click
    ' No39258 のソースは「選択行の先頭」を読み取ってましたが、
    ' 下記は「現在行」を読み取るようにしています。
    Dim row = Me.DataGridView2.CurrentRow
    If row Is Nothing OrElse parentRow Is Nothing Then
      MessageBox.Show(Me, "行が選択されていません")
    Else
      parentRow.Cells(0).Value = row.Cells(0).Value
    End If
  End Sub

  Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    'ここには DataGridView2 にデータを表示する処理などの
    '画面初期化処理が記述される
  End Sub
End Class



上記では ShowDialog メソッドによる「モーダル」ダイアログですが、
もしも Show メソッドによる「モードレス」ダイアログとして Form2 を表示し、
しかも ButtonSel の動作が『ボタンセルが押された行』へ反映ではなく、
『DataGridView1 の選択行すべて』への反映とするのならば、

 ・Form2 に選択通知イベントを自作しておく
 ・Form2 の ButtonSel_Click で、選択した値を
  選択通知イベントとして RaiseEvent する
 ・Form1 側は、子画面から選択通知をイベントして受け取った時に、
  イベント引数で得た選択値を、自身の DataGridView1 に反映させる

という手法が使えるかと思います。

参考までに、自作イベントを用いたフォーム間のデータ送信例を貼っておきます。
http://rucio.cloudapp.net/ThreadDetail.aspx?ThreadId=30458
引用返信 編集キー/
■94144 / inTopicNo.7)  Re[6]: DataGridViewで選択した値を取得して別画面に表示し
□投稿者/ あい (12回)-(2020/03/19(Thu) 13:51:14)
2020/03/19(Thu) 14:03:31 編集(投稿者)

No94143 (魔界の仮面弁士 さん) に返信

すみません、本題に入る前に質問とは異なることなんですが本題に入れないので質問させてください。

MySqlでデータを持ってきているのですが、データを表示しているCell「DataGridViewTextBoxColumn」と「DataGridViewTextBoxColumn」の間に「DataGridViewButtonColumn」を置いているのですが、間に配置するとCellContentClickイベントが反応しないみたいです。
最後尾に配置したところイベントが発行しました。
仕様的に今と変更したくないので、何かいい方法はありませんでしょうか?
引用返信 編集キー/
■94145 / inTopicNo.8)  Re[7]: DataGridViewで選択した値を取得して別画面に表示し
□投稿者/ 魔界の仮面弁士 (2623回)-(2020/03/19(Thu) 14:18:57)
No94144 (あい さん) に返信
> MySqlでデータを持ってきているのですが

DataTable 自体には、「どこから取得したデータなのか」と言う情報は記録されていないので、
元データが CSV だろうと MySql だろうと SQLite だろうと XML だろうと、
DataGridView の動作は変化しないはずです。


> 間に配置するとCellContentClickイベントが反応しないみたいです。

CellContentClick が全く呼ばれないのでしょうか?
それともイベントは発生するけれども、引数 e の内容が想定外ということでしょうか?
あるいは操作方法によって、発生する場合と発生しない場合があるのでしょうか?


なお CellContentClick は文字通り、セル内の「コンテンツ」領域をクリックしないと反応しません。

セル内に Padding で設定された余白部などへのクリックにも反応させたいのであれば、
CellContentClick の代わりに CellMouseClick を使うこともできます。ただしこの場合、
セル領域外のクリックにも反応するため、e.ColumnIndex と e.RowIndex の両方を
検証する必要があるでしょう。
引用返信 編集キー/
■94146 / inTopicNo.9)  Re[8]: DataGridViewで選択した値を取得して別画面に表示し
□投稿者/ あい (13回)-(2020/03/19(Thu) 14:32:04)
No94145 (魔界の仮面弁士 さん) に返信
> DataTable 自体には、「どこから取得したデータなのか」と言う情報は記録されていないので、
> 元データが CSV だろうと MySql だろうと SQLite だろうと XML だろうと、
> DataGridView の動作は変化しないはずです。
何からデータを持ってこようが関係ないという事ですね。

> CellContentClick が全く呼ばれないのでしょうか?
> それともイベントは発生するけれども、引数 e の内容が想定外ということでしょうか?
> あるいは操作方法によって、発生する場合と発生しない場合があるのでしょうか?
全く呼ばれません。Privet Sub.....のところでブレークポイントを止めてやってみたのですが、止まりませんでした。
何故かボタンセルの配置を最後尾に変更すると発行されます。

> セル内に Padding で設定された余白部などへのクリックにも反応させたいのであれば、
> CellContentClick の代わりに CellMouseClick を使うこともできます。ただしこの場合、
> セル領域外のクリックにも反応するため、e.ColumnIndex と e.RowIndex の両方を
> 検証する必要があるでしょう。

ボタンさえ押せれば大丈夫です。
一応、CellMouseClick でやってみたのですが、ボタンだけ反応しませんでした。
他のセルのクリックでは反応したのですが、、、何故でしょう、、、。
DataPropertyNameを設定していなのは関係ないですよね?

引用返信 編集キー/
■94147 / inTopicNo.10)  Re[9]: DataGridViewで選択した値を取得して別画面に表示し
□投稿者/ 魔界の仮面弁士 (2624回)-(2020/03/19(Thu) 14:47:15)
No94146 (あい さん) に返信
> 何故かボタンセルの配置を最後尾に変更すると発行されます。

位置に依存するようであれば、試しに DataGridView の
AllowUserToOrderColumns = True に設定しておき、
実行時に列位置をドラッグで入れかえた場合にも、
イベントが発生しなくなるのか、検証してみてください。

> 一応、CellMouseClick でやってみたのですが、ボタンだけ反応しませんでした。

Handles 句の付け忘れ…とも違うようですね。
あとは座標絡みのトラブルという事で、高DPI設定の問題が起きていないか…とか。


新規プロジェクトに、単純な DataTable と DataGridView を貼ってみて
そこに同じように設定した場合も、現象が再現しますか?

再現性のある最小限のサンプルを作成出来たら、
それを見せて頂けると話が早そうです。


> DataPropertyNameを設定していなのは関係ないですよね?

No94143 のコードを書いた際には、ボタン列は非連結にしていましたが
ボタンが反応しました。
引用返信 編集キー/
■94148 / inTopicNo.11)  Re[10]: DataGridViewで選択した値を取得して別画面に表示し
□投稿者/ あい (14回)-(2020/03/19(Thu) 15:20:13)
No94147 (魔界の仮面弁士 さん) に返信
> 新規プロジェクトに、単純な DataTable と DataGridView を貼ってみて

新規でプロジェクトを作成し同じようにやってみたら、できました(*_*;
一旦元画面の方を削除して、新規で作成した方から元の方に張り替えたら動きました、、、

んーー、原因は不明です。
お手数おかけしましたm(_ _"m)

本題の方に入ります。
No94143 で作成していただいたやり方でやてみますので、少々お待ちください。
引用返信 編集キー/
■94149 / inTopicNo.12)  Re[6]: DataGridViewで選択した値を取得して別画面に表示し
□投稿者/ あい (15回)-(2020/03/19(Thu) 15:52:09)
No94143 (魔界の仮面弁士 さん) に返信
>   Private Sub ButtonSel_Click(sender As Object, e As EventArgs) Handles ButtonSel.Click
>     ' No39258 のソースは「選択行の先頭」を読み取ってましたが、
>     ' 下記は「現在行」を読み取るようにしています。
>     Dim row = Me.DataGridView2.CurrentRow
>     If row Is Nothing OrElse parentRow Is Nothing Then
>       MessageBox.Show(Me, "行が選択されていません")
>     Else
>       parentRow.Cells(0).Value = row.Cells(0).Value
>     End If
>   End Sub

エラーはありません、ただ「parentRow.Cells(0).Value = row.Cells(0).Value」
のところのValue値がNothingでした。

Form2の画面をを閉じる際はMe.Closeでいいんですよね?
引用返信 編集キー/
■94150 / inTopicNo.13)  Re[7]: DataGridViewで選択した値を取得して別画面に表示し
□投稿者/ 魔界の仮面弁士 (2625回)-(2020/03/19(Thu) 18:15:15)
No94149 (あい さん) に返信
> エラーはありません、ただ「parentRow.Cells(0).Value = row.Cells(0).Value」
> のところのValue値がNothingでした。

どちらの Value が Nothing なのでしょうか?
また、読み込むセルと書き込むセルは、双方とも .Cells(0) で間違いないでしょうか?
引用返信 編集キー/
■94161 / inTopicNo.14)  Re[8]: DataGridViewで選択した値を取得して別画面に表示し
□投稿者/ あい (16回)-(2020/03/23(Mon) 09:30:40)
2020/03/23(Mon) 09:31:19 編集(投稿者)

No94150 (魔界の仮面弁士 さん) に返信
> また、読み込むセルと書き込むセルは、双方とも .Cells(0) で間違いないでしょうか?

.Cells(0)内の取得する数字が間違っていました。
parentRow.Cells(4).Value = row.Cells(3).Valueと変更したところ無事取得することができました。

下記修正したコードです。

【Form1 側】
Private Sub DataGridView1_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick
  'ボタン列がクリックされた時
  If e.RowIndex >= 0 AndAlso TypeOf DataGridView1.Columns(e.ColumnIndex) Is DataGridViewButtonColumn Then
    'その行を取得して
    Dim row = DataGridView1.Rows(e.RowIndex)
    ' Dim sourceRow As DataRow = DirectCast(row.DataBoundItem, DataRowView).Row
    '自作の共有メソッドに渡して、Form2 をモーダルダイアログとして開く
    Form2.ShowExampleDialog(Me, row)
  End If
End Sub


【Form2 側】
Public Class Form2
  Private parentRow As DataGridViewRow

  Public Shared Sub ShowExampleDialog(owner As IWin32Window, parentRow As DataGridViewRow)
    Using f2 As New Form2()
      f2.parentRow = parentRow
      f2.ShowDialog(owner)
    End Using
  End Sub

  Private Sub ButtonSel_Click(sender As Object, e As EventArgs) Handles ButtonSel.Click
    '「現在行」を読み取るようにしています。
    Dim row = Me.DataGridView2.CurrentRow
    If row Is Nothing OrElse parentRow Is Nothing Then
      MessageBox.Show(Me, "行が選択されていません")
    Else
      parentRow.Cells(4).Value = row.Cells(3).Value
    End If
  End Sub
End Class

親身に回答して下さりありがとうございました。
解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


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

このトピックに書きこむ