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
CheckBox
geklickt wird, aber bevor der geprüfte Status geändert wird, oderCheckBox
den Fokus verliertIch 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 DataGridView
s ä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.
Um mit dem Ereignis DatGridView
s CheckedChanged
umzugehen, müssen Sie zuerst die CellContentClick
abschießen lassen (die nicht den aktuellen Status CheckBox
es 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
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();
}
}
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();
}
}
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.....
}
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
}
}
}
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);
}
}
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.
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.
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;
}
}
}
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;
}
}
}
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();
}
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);
}
}
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.
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.
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.
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.
}