web-dev-qa-db-fra.com

Comment gérer l'événement click dans Button Column dans Datagridview?

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

115
Himadri

Vous avez ajouté un bouton à votre DataGridView et vous souhaitez exécuter du code lorsque vous cliquez dessus.
Peasy facile - il suffit de suivre ces étapes:

À ne pas faire:

Tout d'abord, voici ce que NOT ne doit pas faire:

J'éviterais les suggestions figurant dans certaines des autres réponses ici et même fournies par le documentation sur MSDN pour coder en dur l'index ou le nom de la colonne afin de déterminer si un bouton a été cliqué. L'événement click s'enregistre pour l'ensemble de la grille. Vous devez donc déterminer si 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 s’y trompent. La plupart des exemples traitent l'événement CellClick qui se déclenchera:

lorsque vous cliquez sur une partie d'une cellule.

... mais sera également déclenché chaque fois que l'en-tête row est cliqué. Cela nécessite l'ajout de code supplémentaire pour déterminer simplement si la valeur e.RowIndex est inférieure à 0.

À la place, gérez le CellContentClick qui ne se produit que:

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

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

Dos:

Alors voici ce que vous devriez faire:

Tout d’abord, transforme l’envoyeur à taper DataGridView pour exposer ses propriétés internes au moment de la conception. Vous pouvez modifier le type sur le paramètre, mais cela peut parfois rendre compliqué l'ajout ou la suppression de gestionnaires.

Ensuite, pour voir si un bouton a été cliqué, vérifiez simplement que la colonne qui déclenche l'événement est de type DataGridViewButtonColumn . Comme nous avons déjà transtypé l'expéditeur sur DataGridView, nous pouvons obtenir la collection Columns et sélectionner la colonne actuelle à l'aide de 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 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 manipulez 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 - Evénement personnalisé

Si vous voulez vous amuser un peu, vous pouvez ajouter votre propre événement pour qu'il soit déclenché chaque fois qu'un bouton est cliqué sur le DataGrid. Vous ne pouvez pas l'ajouter au DataGrid lui-même, sans vous perdre en héritage, etc., mais vous pouvez ajouter un événement personnalisé à votre formulaire et le déclencher si nécessaire. C'est un peu plus de code, mais le bon côté des choses est que vous avez séparé ce que vous voulez faire quand un bouton est cliqué sur la manière de déterminer si un bouton a été cliqué. 

Déclarez simplement un événement, soulevez-le le cas échéant 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 formidable, c’est que nous travaillions avec une grille qui se contentait de faire 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 la DataGridView. Il ne vaut peut-être pas la peine de devoir 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 assemblée:

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 touchez plus jamais. Assurez-vous que votre DataGrid est de type DataGridViewExt, ce qui devrait fonctionner exactement comme 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
217
KyleMit

Ici, la réponse est complète pour WinForms: DataGridViewButtonColumn Class

and here: 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, le contrôle que vous utiliseriez est donc un DataGridView ...)

15
David

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. À la place, vous utilisez l'événement CellClicked du DataGridView et déterminez s'il est déclenché pour une cellule de votre DataGridViewButtonColumn. Utilisez la propriété DataGridViewCellEventArgs.RowIndex de l'événement pour déterminer la ligne sur laquelle 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

9
TechStuffBC

Cela résout mon problème.

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

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

La colonne est en fait créée en tant que membre du conteneur (le formulaire ou la commande usercontrol dans lequel vous avez placé DataGridView). Dans le code du concepteur (ce que vous n'êtes pas censé éditer 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 égal à 0, il vous suffit de vérifier si la colonne sur laquelle vous avez cliqué 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 les changements de nom any seront capturés par le compilateur. Si vous indexez avec un nom de texte qui change ou que vous ne mettez pas correctement les majuscules en valeur, vous êtes lié à des problèmes d'exécution. Ici, vous utilisez réellement le nom d'un objet, créé par le concepteur en fonction du nom que vous avez fourni. Mais toute incompatibilité sera portée à votre attention par le compilateur.

4
Arunas

Voici l'extrait de code pour déclencher l'événement click 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();

        }
    }
2
newComer

En supposant par exemple que DataGridView ait les colonnes indiquées ci-dessous et que ses éléments liés aux données soient de type PrimalPallet, vous pouvez utiliser la solution donnée ci-dessous.

 enter image description here

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 plutôt que d'utiliser dataGridView1.Columns["MyColumnName"] et il n'est pas nécessaire d'analyser sender avec DataGridView car ce n'est pas nécessaire. 

1
Ryfcia

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

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

Par exemple, pour l'événement ClickCell 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 :)

Vous pouvez essayer celui-ci, vous ne vous soucierez 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");
    }
}
0
JL Dajoyag

Dans le cas où quelqu'un utilise C # (ou voir la remarque à propos de VB.NET ci-dessous) et a atteint ce stade, mais reste bloqué, lisez la suite.

La réponse de Josué m'aidait, mais pas complètement. Vous remarquerez que Peter a demandé "D'où obtiendriez-vous le bouton?", Mais est resté sans réponse.

La seule façon dont cela a fonctionné pour moi a été d'effectuer l'une des opérations suivantes pour ajouter mon gestionnaire d'événements (après avoir défini le source de données de mon DataGridView sur mon DataTable et après avoir ajouté le DataGridViewButtonColumn au DataGridView):

Non plus:

dataGridView1.CellClick += new DataGridViewCellEventHandler(dataGridView1_CellClick);

ou:

dataGridView1.CellContentClick += new DataGridViewCellEventHandler(dataGridView1_CellContentClick);

Et ajoutez ensuite la méthode de 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 la documentation de la documentation Microsoft " Comment: appeler un gestionnaire d'événements dans Visual Basic "

0
clairestreb

bien, je vais mordre.

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

button.Click += new ButtonClickyHandlerType(IClicked_My_Button_method)

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

Dans IClicked_MyButton_method, il vous suffit d'indiquer 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 sont à vous, mais s'il vous manque quelque chose de plus conceptuellement, faites-le-moi savoir et je tenterai de vous aider.

0
Joshua Evensen

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 dans 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 trouvé que l'événement Cell Click est automatiquement abonné souvent. Donc, je n'ai pas eu 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);
0
auto9817

ajoutez simplement la méthode ToList() à la fin de votre liste, où bind à datagridview

dataGridView1.DataSource = MyList.ToList();
0