it-swarm.com.de

Wie erkennt man die Änderung der DataGridView CheckBox-Ereignisse?

Ich habe eine Winforms-App und möchte Code auslösen, wenn ein in ein DataGridView-Steuerelement eingebettetes Kontrollkästchen aktiviert/deaktiviert ist. Jede Veranstaltung habe ich entweder ausprobiert

  1. Wird ausgelöst, sobald auf CheckBox geklickt wird, aber bevor der geprüfte Status geändert wird, oder
  2. Triggert nur, wenn CheckBox den Fokus verliert

Ich kann anscheinend kein Ereignis finden, das unmittelbar nach Änderungen des geprüften Status ausgelöst wird.


Bearbeiten:

Was ich versuche zu erreichen, ist, dass, wenn sich der überprüfte Zustand eines CheckBox in einem DataGridView ändert, sich die Daten in zwei anderen DataGridViews ändern. Bei allen Ereignissen, die ich verwendet habe, ändern sich die Daten in den anderen Rastern erst, wenn CheckBox im ersten DataGridView den Fokus verliert. 

63
PJW

Um mit dem Ereignis DatGridViews CheckedChanged umzugehen, müssen Sie zuerst die CellContentClick abschießen lassen (die nicht den aktuellen Status CheckBoxes hat!) Und dann CommitEdit aufrufen. Dadurch wird das CellValueChanged-Ereignis ausgelöst, mit dem Sie Ihre Arbeit erledigen können. Dies ist ein Versehen von Microsoft. Tun Sie etwas wie das Folgende ...

private void dataGridViewSites_CellContentClick(object sender, 
    DataGridViewCellEventArgs e)
{
    dataGridViewSites.CommitEdit(DataGridViewDataErrorContexts.Commit);
}

/// <summary>
/// Works with the above.
/// </summary>
private void dataGridViewSites_CellValueChanged(object sender, 
    DataGridViewCellEventArgs e)
{
    UpdateDataGridViewSite();
}

Ich hoffe das hilft.

P.S. Überprüfen Sie diesen Artikel https://msdn.Microsoft.com/en-us/library/system.windows.forms.datagridview.currentcelldirtystatechanged(v=vs.110).aspx

76
MoonKnight

Ich habe @ Killercams Lösung gefunden, um zu funktionieren, aber es war ein wenig zwielichtig, wenn der Benutzer zu schnell auf einen Doppelklick klickte. Nicht sicher, ob andere den Fall gefunden haben. Ich habe eine andere Lösung gefunden hier .

Es verwendet die Variablen CellValueChanged und CellMouseUp des Datagrids. Changhong erklärt das 

"Der Grund dafür ist, dass das OnCellvalueChanged-Ereignis erst ausgelöst wird, wenn DataGridView der Meinung ist, dass Sie die Bearbeitung abgeschlossen haben. Sinn für eine CheckBox. "

Hier ist es in Aktion von seinem Beispiel:

private void myDataGrid_OnCellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    if (e.ColumnIndex == myCheckBoxColumn.Index && e.RowIndex != -1)
    {
        // Handle checkbox state change here
    }
}

Und den Code, um das Kontrollkästchen mitzuteilen, dass die Bearbeitung erfolgt ist, wenn darauf geklickt wird, anstatt zu warten, bis der Benutzer das Feld verlässt:

private void myDataGrid_OnCellMouseUp(object sender,DataGridViewCellMouseEventArgs e)
{
    // End of edition on each click on column of checkbox
    if (e.ColumnIndex == myCheckBoxColumn.Index && e.RowIndex != -1)
    {
        myDataGrid.EndEdit();
    }
}
74
jsturtevant

die Lösung von jsturtevants hat gut funktioniert. Ich entschied mich jedoch für die Verarbeitung im EndEdit-Ereignis. Ich bevorzuge diesen Ansatz (in meiner Anwendung), da das EndEdit-Ereignis im Gegensatz zum CellValueChanged-Ereignis nicht ausgelöst wird, während Sie das Raster füllen.

Hier ist mein Code (ein Teil davon wird von jsturtevant gestohlen:

private void gridCategories_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    if (e.ColumnIndex == gridCategories.Columns["AddCategory"].Index)
    {
        //do some stuff
    }
}



private void gridCategories_CellMouseUp(object sender, DataGridViewCellMouseEventArgs e)
{
    if (e.ColumnIndex == gridCategories.Columns["AddCategory"].Index)
    {
        gridCategories.EndEdit();
    }
}
7
Mark Ainsworth

Dies übernimmt auch die Tastaturaktivierung.

    private void dgvApps_CellContentClick(object sender, DataGridViewCellEventArgs e)
    {
        if(dgvApps.CurrentCell.GetType() == typeof(DataGridViewCheckBoxCell))
        {
            if (dgvApps.CurrentCell.IsInEditMode)
            {
                if (dgvApps.IsCurrentCellDirty)
                {
                    dgvApps.EndEdit();
                }
            }
        }
    }


    private void dgvApps_CellValueChanged(object sender, DataGridViewCellEventArgs e)
    {
          // handle value changed.....
    }
5
Chuck Fecteau

folge Killercam'answer, Mein Code 

private void dgvProducts_CellContentClick(object sender, DataGridViewCellEventArgs e)
    {
        dgvProducts.CommitEdit(DataGridViewDataErrorContexts.Commit);
    }

und :

private void dgvProducts_CellValueChanged(object sender, DataGridViewCellEventArgs e)
    {
        if (dgvProducts.DataSource != null)
        {
            if (dgvProducts.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString() == "True")
            {
                //do something
            }
            else
            {
               //do something
            }
        }
    }
4
Nghĩa Lê

Hier ist ein Code:

private void dgvStandingOrder_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    if (dgvStandingOrder.Columns[e.ColumnIndex].Name == "IsSelected" && dgvStandingOrder.CurrentCell is DataGridViewCheckBoxCell)
    {
        bool isChecked = (bool)dgvStandingOrder[e.ColumnIndex, e.RowIndex].EditedFormattedValue;
        if (isChecked == false)
        {
            dgvStandingOrder.Rows[e.RowIndex].Cells["Status"].Value = "";
        }
        dgvStandingOrder.EndEdit();
    }
}

private void dgvStandingOrder_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{

    dgvStandingOrder.CommitEdit(DataGridViewDataErrorContexts.Commit);
}

private void dgvStandingOrder_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
    if (dgvStandingOrder.CurrentCell is DataGridViewCheckBoxCell)
    {
        dgvStandingOrder.CommitEdit(DataGridViewDataErrorContexts.Commit);
    }
}
4
Nay Lin Aung

Ich habe eine einfachere Antwort auf dieses Problem gefunden. Ich verwende einfach die umgekehrte Logik. Der Code befindet sich in VB, unterscheidet sich jedoch nicht wesentlich von C #.

 Private Sub DataGridView1_CellContentClick(sender As Object, e As 
 DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick

    Dim _ColumnIndex As Integer = e.ColumnIndex
    Dim _RowIndex As Integer = e.RowIndex

    'Uses reverse logic for current cell because checkbox checked occures 
     'after click
    'If you know current state is False then logic dictates that a click 
     'event will set it true
    'With these 2 check boxes only one can be true while both can be off

    If DataGridView1.Rows(_RowIndex).Cells("Column2").Value = False And 
       DataGridView1.Rows(_RowIndex).Cells("Column3").Value = True Then
        DataGridView1.Rows(_RowIndex).Cells("Column3").Value = False
    End If

    If DataGridView1.Rows(_RowIndex).Cells("Column3").Value = False And 
    DataGridView1.Rows(_RowIndex).Cells("Column2").Value = True Then
        DataGridView1.Rows(_RowIndex).Cells("Column2").Value = False
    End If


End Sub

Das Beste daran ist, dass nicht mehrere Events erforderlich sind.

2
Jimva

Es geht nur um das Bearbeiten der Zelle. Das Problem ist, dass die Zelle tatsächlich nicht bearbeitet wurde. Sie müssen also die Änderungen der Zelle oder der Zeile speichern, um das Ereignis zu erhalten, wenn Sie das Kontrollkästchen aktivieren.

datagridview.CommitEdit(DataGridViewDataErrorContexts.CurrentCellChange)

damit können Sie es auch bei einer anderen Veranstaltung verwenden.

2
ahmedcool166

In dem Event CellContentClick können Sie diese Strategie verwenden:

private void myDataGrid_CellContentClick(object sender, DataGridViewCellEventArgs e)
{    
    if (e.ColumnIndex == 2)//set your checkbox column index instead of 2
    {   //When you check
        if (Convert.ToBoolean(myDataGrid.Rows[e.RowIndex].Cells[2].EditedFormattedValue) == true)
        {
            //EXAMPLE OF OTHER CODE
            myDataGrid.Rows[e.RowIndex].Cells[5].Value = DateTime.Now.ToShortDateString();

            //SET BY CODE THE CHECK BOX
            myDataGrid.Rows[e.RowIndex].Cells[2].Value = 1;
        }
        else //When you decheck
        {
            myDataGrid.Rows[e.RowIndex].Cells[5].Value = String.Empty;

            //SET BY CODE THE CHECK BOX
            myDataGrid.Rows[e.RowIndex].Cells[2].Value = 0;
        }
    }
}
1
daniele3004

Der Code wird in DataGridView wiederholt und überprüft, ob die CheckBox-Spalte markiert ist

private void dgv1_CellMouseUp(object sender, DataGridViewCellMouseEventArgs e)
{
    if (e.ColumnIndex == 0 && e.RowIndex > -1)
    {
        dgv1.CommitEdit(DataGridViewDataErrorContexts.Commit);
        var i = 0;
        foreach (DataGridViewRow row in dgv1.Rows)
        {
            if (Convert.ToBoolean(row.Cells[0].Value))
            {
                i++;
            }
        }

        //Enable Button1 if Checkbox is Checked
        if (i > 0)
        {
            Button1.Enabled = true;
        }
        else
        {
            Button1.Enabled = false;
        }
    }
}
1
E Coder

Was für mich funktionierte, war CurrentCellDirtyStateChanged in Kombination mit datagridView1.EndEdit()

private void dataGridView1_CurrentCellDirtyStateChanged( object sender, EventArgs e ) {
    if ( dataGridView1.CurrentCell is DataGridViewCheckBoxCell ) {
        DataGridViewCheckBoxCell cb = (DataGridViewCheckBoxCell)dataGridView1.CurrentCell;
        if ( (byte)cb.Value == 1 ) {
            dataGridView1.CurrentRow.Cells["time_loadedCol"].Value = DateTime.Now.ToString();
        }
    }
    dataGridView1.EndEdit();
}
1
beetroot123

Durch das Entfernen des Fokus nach Änderungen der Zellenwerte können die Werte in DataGridView aktualisiert werden. Entfernen Sie den Fokus, indem Sie die CurrentCell auf null setzen.

private void DataGridView1OnCellValueChanged(object sender, DataGridViewCellEventArgs dataGridViewCellEventArgs)
{
    // Remove focus
    dataGridView1.CurrentCell = null;
    // Put in updates
    Update();
}

private void DataGridView1OnCurrentCellDirtyStateChanged(object sender, EventArgs eventArgs)
{
    if (dataGridView1.IsCurrentCellDirty)
    {
        dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
    }

}
0
Branden Huggins

Um dies bei der Verwendung des Devexpress xtragrid zu tun, ist es notwendig, das EditValueChanged -Ereignis eines entsprechenden Repository-Elements wie hier zu behandeln. Es ist auch wichtig, die gridView1.PostEditor () - Methode aufzurufen, um sicherzustellen, dass der geänderte Wert gebucht wurde. Hier ist eine Implementierung:

        private void RepositoryItemCheckEdit1_EditValueChanged(object sender, System.EventArgs e)
        {
            gridView3.PostEditor();

            var isNoneOfTheAboveChecked = false;

            for (int i = 0; i < gridView3.DataRowCount; i++)
            {
                if ((bool) (gridView3.GetRowCellValue(i, "NoneOfTheAbove")) && (bool) (gridView3.GetRowCellValue(i, "Answer")))
                {
                    isNoneOfTheAboveChecked = true;
                    break;
                }
            }

            if (isNoneOfTheAboveChecked)
            {
                for (int i = 0; i < gridView3.DataRowCount; i++)
                {
                    if (!((bool)(gridView3.GetRowCellValue(i, "NoneOfTheAbove"))))
                    {
                        gridView3.SetRowCellValue(i, "Answer", false);
                    }
                }
            }
        }

Beachten Sie, dass das Xtragrid keinen Enumerator bereitstellt. Daher muss eine for-Schleife zum Durchlaufen von Zeilen verwendet werden.

0
majjam

Sie können die Zelle zwingen, den Wert festzuschreiben, sobald Sie auf das Kontrollkästchen klicken und das Ereignis CellValueChanged abrufen. Das CurrentCellDirtyStateChanged wird ausgelöst, sobald Sie auf das Kontrollkästchen klicken. 

Der folgende Code funktioniert für mich:

private void grid_CurrentCellDirtyStateChanged(object sender, EventArgs e)
    {
        SendKeys.Send("{tab}");
    }

Sie können dann Ihren Code in das Ereignis CellValueChanged einfügen.

0
David Ruiz

Ich habe eine einfachere Antwort auf dieses Problem gefunden. Ich verwende einfach die umgekehrte Logik. Der Code befindet sich in VB, unterscheidet sich jedoch nicht wesentlich von C #.

 Private Sub DataGridView1_CellContentClick(sender As Object, e As 
 DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick

    Dim _RowIndex As Integer = e.RowIndex

    'Uses reverse logic for current cell because checkbox checked occures 
     'after click
    'If you know current state is False then logic dictates that a click 
     'event will set it true
    'With these 2 check boxes only one can be true while both can be off

    If DataGridView1.Rows(_RowIndex).Cells("Column2").Value = False And 
       DataGridView1.Rows(_RowIndex).Cells("Column3").Value = True Then
        DataGridView1.Rows(_RowIndex).Cells("Column3").Value = False
    End If

    If DataGridView1.Rows(_RowIndex).Cells("Column3").Value = False And 
    DataGridView1.Rows(_RowIndex).Cells("Column2").Value = True Then
        DataGridView1.Rows(_RowIndex).Cells("Column2").Value = False
    End If


End Sub

Das Beste daran ist, dass nicht mehrere Events erforderlich sind.

0
Jimva

Ich habe hier einige Antworten ausprobiert, aber ich hatte immer ein Problem (z. B. Doppelklicken oder Verwenden der Tastatur). Also habe ich einige von ihnen kombiniert und ein konsistentes Verhalten erhalten (es ist nicht perfekt, funktioniert aber einwandfrei).

void gridView_CellContentClick(object sender, DataGridViewCellEventArgs e) {
  if(gridView.CurrentCell.GetType() != typeof(DataGridViewCheckBoxCell))
    return;
  if(!gridView.CurrentCell.IsInEditMode)
    return;
  if(!gridView.IsCurrentCellDirty)
    return;
  gridView.EndEdit();
}

void gridView_CellMouseUp(object sender, DataGridViewCellMouseEventArgs e) {
  if(e.ColumnIndex == gridView.Columns["cFlag"].Index && e.RowIndex >= 0)
    gridView.EndEdit();
}

void gridView_CellValueChanged(object sender, DataGridViewCellEventArgs e) {
  if(e.ColumnIndex != gridView.Columns["cFlag"].Index || e.RowIndex < 0)
    return;

  // Do your stuff here.

}
0
Félix Severo