¿Cómo manejar el evento de clic en la columna de botón en Datagridview?

136

Estoy desarrollando una aplicación de Windows usando C #. Estoy usando DataGridViewpara mostrar datos. He agregado una columna de botón en eso. Quiero saber cómo puedo manejar el evento de clic en ese botón en DataGridView.

Himadri
fuente
1
¿Estás agregando el botón mediante programación (como sospecho que es la única forma)?
XstreamINsanity
Hay muchas respuestas disponibles para esto en línea. ¿Qué te da problemas en particular?
Joshua Evensen
1
@Joshua Recibí muchas respuestas en la red, pero realmente no tenía idea de qué hacer y cuándo comenzar. Había agregado un botón en mi vista de cuadrícula de datos, pero no sé cómo manejar su evento de clic.
Himadri

Respuestas:

263

Agregó un botón a su DataGridViewy desea ejecutar un código cuando se hace clic.
Fácil, solo sigue estos pasos:

No hacer:

Primero, esto es lo que NO debes hacer:

Evitaría las sugerencias en algunas de las otras respuestas aquí e incluso las que proporciona la documentación de MSDN para codificar el índice o el nombre de la columna para determinar si se hizo clic en un botón. El evento click se registra para toda la cuadrícula, por lo que de alguna manera debe determinar que se hizo clic en un botón, pero no debe hacerlo asumiendo que su botón vive en un nombre o índice de columna en particular ... hay una manera más fácil ...

Además, tenga cuidado con el evento que desea manejar. Nuevamente, la documentación y muchos ejemplos se equivocan. La mayoría de los ejemplos manejan el CellClickevento que se disparará:

cuando se hace clic en cualquier parte de una celda.

... pero también se disparará cada vez que se haga clic en el encabezado de la fila . Esto requiere agregar código adicional simplemente para determinar si el e.RowIndexvalor es menor que 0

En su lugar, maneje lo CellContentClickque solo ocurre:

cuando se hace clic en el contenido dentro de una celda

Por alguna razón, el encabezado de la columna también se considera 'contenido' dentro de una celda, por lo que aún tendremos que verificarlo a continuación.

Dos:

Entonces, esto es lo que debes hacer:

Primero, envíe el remitente a escribir DataGridViewpara exponer sus propiedades internas en tiempo de diseño. Puede modificar el tipo en el parámetro, pero eso a veces puede hacer que agregar o quitar controladores sea complicado.

A continuación, para ver si se hizo clic en un botón, solo verifique para asegurarse de que la columna que genera el evento sea de tipo DataGridViewButtonColumn. Debido a que ya enviamos al remitente a escribir DataGridView, podemos obtener la Columnscolección y seleccionar la columna actual usando e.ColumnIndex. Luego verifique si ese objeto es de tipo DataGridViewButtonColumn.

Por supuesto, si necesita distinguir entre varios botones por cuadrícula, puede seleccionar según el nombre de la columna o el índice, pero esa no debería ser su primera comprobación. Siempre asegúrese de hacer clic primero en un botón y luego maneje cualquier otra cosa de manera apropiada. En la mayoría de los casos en los que solo tiene un solo botón por cuadrícula, puede saltar directamente a las carreras.

Poniendolo todo junto:

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

Actualización 1 - Evento personalizado

Si desea divertirse un poco, puede agregar su propio evento para que se genere cada vez que se hace clic en un botón en DataGrid. No puede agregarlo a DataGrid en sí, sin desordenarse con la herencia, etc., pero puede agregar un evento personalizado a su formulario y activarlo cuando sea apropiado. Es un poco más de código, pero lo bueno es que ha separado lo que quiere hacer cuando se hace clic en un botón con la forma de determinar si se hizo clic en un botón.

Simplemente declare un evento, créelo cuando sea apropiado y manejelo. Se verá así:

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

Actualización 2 - Cuadrícula extendida

Lo que sería genial es si estuviéramos trabajando con una grilla que acaba de hacer estas cosas por nosotros. Podríamos responder a la pregunta inicial fácilmente: you've added a button to your DataGridView and you want to run some code when it's clicked. Aquí hay un enfoque que extiende el DataGridView. Puede que no valga la pena tener que entregar un control personalizado con cada biblioteca, pero al menos reutiliza al máximo el código utilizado para determinar si se hizo clic en un botón.

Simplemente agregue esto a su ensamblaje:

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

Eso es. Nunca lo toques de nuevo. Asegúrese de que su DataGrid sea del tipo DataGridViewExtque debería funcionar exactamente igual que un DataGridView. Excepto que también generará un evento adicional que puedes manejar así:

Private Sub DataGridView1_ButtonClick(sender As DataGridView, e As DataGridViewCellEventArgs) _
                                      Handles DataGridView1.CellButtonClick
    'TODO - Button Clicked - Execute Code Here
End Sub
KyleMit
fuente
1
En VB.net no tiene que verificar el índice de la columna. Estoy usando este ejemplo exacto para un dgv con dos columnas. Una columna que es editable y la segunda con un botón de eliminación. Hago clic en todo el dgv y el evento solo se dispara cuando hago clic en el botón.
Luminoso
3
+1. Sin embargo, en nuestro caso, la columna es un DataGridViewColumn genérico, y tuve que verificar el tipo de celda:TypeOf senderGrid.Rows(e.RowIndex).Cells(e.ColumnIndex) Is DataGridViewButtonCell
Dave Johnson
A juzgar por los votos y comentarios positivos, entiendo que esta es una respuesta correcta, pero ... ¡por qué todo debe ser siempre tan complicado! Todavía no me he acercado a WPF, pero, ¿sería lo mismo allí?
jj_
1
Código C # para la Actualización 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, apreciado, pero los comentarios no son realmente un buen lugar para mostrar la sintaxis alternativa para toda una clase, especialmente una que puede derivarse fácilmente a través de un convertidor de código . Claro, la gente vendrá aquí buscando c #, pero pueden cruzar allí ellos mismos y no es probable que busquen los comentarios en busca de una implementación de todos modos. Sugeriría (respetuosamente) eliminar su comentario
KyleMit
15

Eso se responde completamente aquí para WinForms: DataGridViewButtonColumn Class

y aquí: Cómo: responder a eventos de botón en un control GridView

para Asp.Net dependiendo del control que esté usando realmente. (Su pregunta dice DataGrid, pero está desarrollando una aplicación de Windows, por lo que el control que usaría allí es un DataGridView ...)

David
fuente
Oh, perdón, ese fue mi error. Estoy usando DataGridView. Y ya veo el primer enlace de tu respuesta. No entendí dataGridView1_CellClickese código. ¿Puedes actualizar tu respuesta y darme una descripción?
Himadri
10

Aquí está la mejor respuesta:

No puede implementar un evento de botón para celdas de botón en un DataGridViewButtonColumn. En su lugar, utiliza el evento CellClicked de DataGridView y determina si el evento se activó para una celda en su DataGridViewButtonColumn. Use la propiedad DataGridViewCellEventArgs.RowIndex del evento para averiguar en qué fila se hizo clic.

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

encontrado aquí: evento de clic de botón en datagridview

TechStuffBC
fuente
8

Esto resuelve mi problema.

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

Un poco tarde para la tabla aquí, pero en c # (vs2013) tampoco necesita usar nombres de columna, de hecho, gran parte del trabajo adicional que algunas personas proponen es completamente innecesario.

La columna se crea realmente como un miembro del contenedor (el formulario o control de usuario en el que ha puesto el DataGridView). Desde el código del diseñador (las cosas que no debes editar excepto cuando el diseñador rompe algo), verías algo como:

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;

Entonces, en el controlador CellContentClick, además de asegurarse de que el índice de la fila no sea 0, solo debe verificar si la columna en la que se hizo clic es la que desea mediante la comparación de referencias de objetos:

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

Tenga en cuenta que la belleza de esto es que cualquier cambio de nombre será captado por el compilador. Si indexa con un nombre de texto que cambia, o que capitaliza incorrectamente, está obligado a problemas de tiempo de ejecución. Aquí realmente usa el nombre de un objeto, que el diseñador crea en función del nombre que proporcionó. Pero cualquier compilación le indicará el compilador.

Arunas
fuente
+2 por ser inteligente, -1 por ser demasiado inteligente :-) En mi humilde opinión, nunca es demasiado tarde para agregar un comentario a una publicación anterior, porque muchas personas como yo todavía están buscando respuestas en stackoverflow.
JonP
2

Aquí está mi fragmento de código para activar el evento de clic y pasar el valor a otro formulario:

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

        }
    }
recién llegado
fuente
2

Suponiendo, por ejemplo, que las DataGridViewcolumnas se muestran a continuación y que sus elementos enlazados a datos son del tipo PrimalPalletque puede usar, la solución se proporciona a continuación.

ingrese la descripción de la imagen aquí

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

Es más seguro columnas de acceso directamente en lugar de utilizar dataGridView1.Columns["MyColumnName"]y no hay necesidad de analizar sendera la DataGridViewya que no es necesario.

Ryfcia
fuente
0

bien, voy a morder.

tendrás que hacer algo como esto, obviamente es todo metacódigo.

button.Click += new ButtonClickyHandlerType(IClicked_My_Button_method)

que "engancha" el método IClicked_My_Button_method hasta el evento Click del botón. Ahora, cada vez que el evento se "dispara" desde la clase de propietarios, nuestro método también se disparará.

En el método IClicked_MyButton_, simplemente coloca lo que quieras que suceda al hacer clic en él.

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

Los detalles reales aquí dependen de usted, pero si falta algo más conceptualmente, hágamelo saber y trataré de ayudarlo.

Joshua Evensen
fuente
donde quiera que ocurra esa conexión. En términos generales, eso probablemente iría en el constructor de su formulario después de que se inicialice la vista de cuadrícula de datos.
Joshua Evensen el
¿De dónde obtendrías el botón?
Peter - Restablece a Monica el
0

La solución más votada es incorrecta, ya que no puede funcionar con pocos botones en una fila.

La mejor solución será el siguiente código:

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");
            }
        }
Andrés
fuente
0

simplemente agregue el ToList()método al final de su lista, donde se une a datagridview DataSource:

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

Puede probar este, no le importaría mucho el orden de las columnas.

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
fuente
0

Por ejemplo para ClickCell Event en 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);
                }

Saludos :)

Diego Mauricio Guerrero
fuente
0

En caso de que alguien esté usando C # (o vea la Nota sobre VB.NET a continuación) y haya llegado a este punto, pero todavía está atascado, siga leyendo.

La respuesta de Joshua me ayudó, pero no del todo. Notarás que Peter preguntó "¿De dónde obtendrías el botón?", Pero no recibió respuesta.

La única forma en que funcionó para mí fue hacer una de las siguientes acciones para agregar mi controlador de eventos (después de configurar DataSource de DataGridView en mi DataTable y después de agregar DataGridViewButtonColumn a DataGridView):

Ya sea:

dataGridView1.CellClick += new DataGridViewCellEventHandler(dataGridView1_CellClick);

o:

dataGridView1.CellContentClick += new DataGridViewCellEventHandler(dataGridView1_CellContentClick);

Y luego agregue el método del controlador (ya sea dataGridView1_CellClick o dataGridView1_CellContentClick) que se muestra en las diversas respuestas anteriores.

Nota: VB.NET es diferente de C # a este respecto, porque simplemente podemos agregar una cláusula Handles a la firma de nuestro método o emitir una declaración AddHandler como se describe en el documento de Microsoft " Cómo: llamar a un controlador de eventos en Visual Basic "

clairestreb
fuente
0

Agregará una columna de botón como esta en su dataGridView

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


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

Luego puede agregar algunas acciones dentro del evento de clic de celda. Encontré que esta es la forma más fácil de hacerlo.

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


    }

Descubrí que el evento Cell Click se suscribe automáticamente a menudo. Entonces no necesitaba este código a continuación. Sin embargo, si su evento de clic en la celda no está suscrito, agregue esta línea de código para su dataGridView.

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