Bagaimana menangani acara klik di Kolom Tombol di Datagridview?

139

Saya mengembangkan aplikasi windows menggunakan C #. Saya menggunakan DataGridViewuntuk menampilkan data. Saya telah menambahkan kolom tombol di dalamnya. Saya ingin tahu bagaimana saya bisa menangani event klik pada tombol itu di DataGridView.

Himadri
sumber
1
Apakah Anda menambahkan tombol secara terprogram (seperti yang saya duga adalah satu-satunya cara)?
XstreamINsanity
Ada banyak jawaban yang tersedia untuk ini secara online. Apa yang membuat Anda kesulitan?
Joshua Evensen
1
@Joshua Saya mendapat banyak jawaban di internet tetapi tidak benar-benar tahu apa yang harus dilakukan dan kapan harus memulai. Saya telah menambahkan tombol di datagridview saya hanya tidak tahu bagaimana menangani acara kliknya.
Himadri

Jawaban:

272

Anda telah menambahkan tombol ke Anda DataGridViewdan Anda ingin menjalankan beberapa kode saat diklik.
Sangat mudah - cukup ikuti langkah-langkah ini:

Larangan:

Pertama, inilah yang TIDAK harus dilakukan:

Saya akan menghindari saran di beberapa jawaban lain di sini dan bahkan disediakan oleh dokumentasi di MSDN untuk membuat kode keras indeks kolom atau nama kolom untuk menentukan apakah tombol diklik. Peristiwa klik mendaftar untuk seluruh kisi, jadi entah bagaimana Anda perlu menentukan bahwa sebuah tombol telah diklik, tetapi Anda tidak boleh melakukannya dengan mengasumsikan bahwa tombol Anda berada di nama kolom atau indeks tertentu ... ada cara yang lebih mudah ...

Juga, berhati-hatilah dengan acara mana yang ingin Anda tangani. Sekali lagi, dokumentasi dan banyak contoh salah. Kebanyakan contoh menangani fileCellClick peristiwa yang akan diaktifkan:

saat bagian mana pun dari sel diklik.

... tetapi juga akan menembak setiap kali baris header diklik. Ini memerlukan penambahan kode ekstra hanya untuk menentukan apakah e.RowIndexnilainya kurang dari 0

Sebaliknya, tangani file CellContentClick yang hanya terjadi:

saat konten di dalam sel diklik

Untuk alasan apa pun, file tajuk kolom juga dianggap sebagai 'konten' dalam sel, jadi kita masih harus memeriksanya di bawah.

Yang Harus Dilakukan:

Jadi, inilah yang harus Anda lakukan:

Pertama, transmisikan pengirim untuk mengetikDataGridView untuk mengekspos properti internalnya pada waktu desain. Anda bisa memodifikasi tipe pada parameter, tapi itu terkadang bisa membuat penambahan atau penghapusan penangan menjadi rumit.

Selanjutnya, untuk melihat apakah ada tombol yang diklik, cukup periksa untuk memastikan bahwa kolom yang memunculkan acara memiliki tipe DataGridViewButtonColumn. Karena kita sudah mentransmisikan pengirim untuk mengetik DataGridView, kita bisa mendapatkan Columnskoleksi dan memilih kolom saat ini menggunakan e.ColumnIndex. Kemudian periksa apakah objek itu berjenis DataGridViewButtonColumn.

Tentu saja, jika Anda perlu membedakan beberapa tombol per kisi, Anda dapat memilih berdasarkan nama kolom atau indeks, tetapi itu seharusnya tidak menjadi pemeriksaan pertama Anda. Selalu pastikan sebuah tombol diklik terlebih dahulu dan kemudian tangani yang lainnya dengan tepat. Dalam kebanyakan kasus di mana Anda hanya memiliki satu tombol per grid, Anda dapat langsung melompat ke balapan.

Menyatukan semuanya:

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

Pembaruan 1 - Acara Khusus

Jika Anda ingin sedikit bersenang-senang, Anda dapat menambahkan acara Anda sendiri untuk dimunculkan setiap kali tombol diklik pada datagrid. Anda tidak dapat menambahkannya ke DataGrid itu sendiri, tanpa menjadi berantakan dengan warisan dll, tetapi Anda dapat menambahkan kejadian khusus ke formulir Anda dan mengaktifkannya jika perlu. Ini sedikit lebih banyak kode, tetapi keuntungannya adalah Anda telah memisahkan apa yang ingin Anda lakukan ketika sebuah tombol diklik dengan cara menentukan apakah sebuah tombol diklik.

Cukup nyatakan sebuah acara, angkat jika perlu, dan tangani. Ini akan terlihat seperti ini:

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

Perbarui 2 - Kisi Diperluas

Apa yang hebat adalah jika kita bekerja dengan grid yang melakukan hal-hal ini untuk kita. Kita bisa menjawab pertanyaan awal dengan mudah: you've added a button to your DataGridView and you want to run some code when it's clicked. Berikut pendekatan yang memperluas file DataGridView. Mungkin tidak sepadan dengan kerumitan harus memberikan kontrol khusus dengan setiap perpustakaan, tetapi setidaknya itu secara maksimal menggunakan kembali kode yang digunakan untuk menentukan apakah sebuah tombol diklik.

Cukup tambahkan ini ke perakitan Anda:

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

Itu dia. Jangan pernah menyentuhnya lagi. Pastikan DataGrid Anda adalah tipe DataGridViewExtyang harus bekerja sama persis dengan DataGridView. Selain itu juga akan memunculkan event ekstra yang bisa Anda tangani seperti ini:

Private Sub DataGridView1_ButtonClick(sender As DataGridView, e As DataGridViewCellEventArgs) _
                                      Handles DataGridView1.CellButtonClick
    'TODO - Button Clicked - Execute Code Here
End Sub
KyleMit
sumber
1
Di VB.net Anda tidak perlu memeriksa indeks kolom. Saya menggunakan contoh yang tepat ini untuk dgv dengan dua kolom. Satu kolom yang dapat diedit dan yang kedua dengan tombol hapus. Saya mengklik di seluruh dgv dan acara hanya menyala ketika saya mengklik tombol.
Luminous
3
+1. Namun, dalam kasus kami kolom tersebut adalah DataGridViewColumn generik, dan saya harus memeriksa jenis sel:TypeOf senderGrid.Rows(e.RowIndex).Cells(e.ColumnIndex) Is DataGridViewButtonCell
Dave Johnson
Dilihat dari suara positif dan komentar, saya mengerti ini adalah jawaban yang benar, tetapi ... mengapa semuanya harus selalu begitu rumit! Saya belum mendekati WPF, tapi apakah di sana akan sama?
jj_
1
Kode C # untuk Pembaruan 2public 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
@tonyenkiducx, saya hargai tetapi komentar tersebut bukanlah tempat yang baik untuk menampilkan sintaks alternatif untuk seluruh kelas, terutama yang dapat dengan mudah diturunkan melalui konverter kode . Tentu, orang-orang akan datang ke sini mencari c #, tetapi mereka dapat menyeberang ke sana sendiri dan tidak akan melihat-lihat komentar untuk mencari implementasi. Saya akan (dengan hormat) menyarankan untuk menghapus komentar Anda
KyleMit
15

Itu dijawab sepenuhnya di sini untuk WinForms: DataGridViewButtonColumn Class

dan di sini: Cara: Menanggapi Peristiwa Tombol dalam Kontrol GridView

untuk Asp.Net tergantung pada kontrol yang Anda gunakan. (Pertanyaan Anda mengatakan DataGrid, tetapi Anda sedang mengembangkan aplikasi Windows, jadi kontrol yang akan Anda gunakan adalah DataGridView ...)

David
sumber
Oh, maaf itu salahku. Saya menggunakan DataGridView. Dan saya sudah melihat tautan pertama dari jawaban Anda. Saya tidak mendapatkan dataGridView1_CellClickkode itu. Bisakah Anda memperbarui jawaban Anda dan memberi saya penjelasan.
Himadri
10

Inilah jawaban yang lebih baik:

Anda tidak dapat mengimplementasikan acara yang diklik tombol untuk sel tombol di DataGridViewButtonColumn. Sebagai gantinya, Anda menggunakan acara CellClicked DataGridView dan menentukan apakah acara diaktifkan untuk sel di DataGridViewButtonColumn Anda. Gunakan properti DataGridViewCellEventArgs.RowIndex acara untuk mengetahui baris mana yang diklik.

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);
  }
}

ditemukan di sini: acara klik tombol di datagridview

TechStuffBC
sumber
8

Ini memecahkan masalah saya.

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

Agak terlambat ke tabel di sini, tetapi di c # (vs2013) Anda juga tidak perlu menggunakan nama kolom, pada kenyataannya banyak pekerjaan tambahan yang diusulkan beberapa orang sama sekali tidak diperlukan.

Kolom sebenarnya dibuat sebagai anggota wadah (formulir, atau kontrol pengguna tempat Anda meletakkan DataGridView). Dari kode desainer (hal-hal yang tidak seharusnya Anda edit kecuali ketika desainer merusak sesuatu), Anda akan melihat sesuatu seperti:

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;

Jadi di handler CellContentClick, selain memastikan bahwa indeks baris bukan 0, Anda hanya perlu memeriksa apakah kolom yang diklik memang yang Anda inginkan dengan membandingkan referensi objek:

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();
        }
    }
}

Perhatikan bahwa keindahan dari ini adalah bahwa setiap perubahan nama akan ditangkap oleh kompilator. Jika Anda mengindeks dengan nama teks yang berubah, atau yang salah kapitalisasi, Anda terikat untuk masalah runtime. Di sini Anda benar-benar menggunakan nama objek, yang dibuat oleh desainer berdasarkan nama yang Anda berikan. Tetapi ketidakcocokan apa pun akan diperhatikan oleh kompilator.

Arunas
sumber
+2 untuk menjadi pintar, -1 karena terlalu pintar :-) IMHO tidak ada kata terlambat untuk menambahkan komentar ke posting lama, karena banyak orang seperti saya masih mencari jawaban di stackoverflow.
JonP
2

Berikut ini cuplikan kode saya untuk mengaktifkan peristiwa klik dan meneruskan nilainya ke formulir lain:

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();

        }
    }
pendatang
sumber
2

Dengan asumsi misalnya DataGridViewmemiliki kolom seperti yang diberikan di bawah ini dan item terikat datanya adalah tipe PrimalPalletAnda dapat menggunakan solusi yang diberikan di bawah ini.

masukkan deskripsi gambar di sini

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.
        }
    }
}

Lebih aman mengakses kolom secara langsung daripada menggunakan dataGridView1.Columns["MyColumnName"]dan tidak perlu mengurai senderke kolom DataGridViewkarena tidak diperlukan.

Ryfcia
sumber
0

baiklah, aku akan menggigit.

Anda harus melakukan sesuatu seperti ini - jelas itu semua metacode.

button.Click += new ButtonClickyHandlerType(IClicked_My_Button_method)

yang "mengaitkan" metode IClicked_My_Button_method ke acara Klik tombol. Sekarang, setiap kali acara "dipecat" dari dalam kelas pemilik, metode kami juga akan dipecat.

Di IClicked_MyButton_method Anda hanya menempatkan apa pun yang Anda inginkan terjadi saat Anda mengkliknya.

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.
}

Detail sebenarnya di sini terserah Anda, tetapi jika ada hal lain yang Anda lewatkan secara konseptual, beri tahu saya dan saya akan mencoba membantu.

Joshua Evensen
sumber
di mana pun Anda ingin hubungan itu terjadi. Secara umum, itu mungkin akan masuk ke konstruktor formulir Anda setelah datagridview diinisialisasi.
Joshua Evensen
Dari mana Anda akan mendapatkan tombolnya !?
Peter - Kembalikan Monica
0

Sebagian besar solusi yang dipilih salah, karena tidak dapat berfungsi dengan beberapa tombol dalam satu baris.

Solusi terbaik adalah kode berikut:

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");
            }
        }
Andrew
sumber
0

cukup tambahkan ToList()metode ke akhir daftar Anda, di mana mengikat ke datagridview DataSource:

dataGridView1.DataSource = MyList.ToList();
nima khankhanizadeh
sumber
0

Anda dapat mencoba yang ini, Anda tidak akan terlalu peduli dengan urutan kolomnya.

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

Misalnya untuk ClickCell Event di Windows Forms.

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);
                }

Salam :)

Diego Mauricio Guerrero
sumber
0

Jika seseorang menggunakan C # (atau lihat Catatan tentang VB.NET di bawah) dan telah mencapai titik ini, tetapi masih macet, silakan baca terus.

Jawaban Joshua membantu saya, tetapi tidak sepenuhnya. Anda akan melihat Peter bertanya "Dari mana Anda akan mendapatkan tombol itu?", Tetapi tidak dijawab.

Satu-satunya cara itu berhasil bagi saya adalah dengan melakukan salah satu hal berikut untuk menambahkan event hander saya (setelah mengatur DataGridView's DataSource ke DataTable saya dan setelah menambahkan DataGridViewButtonColumn ke DataGridView):

Antara:

dataGridView1.CellClick += new DataGridViewCellEventHandler(dataGridView1_CellClick);

atau:

dataGridView1.CellContentClick += new DataGridViewCellEventHandler(dataGridView1_CellContentClick);

Dan kemudian tambahkan metode handler (baik dataGridView1_CellClick atau dataGridView1_CellContentClick) yang ditunjukkan dalam berbagai jawaban di atas.

Catatan: VB.NET berbeda dari C # dalam hal ini, karena kita cukup menambahkan klausa Handles ke tanda tangan metode kita atau mengeluarkan pernyataan AddHandler seperti yang dijelaskan dalam dokumen Microsoft " Cara: Memanggil Penangan Peristiwa dalam Visual Basic "

clairestreb.dll
sumber
0

Anda akan menambahkan kolom tombol seperti ini di dataGridView Anda

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


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

Kemudian Anda dapat menambahkan beberapa tindakan di dalam acara klik sel. Saya menemukan ini adalah cara termudah untuk melakukannya.

    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.
         }


    }

Saya menemukan bahwa acara Klik Seluler sering berlangganan secara otomatis. Jadi saya tidak membutuhkan kode di bawah ini. Namun, jika acara klik sel Anda tidak berlangganan, tambahkan baris kode ini untuk dataGridView Anda.

     this.dataGridView.CellClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView_CellClick);
auto9817
sumber