159 votes

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

Je développe une application Windows en utilisant C#. J'utilise DataGridView pour afficher les données. J'y ai ajouté une colonne de boutons. J'aimerais savoir comment gérer l'événement de clic sur ce bouton en DataGridView .

1 votes

Ajoutez-vous le bouton de façon programmatique (ce qui, je le soupçonne, est la seule façon) ?

0 votes

Il existe de nombreuses réponses à cette question en ligne. Qu'est-ce qui vous pose problème en particulier ?

1 votes

@Joshua J'ai trouvé de nombreuses réponses sur le net mais je n'ai pas vraiment eu d'idée sur ce qu'il faut faire et quand commencer. J'ai ajouté un bouton dans mon datagridview mais je ne sais pas comment gérer son événement de clic.

312voto

KyleMit Points 6937

Vous avez ajouté un bouton à votre DataGridView et vous voulez exécuter un code lorsqu'il est cliqué.

C'est facile - il suffit de suivre les étapes suivantes :

A ne pas faire

D'abord, voici ce que PAS à faire :

J'éviterais les suggestions formulées dans certaines des autres réponses ici et même celles fournies par la Commission européenne. documentation à 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 s'enregistre pour la grille entière, donc d'une manière ou d'une autre vous devez déterminer qu'un bouton a été cliqué, mais vous ne devez pas le faire en supposant que votre bouton se trouve dans un nom de colonne ou un index particulier... il y a un moyen plus facile...

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

lorsqu'une partie quelconque d'une cellule est cliquée.

...mais se déclenchera également lorsque le rangée est cliqué. Cela nécessite l'ajout de code supplémentaire simplement pour déterminer si l'élément e.RowIndex est inférieure à 0

Traitez plutôt le CellContentClick qui se produit uniquement :

lorsque le contenu d'une cellule est cliqué

Pour une raison quelconque, le colonne est également considéré comme du "contenu" dans une cellule. Nous devrons donc vérifier ce point ci-dessous.

Dos

Voici donc ce que vous devez faire :

D'abord, moulage l'expéditeur à taper DataGridView pour exposer ses propriétés internes au moment de la conception. Vous pouvez modifier le type du paramètre, mais cela peut parfois compliquer l'ajout ou la suppression de gestionnaires.

Ensuite, pour savoir si un bouton a été cliqué, il suffit de vérifier que la colonne qui déclenche l'événement est de type DataGridViewButtonColumn . Parce que nous avons déjà attribué à l'expéditeur le type DataGridView on peut obtenir le Columns et sélectionnez la colonne actuelle en utilisant e.ColumnIndex . Ensuite, vérifiez si cet objet est de type DataGridViewButtonColumn .

Bien sûr, si vous devez faire la distinction entre plusieurs boutons par grille, vous pouvez alors sélectionner sur la base du nom ou de l'index de la colonne, mais cela ne doit pas être votre première vérification. Vérifiez toujours qu'un bouton a été cliqué en premier lieu, puis traitez 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 vous lancer directement dans les courses.

Tout mettre en place :

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 qui sera déclenché chaque fois que vous cliquez sur un bouton dans la grille de données. Vous ne pouvez pas l'ajouter à la grille de données elle-même, sans vous embrouiller avec l'héritage, etc., mais vous pouvez ajouter un événement personnalisé à votre formulaire et le déclencher au moment opportun. C'est un peu plus de code, mais l'avantage est que vous avez séparé ce que vous voulez faire quand un bouton est cliqué de la façon de déterminer si un bouton a été cliqué.

Il suffit de déclarer un événement, de le déclencher au moment opportun et de le gérer. Cela 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 fasse tout simplement ces choses pour nous. Nous pourrions répondre facilement à 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 de devoir fournir un contrôle personnalisé avec chaque bibliothèque, mais au moins cela permet de réutiliser au maximum le code utilisé pour déterminer si un bouton a été cliqué.

Il suffit de l'ajouter à votre montage :

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 ça. N'y touchez plus jamais. Assurez-vous que votre DataGrid est de type DataGridViewExt qui devrait fonctionner exactement de la même manière qu'un DataGridView. Sauf qu'il soulèvera é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

2 votes

En VB.net, il n'est pas nécessaire de vérifier l'index de la colonne. J'utilise cet exemple exact pour un dgv avec deux colonnes. Une colonne qui est éditable et la 2ème avec un bouton de suppression. Je clique partout dans le dgv et l'événement ne se déclenche que lorsque je clique sur le bouton.

3 votes

+1. Cependant, dans notre cas, la colonne est une DataGridViewColumn générique, et j'ai dû vérifier le type de cellule : TypeOf senderGrid.Rows(e.RowIndex).Cells(e.ColumnIndex) Is DataGridViewButtonCell

0 votes

D'après les votes et les commentaires, je pense que c'est une réponse correcte, mais... pourquoi tout doit toujours être si compliqué ! Je n'ai pas encore abordé WPF, mais, est-ce que ce serait la même chose là-bas ?

16voto

David Stratton Points 45298

Cette question est traitée en détail ici pour WinForms : Classe DataGridViewButtonColumn

et ici : Comment faire : Répondre aux événements liés aux boutons 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 ici est un DataGridView...)

0 votes

Oh, désolé, c'était mon erreur. J'utilise DataGridView. Et j'ai déjà vu le premier lien de votre réponse. Je n'ai pas obtenu dataGridView1_CellClick dans ce code. Pouvez-vous mettre à jour votre réponse et me donner une description.

13voto

TechStuffBC Points 51

Voici la meilleure réponse :

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

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 une grille de données

8voto

Himadri Points 755

Cela résout mon problème.

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

6voto

Arunas Points 153

J'arrive un peu tard, mais en C# (vs2013), il n'est pas non plus nécessaire d'utiliser des noms de colonnes. En fait, une grande partie du travail supplémentaire proposé par certaines personnes est totalement inutile.

La colonne est en fait créée comme un membre du conteneur (le formulaire ou le contrôle d'utilisateur dans lequel vous avez placé le DataGridView). Dans le code du concepteur (le truc que vous n'êtes pas censé modifier, sauf si le concepteur casse quelque chose), vous verriez 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, outre le fait de s'assurer que l'indice de ligne n'est pas égal à 0, il suffit de vérifier si la colonne cliquée est bien celle que vous souhaitez en comparant les références d'objets :

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 tout Les changements de nom seront pris en compte par le compilateur. Si vous indexez avec un nom de texte qui change, ou que vous mettez en majuscule de manière incorrecte, vous êtes condamné à des problèmes d'exécution. Ici, vous utilisez en fait le nom d'un objet, que le concepteur crée sur la base du nom que vous avez fourni. Mais toute discordance sera portée à votre attention par le compilateur.

0 votes

+2 pour être intelligent, -1 pour être trop astucieux :-) Il n'est jamais trop tard pour ajouter un commentaire à une ancienne publication, car de nombreuses personnes comme moi cherchent encore des réponses sur stackoverflow.

0 votes

Je ne pense pas qu'utiliser un nom de variable défini plutôt qu'une chaîne de caractères ou un nombre soit "trop intelligent" J'ai également apprécié la blague du "retard à la table".

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X