Come gestire l'evento click nella colonna Button in Datagridview?


136

Sto sviluppando un'applicazione Windows usando C #. Sto usando DataGridViewper visualizzare i dati. Ho aggiunto una colonna di pulsanti in questo. Voglio sapere come posso gestire l'evento click su quel pulsante in DataGridView.


1
Stai aggiungendo il pulsante a livello di codice (come sospetto sia l'unico modo)?
XstreamINsanity,

Ci sono molte risposte disponibili per questo online. Cosa ti dà problemi in particolare?
Joshua Evensen,

1
@Joshua Ho avuto molte risposte in rete, ma non avevo davvero idea di cosa fare e quando iniziare. Avevo aggiunto un pulsante nel mio datagridview ma non so come gestire l'evento click.
Himadri,

Risposte:


263

Hai aggiunto un pulsante al tuo DataGridViewe vuoi eseguire un po 'di codice quando viene cliccato.
Facile, basta seguire questi passaggi:

Cosa non fare:

Innanzitutto, ecco cosa NON fare:

Vorrei evitare i suggerimenti in alcune delle altre risposte qui e persino forniti dalla documentazione su MSDN per codificare a fondo l'indice di colonna o il nome della colonna al fine di determinare se è stato fatto clic su un pulsante. L'evento click si registra per l'intera griglia, quindi in qualche modo devi determinare che è stato fatto clic su un pulsante, ma non dovresti farlo supponendo che il tuo pulsante risieda in un particolare nome di colonna o indice ... c'è un modo più semplice ...

Inoltre, fai attenzione a quale evento vuoi gestire. Ancora una volta, la documentazione e molti esempi hanno sbagliato. La maggior parte degli esempi gestisce l' CellClickevento che genererà:

quando si fa clic su qualsiasi parte di una cella.

... ma si attiva anche ogni volta che si fa clic sull'intestazione della riga . Ciò richiede l'aggiunta di un codice aggiuntivo semplicemente per determinare se il e.RowIndexvalore è inferiore a 0

Gestisci invece ciò CellContentClickche si verifica solo:

quando si fa clic sul contenuto all'interno di una cella

Per qualsiasi motivo, anche l' intestazione della colonna è considerata "contenuto" all'interno di una cella, quindi dovremo comunque verificarlo di seguito.

dos:

Quindi, ecco cosa dovresti fare:

Innanzitutto, cast il mittente da digitare DataGridViewper esporre le sue proprietà interne in fase di progettazione. È possibile modificare il tipo sul parametro, ma ciò a volte può rendere complicata l'aggiunta o la rimozione di gestori.

Quindi, per vedere se è stato fatto clic su un pulsante, basta verificare che la colonna che solleva l'evento sia di tipo DataGridViewButtonColumn. Poiché abbiamo già trasmesso il mittente al tipo DataGridView, possiamo ottenere la Columnsraccolta e selezionare la colonna corrente utilizzando e.ColumnIndex. Quindi controlla se l'oggetto è di tipo DataGridViewButtonColumn.

Naturalmente, se devi distinguere tra più pulsanti per griglia, puoi selezionare in base al nome della colonna o all'indice, ma non dovrebbe essere il tuo primo controllo. Assicurati sempre di aver fatto clic prima su un pulsante, quindi gestisci qualsiasi altra cosa in modo appropriato. Nella maggior parte dei casi in cui hai un solo pulsante per griglia, puoi saltare direttamente alle gare.

Mettere tutto insieme:

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

Aggiornamento 1 - Evento personalizzato

Se vuoi divertirti un po ', puoi aggiungere il tuo evento da sollevare ogni volta che fai clic su un pulsante su DataGrid. Non è possibile aggiungerlo al DataGrid stesso, senza diventare disordinato con l'ereditarietà ecc., Ma è possibile aggiungere un evento personalizzato al modulo e attivarlo quando appropriato. È un po 'più di codice, ma il lato positivo è che hai separato ciò che vuoi fare quando si fa clic su un pulsante con come determinare se è stato fatto clic su un pulsante.

Basta dichiarare un evento, sollevarlo quando appropriato e gestirlo. Sarà simile a questo:

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

Aggiornamento 2 - Griglia estesa

Ciò che sarebbe fantastico sarebbe se stessimo lavorando con una griglia che faceva proprio queste cose per noi. Potremmo rispondere alla domanda iniziale facilmente: you've added a button to your DataGridView and you want to run some code when it's clicked. Ecco un approccio che estende il DataGridView. Potrebbe non valere la pena dover fornire un controllo personalizzato con ogni libreria, ma almeno riutilizza al massimo il codice utilizzato per determinare se è stato fatto clic su un pulsante.

Basta aggiungere questo al tuo assieme:

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

Questo è tutto. Non toccarlo mai più. Assicurati che il tuo DataGrid sia di tipo DataGridViewExtche dovrebbe funzionare esattamente come un DataGridView. Tranne che genererà anche un ulteriore evento che puoi gestire in questo modo:

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

1
In VB.net non è necessario controllare l'indice di colonna. Sto usando questo esempio esatto per un dgv con due colonne. Una colonna è modificabile e la seconda con un pulsante di rimozione. Faccio clic su tutto il dgv e l'evento si attiva solo quando faccio clic sul pulsante.
Luminoso

3
+1. Tuttavia, nel nostro caso la colonna è un DataGridViewColumn generico e ho dovuto controllare il tipo di cella:TypeOf senderGrid.Rows(e.RowIndex).Cells(e.ColumnIndex) Is DataGridViewButtonCell
Dave Johnson,

A giudicare da valutazioni e commenti capisco che questa è una risposta corretta, ma ... perché tutto deve essere sempre così complicato! Non mi sono ancora avvicinato al WPF, ma sarebbe lo stesso lì?
jj_

1
Codice C # per l'aggiornamento 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, apprezzato ma i commenti non sono davvero un buon posto per mostrare la sintassi alternativa per un'intera classe, in particolare una che può essere facilmente derivata attraverso un convertitore di codice . Certo, le persone verranno qui alla ricerca di c #, ma possono attraversare da sole lì e non sono in grado di sfogliare i commenti alla ricerca di un'implementazione comunque. Suggerirei (rispettosamente) di eliminare il tuo commento
KyleMit,

15

Questa è una risposta completa qui per WinForms: DataGridViewButtonColumn Class

e qui: Procedura: rispondere agli eventi dei pulsanti in un controllo GridView

per Asp.Net a seconda del controllo che stai effettivamente utilizzando. (La tua domanda dice DataGrid, ma stai sviluppando un'app di Windows, quindi il controllo che useresti è un DataGridView ...)


Oh, scusa è stato un mio errore. Sto usando DataGridView. E vedo già il primo link della tua risposta. Non ho inserito dataGridView1_CellClickquel codice. Puoi aggiornare la tua risposta e darmi una descrizione.
Himadri,

10

Ecco la risposta migliore:

Non è possibile implementare un evento su cui è stato fatto clic per le celle dei pulsanti in DataGridViewButtonColumn. Invece, si utilizza l'evento CellClicked di DataGridView e si determina se l'evento è stato generato per una cella in DataGridViewButtonColumn. Utilizzare la proprietà DataGridViewCellEventArgs.RowIndex dell'evento per scoprire quale riga è stata selezionata.

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

trovato qui: evento clic pulsante in Datagridview


8

Questo risolve il mio problema.

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

5

Un po 'tardi alla tabella qui, ma in c # (vs2013) non è nemmeno necessario utilizzare i nomi delle colonne, in effetti un sacco di lavoro extra che alcune persone propongono è completamente inutile.

La colonna viene effettivamente creata come membro del contenitore (il modulo o il controllo utente in cui hai inserito DataGridView). Dal codice del designer (le cose che non dovresti modificare tranne quando il designer rompe qualcosa), vedresti qualcosa del tipo:

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;

Quindi nel gestore CellContentClick, oltre a garantire che l'indice di riga non sia 0, devi solo verificare se la colonna cliccata è effettivamente quella che desideri confrontando i riferimenti agli oggetti:

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

Si noti che la bellezza di questo è che eventuali modifiche al nome verranno rilevate dal compilatore. Se si indicizza con un nome di testo che cambia o che si capitalizza in modo errato, si è destinati a problemi di runtime. Qui in realtà si utilizza il nome di un oggetto, che il designer crea in base al nome fornito. Ma qualsiasi discrepanza verrà portata alla tua attenzione dal compilatore.


+2 per essere intelligente, -1 per essere troppo intelligente :-) IMHO non è mai troppo tardi per aggiungere un commento a un vecchio post, perché molte persone come me stanno ancora cercando risposte su stackoverflow.
Jon

2

Ecco il mio frammento di codice per attivare l'evento click e passare il valore a un altro modulo:

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

Supponendo ad esempio di DataGridViewavere colonne come indicato di seguito e i relativi elementi associati ai dati sono di tipo PrimalPalletè possibile utilizzare la soluzione fornita di seguito.

inserisci qui la descrizione dell'immagine

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

E 'più sicuro alle colonne di accesso direttamente invece di usare dataGridView1.Columns["MyColumnName"]e non v'è alcuna necessità di analizzare senderil DataGridViewcome non è necessario.


0

bene, ti mordo.

dovrai fare qualcosa del genere - ovviamente è tutto metacode.

button.Click += new ButtonClickyHandlerType(IClicked_My_Button_method)

che "aggancia" il metodo IClicked_My_Button_method fino all'evento Click del pulsante. Ora, ogni volta che l'evento viene "attivato" all'interno della classe del proprietario, verrà attivato anche il nostro metodo.

Nel metodo IClicked_MyButton_ inserisci semplicemente quello che vuoi che accada quando fai clic su di esso.

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

I dettagli effettivi qui dipendono da te, ma se c'è qualcos'altro che ti manca concettualmente fammi sapere e cercherò di aiutarti.


ovunque tu voglia che si verifichi quel collegamento. In generale, ciò andrebbe probabilmente nel costruttore del modulo dopo l'inizializzazione della vista dati.
Joshua Evensen,

Da dove prenderesti il ​​pulsante !?
Peter - Ripristina Monica il

0

La soluzione più votata è sbagliata, poiché non può funzionare con pochi pulsanti in una riga.

La migliore soluzione sarà il seguente codice:

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

aggiungi il ToList()metodo alla fine del tuo elenco, dove si lega a Datagridview DataSource:

dataGridView1.DataSource = MyList.ToList();

0

Puoi provare questo, non ti importerebbe molto sull'ordinamento delle colonne.

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

0

Ad esempio per l'evento ClickCell in Windows Form.

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

Saluti :)


0

Nel caso in cui qualcuno stia usando C # (o vedi Nota su VB.NET di seguito) e abbia raggiunto questo punto, ma è ancora bloccato, continua a leggere.

La risposta di Joshua mi ha aiutato, ma non del tutto. Noterai che Peter ha chiesto "Da dove prenderesti il ​​pulsante?", Ma senza risposta.

L'unico modo in cui ha funzionato per me è stato quello di effettuare una delle seguenti operazioni per aggiungere il mio evento hander (dopo aver impostato l'origine dati di DataGridView su DataTable e dopo aver aggiunto DataGridViewButtonColumn a DataGridView):

O:

dataGridView1.CellClick += new DataGridViewCellEventHandler(dataGridView1_CellClick);

o:

dataGridView1.CellContentClick += new DataGridViewCellEventHandler(dataGridView1_CellContentClick);

Quindi aggiungi il metodo del gestore (dataGridView1_CellClick o dataGridView1_CellContentClick) mostrato nelle varie risposte sopra.

Nota: VB.NET è diverso da C # in questo senso, perché possiamo semplicemente aggiungere una clausola Handles alla firma del nostro metodo o emettere un'istruzione AddHandler come descritto nel documento " Procedura: chiamare un gestore eventi in Visual Basic " del documento Microsoft


0

Aggiungi la colonna dei pulsanti in questo modo in dataGridView

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


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

Quindi è possibile aggiungere alcune azioni all'interno dell'evento clic cella. Ho scoperto che questo è il modo più semplice per farlo.

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


    }

Ho scoperto che l'evento Cell Click viene automaticamente sottoscritto spesso. Quindi non avevo bisogno di questo codice qui sotto. Tuttavia, se l'evento del clic della cella non è sottoscritto, aggiungere questa riga di codice per dataGridView.

     this.dataGridView.CellClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView_CellClick);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.