1. ホーム
  2. c#

[解決済み] Datagridviewのボタン列のクリックイベントを処理するには?

2022-04-27 18:29:44

質問

C#を使用してWindowsアプリケーションを開発しています。私は、以下のものを使用しています。 DataGridView を使用してデータを表示します。その中にボタン列を追加しました。そのボタンのクリックイベントを DataGridView .

解決方法は?

にボタンを追加しました。 DataGridView クリックされたときに何らかのコードを実行させたい。

簡単です。以下のステップを踏むだけです。

注意事項

まず、以下の通りです。 NOT を行うことです。

私は、ここでの他のいくつかの回答での提案や、さらに、その回答が提供した のドキュメントを参照してください。 ボタンがクリックされたかどうかを判断するために、列インデックスまたは列名をハードコードする必要があります。 クリックイベントはグリッド全体に対して登録されるので、何らかの方法でボタンがクリックされたことを判断する必要がありますが、ボタンが特定の列名やインデックスに存在すると仮定してそれを行うべきではありません...より簡単な方法があります...。

また、どのイベントを処理するかは注意が必要です。 これもまた、ドキュメントや多くの例で間違っています。 ほとんどの例では CellClick イベントが発生します。

セルのどこかがクリックされたとき。

...しかし ヘッダーがクリックされました。 このため、単に e.RowIndex が0より小さい場合

代わりに CellContentClick だけが発生します。

セル内のコンテンツがクリックされたとき

何らかの理由で ヘッダもセル内の「コンテンツ」とみなされるので、以下でもそのチェックをする必要があります。

ドス

では、どうすればいいのか、ご紹介しましょう。

まず キャスト と入力すると、送信者は DataGridView を使用すると、設計時に内部プロパティを公開することができます。 パラメータで型を変更することもできますが、その場合、ハンドラの追加や削除が面倒になる場合があります。

次に、ボタンがクリックされたかどうかを確認するには、イベントを発生させた列の型が DataGridViewButtonColumn . なぜなら、すでに送信者をキャストして DataGridView を取得することができます。 Columns コレクションを作成し、現在のカラムを選択するには e.ColumnIndex . 次に、そのオブジェクトが DataGridViewButtonColumn .

もちろん、グリッドごとに複数のボタンを区別する必要がある場合は、カラム名やインデックスに基づいて選択することができますが、それは最初のチェックではありません。 ボタンがクリックされたことをまず確認してから、それ以外のことを適切に処理するようにしましょう。 1つのグリッドにボタンが1つしかない場合、ほとんどの場合、すぐにレースに参加することができます。

すべてをまとめる

C#

private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    var senderGrid = (DataGridView)sender;

    if (senderGrid.Columns[e.ColumnIndex] is DataGridViewButtonColumn &&
        e.RowIndex >= 0)
    {
        //TODO - Button Clicked - Execute Code Here
    }
}

VB

Private Sub DataGridView1_CellContentClick(sender As System.Object, e As DataGridViewCellEventArgs) _
                                            Handles DataGridView1.CellContentClick
    Dim senderGrid = DirectCast(sender, DataGridView)

    If TypeOf senderGrid.Columns(e.ColumnIndex) Is DataGridViewButtonColumn AndAlso
        e.RowIndex >= 0 Then
        'TODO - Button Clicked - Execute Code Here
    End If

End Sub


アップデート1 - カスタムイベント

もし、少し楽しみたいのであれば、DataGrid上でボタンがクリックされるたびに発生する独自のイベントを追加することができます。 データグリッドそのものにイベントを追加することはできませんが、フォームにカスタムイベントを追加し、適切なタイミングでイベントを発生させることができます。 少しコードが多くなりますが、ボタンがクリックされたときに何をしたいかと、ボタンがクリックされたかどうかを判断する方法を分離することができるという利点があります。

イベントを宣言し、適切なタイミングでイベントを発生させ、それを処理するだけです。 こんな感じになります。

Event DataGridView1ButtonClick(sender As DataGridView, e As DataGridViewCellEventArgs)

Private Sub DataGridView1_CellContentClick(sender As System.Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick
    Dim senderGrid = DirectCast(sender, DataGridView)
    If TypeOf senderGrid.Columns(e.ColumnIndex) Is DataGridViewButtonColumn AndAlso e.RowIndex >= 0 Then
        RaiseEvent DataGridView1ButtonClick(senderGrid, e)
    End If
End Sub

Private Sub DataGridView1_ButtonClick(sender As DataGridView, e As DataGridViewCellEventArgs) Handles Me.DataGridView1ButtonClick
    'TODO - Button Clicked - Execute Code Here
End Sub


アップデート2 - グリッドの拡張

もし、このようなことをやってくれるグリッドがあれば最高です。 最初の質問に簡単に答えることができます。 you've added a button to your DataGridView and you want to run some code when it's clicked . を拡張したアプローチを紹介します。 DataGridView . すべてのライブラリでカスタムコントロールを提供しなければならないという手間に見合うものではないかもしれませんが、少なくとも、ボタンがクリックされたかどうかを判断するために使用するコードを最大限に再利用することができます。

これをアセンブリに追加するだけです。

Public Class DataGridViewExt : Inherits DataGridView

    Event CellButtonClick(sender As DataGridView, e As DataGridViewCellEventArgs)

    Private Sub CellContentClicked(sender As System.Object, e As DataGridViewCellEventArgs) Handles Me.CellContentClick
        If TypeOf Me.Columns(e.ColumnIndex) Is DataGridViewButtonColumn AndAlso e.RowIndex >= 0 Then
            RaiseEvent CellButtonClick(Me, e)
        End If
    End Sub

End Class

これで終わりです。 もう二度と触らないようにしましょう。 データグリッドの型が DataGridViewExt は、DataGridViewと全く同じように動作するはずです。 ただし、追加イベントも発生するので、このように処理することができます。

Private Sub DataGridView1_ButtonClick(sender As DataGridView, e As DataGridViewCellEventArgs) _
    Handles DataGridView1.CellButtonClick
    'TODO - Button Clicked - Execute Code Here
End Sub