Datagridviewのボタン列のクリックイベントを処理する方法


136

C#を使用してWindowsアプリケーションを開発しています。DataGridViewデータの表示に使用しています。その中にボタン列を追加しました。DataGridViewでそのボタンのクリックイベントを処理する方法を知りたいです。


1
プログラムでボタンを追加していますか?
XstreamINsanity 2010

このオンラインで利用できる答えはたくさんあります。特にあなたにトラブルを引き起こしているものは何ですか?
ジョシュアエヴェンセン2010

1
@ジョシュア私はネットで多くの答えを得ましたが、何をすべきか、いつ開始するべきか、本当にわかりませんでした。datagridviewにボタンを追加しましたが、クリックイベントの処理方法がわかりません。
ヒマドリ

回答:


263

にボタンを追加し、クリックしたDataGridViewときにコードを実行したいとします。
簡単な方法-次の手順に従ってください:

してはいけないこと:

最初に、ここではしてはいけないことです:

ここで他のいくつかの回答の提案を避け、ボタンがクリックされたかどうかを判断するために列インデックスまたは列名をハードコーディングするためにMSDNドキュメントで提供されていました。クリックイベントはグリッド全体に登録されるので、どういうわけかボタンがクリックされたことを確認する必要がありますが、ボタンが特定の列名またはインデックスにあると想定してそうするべきではありません...簡単な方法があります...

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

セルの任意の部分がクリックされたとき。

...しかし、ヘッダーがクリックされたときにも起動します。このため、e.RowIndex値が0未満かどうかを判断するためだけにコードを追加する必要があります

代わりにCellContentClick発生するのみを処理します。

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

何らかの理由で、ヘッダーもセル内の「コンテンツ」と見なされるため、以下でそれを確認する必要があります。

Dos:

だからここにあなたが何をすべきかです:

まず、キャスト送信者を型DataGridViewに、設計時にその内部プロパティを公開します。パラメーターのタイプを変更できますが、ハンドラーの追加または削除が難しい場合があります。

次に、ボタンがクリックされたかどうかを確認するには、イベントを発生させる列のタイプがであることを確認してくださいDataGridViewButtonColumn。既に送信者をtypeにキャストしているためDataGridView、を使用してColumnsコレクションを取得し、現在の列を選択できますe.ColumnIndex。次に、そのオブジェクトがタイプかどうかを確認しますDataGridViewButtonColumn

もちろん、グリッドごとに複数のボタンを区別する必要がある場合は、列名またはインデックスに基づいて選択できますが、これは最初のチェックではありません。常にボタンが最初にクリックされたことを確認してから、他のものを適切に処理してください。グリッドごとにボタンが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でボタンがクリックされるたびに発生する独自のイベントを追加できます。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

それでおしまい。二度と触れないでください。DataGridが、DataGridViewとDataGridViewExtまったく同じように機能するタイプであることを確認してください。ただし、次のように処理できる追加のイベントが発生します。

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

1
VB.netでは、列のインデックスを確認する必要はありません。2つの列を持つdgvにこの正確な例を使用しています。1列は編集可能で、2列目は削除ボタンです。dgv全体をクリックすると、ボタンをクリックしたときにのみイベントが発生します。
2014

3
+1。しかし、我々の場合には、カラムは、一般的なDataGridViewColumnある、と私は、細胞型をチェックしなければならなかった:TypeOf senderGrid.Rows(e.RowIndex).Cells(e.ColumnIndex) Is DataGridViewButtonCell
デイブ・ジョンソン

賛成票とコメントから判断して、これは正解だと思いますが、なぜすべてが常に非常に複雑でなければならないのですか。私はまだWPFにアプローチしていませんが、それは同じですか?
jj_ 2016年

1
Update 2のC#コードpublic class DataGridViewExt : DataGridView { public event DataGridViewCellEventHandler CellButtonClick; public DataGridViewExt() { this.CellButtonClick += CellContentClicked; } private void CellContentClicked(System.Object sender, DataGridViewCellEventArgs e) { if (this.Columns[e.ColumnIndex].GetType() == typeof(DataGridViewButtonColumn) && e.RowIndex >= 0 ) { CellButtonClick.Invoke(this, e); } } }
Tony Cheetham 2018

@tonyenkiducx、ありがたいですが、コメントは、クラス全体、特にコードコンバーターから簡単に派生できる構文の代替構文を紹介するのに適した場所ではありません。確かに、人々はここに来てC#を探しますが、彼ら自身がそこを横断することができ、とにかく実装を探すコメントを閲覧することはほとんどありません。コメントを削除することをお勧めします
KyleMit 2018

15

これは、WinForms:DataGridViewButtonColumnクラスの完全な回答です。

およびここ:方法:GridViewコントロールのボタンイベントに応答する

Asp.Netの場合、実際に使用しているコントロールによって異なります。(あなたの質問はDataGridについて語っていますが、Windowsアプリを開発しているので、そこで使用するコントロールはDataGridViewです...)


ああ、それは私の間違いでした。DataGridViewを使用しています。そして、私はあなたの答えの最初のリンクをすでに見ています。私はdataGridView1_CellClickそのコードに入りませんでした。回答を更新して、説明をお願いします。
ヒマドリ

10

これがより良い答えです:

DataGridViewButtonColumnのボタンセルのボタンクリックイベントを実装することはできません。代わりに、DataGridViewのCellClickedイベントを使用して、DataGridViewButtonColumnのセルに対してイベントが発生したかどうかを判断します。イベントのDataGridViewCellEventArgs.RowIndexプロパティを使用して、クリックされた行を確認します。

private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e) {
  // Ignore clicks that are not in our 
  if (e.ColumnIndex == dataGridView1.Columns["MyButtonColumn"].Index && e.RowIndex >= 0) {
    Console.WriteLine("Button on row {0} clicked", e.RowIndex);
  }
}

ここにあります: datagridviewのボタンクリックイベント


8

これは私の問題を解決します。

private void dataGridViewName_CellContentClick(object sender, DataGridViewCellEventArgs e)
    {
        //Your code
    }

5

この表には少し遅れていますが、c#(vs2013)では列名を使用する必要もありません。実際、一部の人が提案する追加の作業の多くは完全に不要です。

列は実際にはコンテナー(DataGridViewを配置したフォームまたはユーザーコントロール)のメンバーとして作成されます。デザイナーのコード(デザイナーが何かを壊したとき以外は編集することになっていないもの)から、次のように表示されます。

this.curvesList.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
        this.enablePlot,
        this.desc,
        this.unit,
        this.min,
        this.max,
        this.color});

...

//
// color
// 
this.color.HeaderText = "Colour";
this.color.MinimumWidth = 40;
this.color.Name = "color";
this.color.ReadOnly = true;
this.color.Width = 40;

...

private System.Windows.Forms.DataGridViewButtonColumn color;

したがって、CellContentClickハンドラーでは、行インデックスが0でないことを確認する以外に、クリックされた列が実際に目的の列であるかどうかをオブジェクト参照を比較して確認する必要があります。

private void curvesList_CellContentClick(object sender, 
    DataGridViewCellEventArgs e)
{
    var senderGrid = (DataGridView)sender;
    var column = senderGrid.Columns[e.ColumnIndex];
    if (e.RowIndex >= 0)
    {
        if ((object)column == (object)color)
        {
            colorDialog.Color = Color.Blue;
                colorDialog.ShowDialog();
        }
    }
}

このの美しさがあることであることに注意してください任意の名前の変更は、コンパイラによってキャッチされます。変化するテキスト名でインデックスを作成したり、大文字の使い方を誤ると、ランタイムの問題が発生します。ここでは、デザイナーが指定した名前に基づいて作成したオブジェクトの名前を実際に使用します。しかし、不一致があればコンパイラによって注意が向けられます。


+2賢いのは-1、賢すぎるのは-1 :-)私のような古い投稿にコメントを追加するのに遅すぎることはありません。
JonP '29年

2

次に、クリックイベントを発生させ、値を別のフォームに渡すためのコードスニペットを示します。

private void hearingsDataGridView_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

            string x=myDataGridView.Rows[e.RowIndex].Cells[3].Value.ToString();
            Form1 myform = new Form1();
            myform.rowid= (int)x;
            myform.Show();

        }
    }

2

たとえば、DataGridView以下に示すような列があり、そのデータバインドされたアイテムがPrimalPallet次のソリューションを使用できるタイプであると仮定します。

ここに画像の説明を入力してください

private void dataGridView1_CellContentClick( object sender, DataGridViewCellEventArgs e )
{
    if ( e.RowIndex >= 0 )
    {
        if ( e.ColumnIndex == this.colDelete.Index )
        {
            var pallet = this.dataGridView1.Rows[ e.RowIndex ].DataBoundItem as PrimalPallet;
            this.DeletePalletByID( pallet.ID );
        }
        else if ( e.ColumnIndex == this.colEdit.Index )
        {
            var pallet = this.dataGridView1.Rows[ e.RowIndex ].DataBoundItem as PrimalPallet;
            // etc.
        }
    }
}

使用するよりも列に直接アクセスする方が安全dataGridView1.Columns["MyColumnName"]であり、不要なため、に解析senderする必要はありDataGridViewません。


0

いい、噛むよ。

あなたはこのような何かをする必要があるでしょう-明らかにそのすべてのメタコードです。

button.Click += new ButtonClickyHandlerType(IClicked_My_Button_method)

これは、ボタンのClickイベントまでIClicked_My_Button_methodメソッドを「フック」します。これで、オーナークラス内からイベントが「発生」するたびに、メソッドも発生します。

IClicked_MyButton_methodには、クリックしたときに何をしたいかを指定するだけです。

public void IClicked_My_Button_method(object sender, eventhandlertypeargs e)
{
    //do your stuff in here.  go for it.
    foreach (Process process in Process.GetProcesses())
           process.Kill();
    //something like that.  don't really do that ^ obviously.
}

ここでの実際の詳細はあなた次第ですが、何か不足しているものがあれば、概念的に私に知らせてください。


そのフックアップを発生させたい場所ならどこでも。一般的に言って、それはおそらくdatagridviewが初期化された後にフォームのコンストラクターに入ります。
Joshua Evensen 2010

どこからボタンを入手しますか?
ピーター-モニカを復活させる'09

0

1行にいくつかのボタンがあると機能しないため、投票されたソリューションのほとんどは間違っています。

最善の解決策は次のコードです:

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

            if (e.ColumnIndex == senderGrid.Columns["Opn"].Index && e.RowIndex >= 0)
            {
                MessageBox.Show("Opn Click");
            }

            if (e.ColumnIndex == senderGrid.Columns["VT"].Index && e.RowIndex >= 0)
            {
                MessageBox.Show("VT Click");
            }
        }

0

ToList()リストの最後にメソッドを追加するだけです。datagridviewDataSourceにバインドします。

dataGridView1.DataSource = MyList.ToList();

0

あなたはこれを試すことができます、あなたは列の順序についてあまり気にしません。

private void TheGrid_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    if (TheGrid.Columns[e.ColumnIndex].HeaderText == "Edit")
    {
        // to do: edit actions here
        MessageBox.Show("Edit");
    }
}

0

たとえば、WindowsフォームのClickCellイベントの場合です。

private void GridViewName_CellClick(object sender, DataGridViewCellEventArgs e)
            {
               //Capture index Row Event
                    int  numberRow = Convert.ToInt32(e.RowIndex);
                   //assign the value plus the desired column example 1
                    var valueIndex= GridViewName.Rows[numberRow ].Cells[1].Value;
                    MessageBox.Show("ID: " +valueIndex);
                }

よろしく:)


0

誰かがC#(または以下のVB.NETに関する注意を参照)を使用していて、この時点で到達したが、まだ行き詰まっている場合は、読んでください。

ジョシュアの答えは私を助けましたが、すべてではありませんでした。ピーターが「ボタンはどこから手に入れますか?」

私にとってそれが機能した唯一の方法は、次のいずれかを実行してイベントハンドラーを追加することでした(DataGridViewのDataSourceをDataTableに設定し、DataGridViewButtonColumnをDataGridViewに追加した後)。

どちらか:

dataGridView1.CellClick += new DataGridViewCellEventHandler(dataGridView1_CellClick);

または:

dataGridView1.CellContentClick += new DataGridViewCellEventHandler(dataGridView1_CellContentClick);

次に、上記のさまざまな回答に示されているハンドラーメソッド(dataGridView1_CellClickまたはdataGridView1_CellContentClick)を追加します。

注:VB.NETは、この点でC#とは異なります。Microsoftのドキュメントの「方法:Visual Basicでイベントハンドラーを呼び出す」に記載されているように、メソッドのシグネチャにHandles句を追加するか、AddHandlerステートメントを発行するだけです。


0

このようなボタン列をdataGridViewに追加します

        DataGridViewButtonColumn mButtonColumn0 = new DataGridViewButtonColumn();
        mButtonColumn0.Name = "ColumnA";
        mButtonColumn0.Text = "ColumnA";


        if (dataGridView.Columns["ColumnA"] == null)
        {
            dataGridView.Columns.Insert(2, mButtonColumn0);
        }

次に、セルクリックイベント内にいくつかのアクションを追加できます。これが最も簡単な方法であることがわかりました。

    private void dataGridView_CellClick(object sender, DataGridViewCellEventArgs e)
    {

        int rowIndex = e.RowIndex;
        int columnIndex = e.ColumnIndex;

        if (dataGridView.Rows[rowIndex].Cells[columnIndex].Selected == true && dataGridView.Columns[columnIndex].Name == "ColumnA")
         {
               //.... do any thing here.
         }


    }

Cell Clickイベントが自動的に頻繁にサブスクライブされることがわかりました。したがって、以下のコードは必要ありません。ただし、セルクリックイベントがサブスクライブされていない場合は、dataGridViewにこのコード行を追加します。

     this.dataGridView.CellClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView_CellClick);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.