Comment gérer l'événement de clic dans la colonne de bouton dans Datagridview?

136

Je développe une application Windows en utilisant C #. J'utilise DataGridViewpour afficher des données. J'ai ajouté une colonne de boutons à cela. Je veux savoir comment puis-je gérer l'événement de clic sur ce bouton dans DataGridView.

Himadri
la source
1
Ajoutez-vous le bouton par programme (comme je suppose que c'est le seul moyen)?
XstreamINsanity
Il existe de nombreuses réponses disponibles à ce sujet en ligne. Qu'est-ce qui vous pose des problèmes en particulier?
Joshua Evensen
1
@Joshua J'ai eu beaucoup de réponses sur le net mais je ne savais pas vraiment quoi faire et quand commencer. J'avais ajouté un bouton dans mon datagridview ne sais tout simplement pas comment gérer son événement de clic.
Himadri

Réponses:

263

Vous avez ajouté un bouton à votre DataGridViewet vous souhaitez exécuter du code lorsque l'utilisateur clique dessus.
Easy peasy - suivez simplement ces étapes:

À ne pas faire:

Tout d'abord, voici ce que PAS faut faire:

J'éviterais les suggestions dans certaines des autres réponses ici et même fournies par la documentation de MSDN pour coder en dur l'index de la colonne ou le nom de la colonne afin de déterminer si un bouton a été cliqué. L'événement de clic est enregistré pour l'ensemble de la grille, vous devez donc d'une manière ou d'une autre déterminer qu'un bouton a été cliqué, mais vous ne devriez pas le faire en supposant que votre bouton réside dans un nom de colonne ou un index particulier ... il existe un moyen plus simple ...

Faites également attention à l'événement que vous souhaitez gérer. Encore une fois, la documentation et de nombreux exemples se trompent. La plupart des exemples gèrent l' CellClickévénement qui se déclenchera:

lorsque l'utilisateur clique sur n'importe quelle partie d'une cellule.

... mais se déclenchera également chaque fois que l'en- tête de ligne est cliqué. Cela nécessite d'ajouter du code supplémentaire simplement pour déterminer si la e.RowIndexvaleur est inférieure à 0

Au lieu de cela, gérez ce CellContentClickqui se produit uniquement:

lorsque l'utilisateur clique sur le contenu d'une cellule

Pour une raison quelconque, l'en - tête de colonne est également considéré comme du «contenu» dans une cellule, nous devrons donc toujours vérifier cela ci-dessous.

Dos:

Alors, voici ce que vous devez faire:

Commencez par convertir l'expéditeur en saisieDataGridView pour exposer ses propriétés internes au moment du design. Vous pouvez modifier le type du paramètre, mais cela peut parfois rendre difficile l'ajout ou la suppression de gestionnaires.

Ensuite, pour voir si un bouton a été cliqué, vérifiez simplement que la colonne déclenchant l'événement est de type DataGridViewButtonColumn. Comme nous avons déjà converti l'expéditeur en type DataGridView, nous pouvons obtenir la Columnscollection et sélectionner la colonne actuelle à l'aide de e.ColumnIndex. Vérifiez ensuite si cet objet est de type DataGridViewButtonColumn.

Bien sûr, si vous avez besoin de faire la distinction entre plusieurs boutons par grille, vous pouvez ensuite sélectionner en fonction du nom de la colonne ou de l'index, mais cela ne devrait pas être votre première vérification. Assurez-vous toujours qu'un bouton a été cliqué en premier, puis gérez tout le reste de manière appropriée. Dans la plupart des cas où vous n'avez qu'un seul bouton par grille, vous pouvez passer directement aux courses.

Mettre tous ensemble:

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

Mise à jour 1 - Événement personnalisé

Si vous voulez vous amuser un peu, vous pouvez ajouter votre propre événement à déclencher chaque fois qu'un bouton est cliqué sur le DataGrid. Vous ne pouvez pas l'ajouter au DataGrid lui-même, sans être compliqué avec l'héritage, etc., mais vous pouvez ajouter un événement personnalisé à votre formulaire et le déclencher le cas échéant. C'est un peu plus de code, mais l'avantage est que vous avez séparé ce que vous voulez faire lorsqu'un bouton est cliqué avec la façon de déterminer si un bouton a été cliqué.

Déclarez simplement un événement, déclenchez-le si nécessaire et gérez-le. Il ressemblera à ceci:

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

Mise à jour 2 - Grille étendue

Ce qui serait génial, c'est que nous travaillions avec une grille qui ne faisait que cela pour nous. On pourrait facilement répondre à la question initiale: you've added a button to your DataGridView and you want to run some code when it's clicked. Voici une approche qui étend le DataGridView. Cela ne vaut peut-être pas la peine d'avoir à fournir un contrôle personnalisé avec chaque bibliothèque, mais au moins, il réutilise au maximum le code utilisé pour déterminer si un bouton a été cliqué.

Ajoutez simplement ceci à votre assemblage:

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

C'est tout. Ne le touchez plus jamais. Assurez-vous que votre DataGrid est d'un type DataGridViewExtqui doit fonctionner exactement de la même manière qu'un DataGridView. Sauf que cela déclenchera également un événement supplémentaire que vous pouvez gérer comme ceci:

Private Sub DataGridView1_ButtonClick(sender As DataGridView, e As DataGridViewCellEventArgs) _
                                      Handles DataGridView1.CellButtonClick
    'TODO - Button Clicked - Execute Code Here
End Sub
KyleMit
la source
1
Dans VB.net, vous n'avez pas à vérifier l'index des colonnes. J'utilise cet exemple exact pour un dgv avec deux colonnes. Une colonne modifiable et la deuxième avec un bouton de suppression. Je clique partout sur le dgv et l'événement ne se déclenche que lorsque je clique sur le bouton.
Lumineux
3
+1. Cependant, dans notre cas, la colonne est un DataGridViewColumn générique, et j'ai dû vérifier le type de cellule:TypeOf senderGrid.Rows(e.RowIndex).Cells(e.ColumnIndex) Is DataGridViewButtonCell
Dave Johnson
À en juger par les votes positifs et les commentaires, je comprends que c'est une réponse correcte, mais ... pourquoi tout doit toujours être si compliqué! Je n'ai pas encore approché WPF, mais serait-ce la même chose là-bas?
jj_
1
Code C # pour la mise à jour 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, apprécié, mais les commentaires ne sont pas vraiment un bon endroit pour présenter la syntaxe alternative pour une classe entière, en particulier celle qui peut être facilement dérivée via un convertisseur de code . Bien sûr, les gens viendront ici à la recherche de c #, mais ils peuvent y passer eux-mêmes et ne sont pas susceptibles de parcourir les commentaires à la recherche d'une implémentation de toute façon. Je suggère (respectueusement) de supprimer votre commentaire
KyleMit
15

Cela répond entièrement ici pour WinForms: DataGridViewButtonColumn Class

et ici: Comment: répondre aux événements de bouton dans un contrôle GridView

pour Asp.Net en fonction du contrôle que vous utilisez réellement. (Votre question dit DataGrid, mais vous développez une application Windows, donc le contrôle que vous utiliseriez là-bas est un DataGridView ...)

David
la source
Oh, désolé c'était mon erreur. J'utilise DataGridView. Et je vois déjà le premier lien de votre réponse. Je n'ai pas saisi dataGridView1_CellClickce code. Pouvez-vous mettre à jour votre réponse et me donner une description.
Himadri
10

Voici la meilleure réponse:

Vous ne pouvez pas implémenter un événement cliqué sur un bouton pour les cellules de bouton dans un DataGridViewButtonColumn. Au lieu de cela, vous utilisez l'événement CellClicked de DataGridView et déterminez si l'événement déclenché pour une cellule dans votre DataGridViewButtonColumn. Utilisez la propriété DataGridViewCellEventArgs.RowIndex de l'événement pour savoir sur quelle ligne l'utilisateur a cliqué.

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

trouvé ici: événement de clic de bouton dans datagridview

TechStuffBC
la source
8

Cela résout mon problème.

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

Un peu tard dans la table ici, mais en c # (vs2013), vous n'avez pas non plus besoin d'utiliser les noms de colonnes, en fait, une grande partie du travail supplémentaire que certaines personnes proposent est complètement inutile.

La colonne est en fait créée en tant que membre du conteneur (le formulaire ou le contrôle utilisateur dans lequel vous avez placé le DataGridView). À partir du code du concepteur (ce que vous n'êtes pas censé modifier sauf lorsque le concepteur casse quelque chose), vous verrez quelque chose comme:

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;

Ainsi, dans le gestionnaire CellContentClick, en plus de vous assurer que l'index de ligne n'est pas 0, il vous suffit de vérifier si la colonne cliquée est bien celle que vous souhaitez en comparant les références d'objet:

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

Notez que la beauté de ceci est que toute modification de nom sera interceptée par le compilateur. Si vous indexez avec un nom de texte qui change ou que vous mettez une majuscule incorrecte, vous êtes lié à des problèmes d'exécution. Ici, vous utilisez en fait le nom d'un objet, que le concepteur crée en fonction du nom que vous avez fourni. Mais toute incompatibilité sera portée à votre attention par le compilateur.

Arunas
la source
+2 pour être intelligent, -1 pour être trop intelligent :-) À mon humble avis, il n'est jamais trop tard pour ajouter un commentaire à une ancienne publication, car beaucoup de gens comme moi recherchent toujours des réponses sur stackoverflow.
JonP
2

Voici mon extrait de code pour déclencher l'événement de clic et transmettre la valeur à un autre formulaire:

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

        }
    }
nouveau venu
la source
2

En supposant, par exemple, qu'il DataGridViewpossède des colonnes comme indiqué ci-dessous et que ses éléments liés aux données sont du type, PrimalPalletvous pouvez utiliser la solution donnée ci-dessous.

entrez la description de l'image ici

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

Il est plus sûr d'accéder directement aux colonnes que d'utiliser dataGridView1.Columns["MyColumnName"]et il n'est pas nécessaire d'analyser senderle DataGridViewcar il n'est pas nécessaire.

Ryfcia
la source
0

très bien, je vais mordre.

vous aurez besoin de faire quelque chose comme ça - évidemment, tout est métacode.

button.Click += new ButtonClickyHandlerType(IClicked_My_Button_method)

qui "accroche" la méthode IClicked_My_Button_method jusqu'à l'événement Click du bouton. Désormais, chaque fois que l'événement est "déclenché" depuis la classe propriétaire, notre méthode sera également déclenchée.

Dans IClicked_MyButton_method, vous mettez simplement ce que vous voulez quand vous cliquez dessus.

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

Les détails réels ici dépendent de vous, mais s'il y a quelque chose d'autre qui vous manque conceptuellement, faites-le moi savoir et j'essaierai de vous aider.

Joshua Evensen
la source
où vous voulez que ce raccordement se produise. De manière générale, cela ira probablement dans le constructeur de votre formulaire après l'initialisation du datagridview.
Joshua Evensen
D'où tireriez-vous le bouton !?
Peter - Réintègre Monica le
0

La solution la plus votée est fausse, car elle ne peut pas fonctionner avec quelques boutons sur une seule ligne.

La meilleure solution sera le code suivant:

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
la source
0

ajoutez simplement une ToList()méthode à la fin de votre liste, où liez-vous à datagridview DataSource:

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

Vous pouvez essayer celui-ci, vous ne vous souciez pas beaucoup de l'ordre des colonnes.

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
la source
0

Par exemple, pour ClickCell Event dans 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);
                }

Cordialement :)

Diego Mauricio Guerrero
la source
0

Dans le cas où quelqu'un utilise C # (ou voir la remarque sur VB.NET ci-dessous) et a atteint ce point, mais est toujours bloqué, veuillez lire la suite.

La réponse de Joshua m'a aidé, mais pas complètement. Vous remarquerez que Peter a demandé «D'où obtiendriez-vous le bouton?», Mais il n'a pas répondu.

La seule façon dont cela a fonctionné pour moi était de faire l'une des choses suivantes pour ajouter mon gestionnaire d'événement (après avoir défini le DataSource de mon DataGridView à mon DataTable et après avoir ajouté le DataGridViewButtonColumn au DataGridView):

Soit:

dataGridView1.CellClick += new DataGridViewCellEventHandler(dataGridView1_CellClick);

ou:

dataGridView1.CellContentClick += new DataGridViewCellEventHandler(dataGridView1_CellContentClick);

Et puis ajoutez la méthode du gestionnaire (dataGridView1_CellClick ou dataGridView1_CellContentClick) indiquée dans les différentes réponses ci-dessus.

Remarque: VB.NET est différent de C # à cet égard, car nous pouvons simplement ajouter une clause Handles à la signature de notre méthode ou émettre une instruction AddHandler comme décrit dans le document Microsoft " Comment: appeler un gestionnaire d'événements dans Visual Basic "

clairestreb
la source
0

Vous allez ajouter une colonne de boutons comme celle-ci dans votre dataGridView

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


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

Ensuite, vous pouvez ajouter des actions à l'intérieur de l'événement de clic de cellule. J'ai trouvé que c'était le moyen le plus simple de le faire.

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


    }

J'ai constaté que l'événement Clic sur cellule est automatiquement souscrit souvent. Je n'avais donc pas besoin de ce code ci-dessous. Toutefois, si votre événement de clic de cellule n'est pas abonné, ajoutez cette ligne de code pour votre dataGridView.

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