Wie gehe ich mit Klickereignissen in der Schaltflächenspalte in Datagridview um?


136

Ich entwickle eine Windows-Anwendung mit C #. ich benutzeDataGridView , um Daten anzuzeigen. Ich habe eine Schaltflächenspalte hinzugefügt. Ich möchte wissen, wie ich mit Klickereignissen auf dieser Schaltfläche in DataGridView umgehen kann.


1
Fügen Sie die Schaltfläche programmgesteuert hinzu (wie ich vermute, ist dies der einzige Weg)?
XstreamINsanity

Hierfür stehen online zahlreiche Antworten zur Verfügung. Was macht Ihnen besonders Probleme?
Joshua Evensen

1
@Joshua Ich habe viele Antworten im Internet bekommen, aber nicht wirklich eine Idee bekommen, was zu tun ist und wann ich anfangen soll. Ich hatte eine Schaltfläche in meiner Datagrid-Ansicht hinzugefügt und weiß nur nicht, wie ich mit dem Klickereignis umgehen soll.
Himadri

Antworten:


263

Sie haben Ihrer Schaltfläche eine Schaltfläche hinzugefügt DataGridViewund möchten beim Klicken Code ausführen.
Einfach peasy - folgen Sie einfach diesen Schritten:

Verbote:

Zunächst ist Folgendes NICHT zu tun:

Ich würde die Vorschläge in einigen der anderen Antworten hier vermeiden und sogar in der Dokumentation bei MSDN enthalten sein, um den Spaltenindex oder den Spaltennamen fest zu codieren, um festzustellen, ob auf eine Schaltfläche geklickt wurde. Das Klickereignis wird für das gesamte Raster registriert. Sie müssen also irgendwie feststellen, dass auf eine Schaltfläche geklickt wurde. Sie sollten dies jedoch nicht tun, indem Sie davon ausgehen, dass Ihre Schaltfläche in einem bestimmten Spaltennamen oder Index gespeichert ist. Es gibt einen einfacheren Weg.

Achten Sie auch darauf, welches Ereignis Sie behandeln möchten. Auch hier verstehen die Dokumentation und viele Beispiele dies falsch. Die meisten Beispiele behandeln das CellClickEreignis, das ausgelöst wird:

Wenn auf einen Teil einer Zelle geklickt wird.

... sondern auch feuern , wenn die Zeile Header geklickt wird. Dies erfordert das Hinzufügen von zusätzlichem Code, um festzustellen, ob der e.RowIndexWert kleiner als 0 ist

Behandeln Sie stattdessen das, CellContentClickwas nur auftritt:

wenn auf den Inhalt einer Zelle geklickt wird

Aus irgendeinem Grund wird die Spaltenüberschrift auch als "Inhalt" in einer Zelle betrachtet, daher müssen wir dies unten noch überprüfen.

DOS:

Folgendes sollten Sie also tun:

Zuerst warf den Absender eingeben DataGridViewes interne Eigenschaften zur Entwurfszeit belichten. Sie können den Typ des Parameters ändern, dies kann jedoch manchmal das Hinzufügen oder Entfernen von Handlern schwierig machen.

Um zu sehen, ob auf eine Schaltfläche geklickt wurde, überprüfen Sie einfach, ob die Spalte, die das Ereignis auslöst, vom Typ ist DataGridViewButtonColumn. Da wir den Absender bereits in Typ umgewandelt haben DataGridView, können wir die ColumnsSammlung abrufen und die aktuelle Spalte mit auswählen e.ColumnIndex. Überprüfen Sie dann, ob dieses Objekt vom Typ ist DataGridViewButtonColumn.

Wenn Sie zwischen mehreren Schaltflächen pro Raster unterscheiden müssen, können Sie diese natürlich anhand des Spaltennamens oder des Index auswählen. Dies sollte jedoch nicht Ihre erste Prüfung sein. Stellen Sie immer sicher, dass zuerst auf eine Schaltfläche geklickt wurde, und behandeln Sie dann alles andere entsprechend. In den meisten Fällen, in denen Sie nur eine Schaltfläche pro Raster haben, können Sie direkt zu den Rennen springen.

Alles zusammen:

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

Update 1 - Benutzerdefiniertes Ereignis

Wenn Sie ein bisschen Spaß haben möchten, können Sie Ihr eigenes Ereignis hinzufügen, das ausgelöst wird, wenn auf eine Schaltfläche im DataGrid geklickt wird. Sie können es nicht zum DataGrid selbst hinzufügen, ohne mit Vererbung usw. in Konflikt zu geraten. Sie können Ihrem Formular jedoch ein benutzerdefiniertes Ereignis hinzufügen und es gegebenenfalls auslösen. Es ist etwas mehr Code, aber der Vorteil ist, dass Sie getrennt haben, was Sie tun möchten, wenn auf eine Schaltfläche geklickt wird, und wie Sie feststellen können, ob auf eine Schaltfläche geklickt wurde.

Deklarieren Sie einfach ein Ereignis, lösen Sie es gegebenenfalls aus und behandeln Sie es. Es wird so aussehen:

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

Update 2 - Erweitertes Raster

Was großartig wäre, wäre, wenn wir mit einem Raster arbeiten würden, das diese Dinge nur für uns erledigt. Wir könnten die erste Frage leicht beantworten : you've added a button to your DataGridView and you want to run some code when it's clicked. Hier ist ein Ansatz, der die DataGridView. Es lohnt sich möglicherweise nicht, mit jeder Bibliothek ein benutzerdefiniertes Steuerelement bereitzustellen, aber zumindest wird der Code, der zum Bestimmen, ob auf eine Schaltfläche geklickt wurde, verwendet wird, maximal wiederverwendet.

Fügen Sie dies einfach Ihrer Baugruppe hinzu:

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

Das ist es. Nie wieder anfassen. Stellen Sie sicher, dass Ihr DataGrid vom Typ DataGridViewExtist, der genauso funktionieren sollte wie ein DataGridView. Außer es wird auch ein zusätzliches Ereignis ausgelöst, das Sie wie folgt behandeln können:

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 müssen Sie den Spaltenindex nicht überprüfen. Ich verwende genau dieses Beispiel für eine GDV mit zwei Spalten. Eine bearbeitbare Spalte und die zweite mit einem Button zum Entfernen. Ich klicke überall auf dem dgv und das Ereignis wird nur ausgelöst, wenn ich auf die Schaltfläche klicke.
Leuchtend

3
+1. In unserem Fall ist die Spalte jedoch eine generische DataGridViewColumn, und ich musste den Zelltyp überprüfen:TypeOf senderGrid.Rows(e.RowIndex).Cells(e.ColumnIndex) Is DataGridViewButtonCell
Dave Johnson

Nach Upvotes und Kommentaren zu urteilen, verstehe ich, dass dies eine richtige Antwort ist, aber ... warum muss immer alles so kompliziert sein! Ich habe mich noch nicht an WPF gewandt, aber wäre es dort dasselbe?
jj_

1
C # Code für Update 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, geschätzt, aber die Kommentare sind nicht wirklich ein guter Ort, um die alternative Syntax für eine ganze Klasse zu präsentieren, insbesondere eine, die leicht über einen Codekonverter abgeleitet werden kann . Sicher, die Leute werden hierher kommen, um nach c # zu suchen, aber sie können dort selbst überqueren und werden wahrscheinlich nicht in den Kommentaren nach einer Implementierung suchen. Ich würde (respektvoll) vorschlagen, Ihren Kommentar zu löschen
KyleMit

15

Dies wird hier für WinForms vollständig beantwortet: DataGridViewButtonColumn Class

und hier: Gewusst wie: Auf Schaltflächenereignisse in einem GridView-Steuerelement reagieren

für Asp.Net abhängig von der Steuerung, die Sie tatsächlich verwenden. (Ihre Frage lautet DataGrid, aber Sie entwickeln eine Windows-App. Das Steuerelement, das Sie dort verwenden würden, ist also DataGridView ...)


Oh, Entschuldigung, das war mein Fehler. Ich verwende DataGridView. Und ich sehe bereits den ersten Link Ihrer Antwort. Ich habe dataGridView1_CellClickdiesen Code nicht eingegeben. Können Sie Ihre Antwort aktualisieren und mir eine Beschreibung geben?
Himadri

10

Hier ist die bessere Antwort:

Sie können kein Ereignis mit Schaltflächenklick für Schaltflächenzellen in einer DataGridViewButtonColumn implementieren. Stattdessen verwenden Sie das CellClicked-Ereignis von DataGridView und bestimmen, ob das Ereignis für eine Zelle in Ihrer DataGridViewButtonColumn ausgelöst wurde. Verwenden Sie die DataGridViewCellEventArgs.RowIndex-Eigenschaft des Ereignisses, um herauszufinden, auf welche Zeile geklickt wurde.

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

hier zu finden: button click event in datagridview


8

Dies löst mein Problem.

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

5

Ein bisschen zu spät zur Tabelle hier, aber in c # (vs2013) müssen Sie auch keine Spaltennamen verwenden, tatsächlich ist ein Großteil der zusätzlichen Arbeit, die einige Leute vorschlagen, völlig unnötig.

Die Spalte wird tatsächlich als Mitglied des Containers erstellt (das Formular oder die Benutzersteuerung, in die Sie DataGridView eingefügt haben). Aus dem Designer-Code (dem Material, das Sie nur bearbeiten sollen, wenn der Designer etwas kaputt macht) sehen Sie Folgendes:

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;

Im CellContentClick-Handler müssen Sie also nicht nur sicherstellen, dass der Zeilenindex nicht 0 ist, sondern auch überprüfen, ob die angeklickte Spalte tatsächlich die gewünschte ist, indem Sie Objektreferenzen vergleichen:

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

Beachten Sie, dass das Schöne daran ist, dass alle Namensänderungen vom Compiler abgefangen werden. Wenn Sie mit einem Textnamen indizieren, der sich ändert oder den Sie falsch großschreiben, sind Sie an Laufzeitprobleme gebunden. Hier verwenden Sie tatsächlich den Namen eines Objekts, das der Designer basierend auf dem von Ihnen angegebenen Namen erstellt. Aber jede Nichtübereinstimmung wird Sie vom Compiler darauf aufmerksam machen.


+2 für klug sein, -1 für zu klug sein :-) IMHO ist es nie zu spät, einen Kommentar zu einem alten Beitrag hinzuzufügen, weil viele Leute wie ich immer noch nach Antworten auf Stackoverflow suchen.
JonP

2

Hier ist mein Code-Snippet, um das Klickereignis auszulösen und den Wert an ein anderes Formular zu übergeben:

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

Angenommen, Sie haben beispielsweise DataGridViewdie unten angegebenen Spalten und die datengebundenen Elemente sind vom Typ PrimalPallet, können Sie die unten angegebene Lösung verwenden.

Geben Sie hier die Bildbeschreibung ein

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 ist sicherer, direkt auf Spalten zuzugreifen, als sie zu verwenden, dataGridView1.Columns["MyColumnName"]und es ist nicht erforderlich, sie zu analysieren sender, DataGridViewda sie nicht benötigt werden.


0

gut, ich werde beißen.

Sie müssen so etwas tun - offensichtlich ist alles Metacode.

button.Click += new ButtonClickyHandlerType(IClicked_My_Button_method)

Dadurch wird die IClicked_My_Button_method-Methode bis zum Click-Ereignis der Schaltfläche "eingehakt". Jedes Mal, wenn das Ereignis innerhalb der Eigentümerklasse "ausgelöst" wird, wird unsere Methode ebenfalls ausgelöst.

In der IClicked_MyButton_method geben Sie einfach ein, was passieren soll, wenn Sie darauf klicken.

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

Die tatsächlichen Details hier liegen bei Ihnen, aber wenn Ihnen noch etwas fehlt, lassen Sie es mich wissen und ich werde versuchen zu helfen.


wo immer Sie möchten, dass diese Verbindung hergestellt wird. Im Allgemeinen wird dies wahrscheinlich im Konstruktor Ihres Formulars nach der Initialisierung der Datagrid-Ansicht angezeigt.
Joshua Evensen

Woher würden Sie den Knopf bekommen?
Peter - Wiedereinsetzung Monica

0

Die am häufigsten gewählte Lösung ist falsch, da nicht mit wenigen Schaltflächen in einer Reihe gearbeitet werden kann.

Die beste Lösung ist der folgende Code:

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

ToList()Fügen Sie einfach eine Methode am Ende Ihrer Liste hinzu, wo Sie an datagridview DataSource binden:

dataGridView1.DataSource = MyList.ToList();

0

Sie können es versuchen, die Reihenfolge der Spalten ist Ihnen egal.

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

0

Zum Beispiel für ClickCell-Ereignis in 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);
                }

Grüße :)


0

Falls jemand C # verwendet (oder siehe Hinweis zu VB.NET unten) und diesen Punkt erreicht hat, aber immer noch nicht weiterkommt, lesen Sie bitte weiter.

Joshuas Antwort hat mir geholfen, aber nicht den ganzen Weg. Sie werden bemerken, dass Peter fragte "Woher würden Sie den Knopf bekommen?", Aber unbeantwortet blieb.

Die einzige Möglichkeit für mich bestand darin, einen der folgenden Schritte auszuführen, um meinen Ereignishander hinzuzufügen (nachdem die DataSource von DataGridView zu meiner DataTable und die DataGridViewButtonColumn zur DataGridView hinzugefügt wurden):

Entweder:

dataGridView1.CellClick += new DataGridViewCellEventHandler(dataGridView1_CellClick);

oder:

dataGridView1.CellContentClick += new DataGridViewCellEventHandler(dataGridView1_CellContentClick);

Fügen Sie dann die in den verschiedenen Antworten oben gezeigte Handlermethode hinzu (entweder dataGridView1_CellClick oder dataGridView1_CellContentClick).

Hinweis: VB.NET unterscheidet sich in dieser Hinsicht von C #, da wir der Signatur unserer Methode einfach eine Handles-Klausel hinzufügen oder eine AddHandler-Anweisung ausgeben können, wie im Microsoft-Dokument "Gewusst wie: Aufrufen eines Ereignishandlers in Visual Basic " beschrieben.


0

Sie werden eine solche Schaltflächenspalte in Ihre dataGridView einfügen

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


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

Anschließend können Sie einige Aktionen innerhalb des Zellenklickereignisses hinzufügen. Ich fand, dass dies der einfachste Weg ist.

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


    }

Ich habe festgestellt, dass das Cell Click-Ereignis häufig automatisch abonniert wird. Also brauchte ich diesen Code unten nicht. Wenn Ihr Zellenklickereignis jedoch nicht abonniert ist, fügen Sie diese Codezeile für Ihre dataGridView hinzu.

     this.dataGridView.CellClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView_CellClick);
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.