Mam aplikację winForms i chcę wyzwolić kod, gdy pole wyboru osadzone w DataGridView
formancie jest zaznaczone / odznaczone. Każde wydarzenie, którego próbowałem
- Uruchamia się zaraz po
CheckBox
kliknięciu, ale przed zmianą stanu zaznaczenia lub - Uruchamia się tylko wtedy, gdy
CheckBox
traci ostrość
Nie mogę znaleźć zdarzenia uruchamiającego się natychmiast po zmianie stanu zaznaczenia.
Edytować:
To, co staram się osiągnąć, to to, że gdy zmienia się stan zaznaczenia CheckBox
jednej w jednej DataGridView
, dane w dwóch innych się DataGridView
zmieniają. Jednak wszystkie zdarzenia, których użyłem, dane w innych siatkach zmieniają się dopiero po tym, jak CheckBox
w pierwszej DataGridView
traci fokus.
c#
winforms
datagridview
PJW
źródło
źródło
CurrentCellDirtyStateChanged
wydarzenie?Odpowiedzi:
Aby obsłużyć zdarzenie
DatGridView
sCheckedChanged
, musisz najpierw uruchomićCellContentClick
polecenie (które nie maCheckBox
obecnego stanu es!), A następnie wywołaćCommitEdit
. To z kolei uruchomiCellValueChanged
zdarzenie, którego możesz użyć do wykonania swojej pracy. To przeoczenie Microsoft . Zrób coś takiego jak następujące ...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(); }
Mam nadzieję, że to pomoże.
PS Sprawdź ten artykuł https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.currentcelldirtystatechanged(v=vs.110).aspx
źródło
DataGridViewCheckBox
polega całe zamieszanie związane z dwukrotnym kliknięciem . To nie jest WPF i dwukrotne kliknięcie kontrolki nie powoduje zerwania żadnego powiązania danych, to WinForms. Podwójne kliknięcie może nie zaktualizować wizualnie kontrolki, ale niczego nie psuje iw tym przypadku być może poniższe rozwiązanie jest lepsze. Dzięki.CellContentClick
doCellContentDoubleClick
.CellMouseUp
Program zostanie uruchomiony, nawet jeśli komórka jest zaznaczona, ale pole wyboru nie jest zaznaczone - co nie jest pożądane.Znalazłem rozwiązanie @ Killercam, które działa, ale było trochę podejrzane, jeśli użytkownik kliknął dwukrotnie zbyt szybko. Nie jestem pewien, czy inni też to stwierdzili. Znalazłem inne rozwiązanie tutaj .
Używa datagridów
CellValueChanged
iCellMouseUp
. Changhong wyjaśnia toOto jego przykład w akcji:
private void myDataGrid_OnCellValueChanged(object sender, DataGridViewCellEventArgs e) { if (e.ColumnIndex == myCheckBoxColumn.Index && e.RowIndex != -1) { // Handle checkbox state change here } }
I kod informujący pole wyboru, że edycja jest zakończona po kliknięciu, zamiast czekać, aż użytkownik opuści pole:
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(); } }
Edycja: zdarzenie DoubleClick jest traktowane oddzielnie od zdarzenia MouseUp. Jeśli wykryte zostanie zdarzenie DoubleClick, aplikacja całkowicie zignoruje pierwsze zdarzenie MouseUp. Ta logika musi zostać dodana do zdarzenia CellDoubleClick oprócz zdarzenia MouseUp:
private void myDataGrid_OnCellDoubleClick(object sender,DataGridViewCellEventArgs e) { // End of edition on each click on column of checkbox if (e.ColumnIndex == myCheckBoxColumn.Index && e.RowIndex != -1) { myDataGrid.EndEdit(); } }
źródło
KeyPreview
na wartość true w formularzu i kiedye.KeyCode == Keys.Space
ustawiłeme.Handled = true
. Innymi słowy, właśnie wyłączyłem edycję klawiatury.Rozwiązanie jsturtevants działało świetnie. Jednak zdecydowałem się wykonać przetwarzanie w zdarzeniu EndEdit. Preferuję to podejście (w mojej aplikacji), ponieważ w przeciwieństwie do zdarzenia CellValueChanged zdarzenie EndEdit nie jest uruchamiane podczas wypełniania siatki.
Oto mój kod (którego część została skradziona z jsturtevant:
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(); } }
źródło
CellContentClick
zamiast tego,CellMouseUp
ponieważ ta druga zostanie wywołana, gdy użytkownik kliknie w dowolnym miejscu w komórce, podczas gdy pierwsza jest wywoływana tylko po kliknięciu pola wyboru.Obsługuje również aktywację klawiatury.
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..... }
źródło
Oto kod:
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); } }
źródło
CommitEdit
zCurrentCellDirtyStateChanged
jest całym rozwiązaniem.po Killercam'answer, My code
private void dgvProducts_CellContentClick(object sender, DataGridViewCellEventArgs e) { dgvProducts.CommitEdit(DataGridViewDataErrorContexts.Commit); }
i :
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 } } }
źródło
Chodzi o edycję komórki, problem polegający na tym, że komórka w rzeczywistości nie była edytowana, więc musisz zapisać zmiany komórki lub wiersza, aby uzyskać zdarzenie po kliknięciu pola wyboru, aby móc użyć tej funkcji:
dzięki temu możesz go użyć nawet z innym wydarzeniem.
źródło
Znalazłem prostszą odpowiedź na ten problem. Po prostu używam logiki odwrotnej. Kod jest w VB, ale niewiele różni się od 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
Jedną z najlepszych rzeczy w tym jest brak konieczności organizowania wielu wydarzeń.
źródło
To, co zadziałało dla mnie, było
CurrentCellDirtyStateChanged
w połączeniu zdatagridView1.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(); }
źródło
Kod zapętli się w DataGridView i sprawdzi, czy kolumna CheckBox jest zaznaczona
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; } } }
źródło
W przypadku CellContentClick możesz skorzystać z tej strategii:
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; } } }
źródło
Wypróbowałem kilka odpowiedzi stąd, ale zawsze miałem jakiś problem (na przykład podwójne kliknięcie lub użycie klawiatury). Więc połączyłem niektóre z nich i uzyskałem spójne zachowanie (nie jest idealne, ale działa poprawnie).
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. }
źródło
Aby to zrobić podczas korzystania z devexpress xtragrid, konieczne jest obsłużenie zdarzenia EditValueChanged odpowiedniego elementu repozytorium, jak opisano tutaj . Ważne jest również wywołanie metody gridView1.PostEditor (), aby upewnić się, że zmieniona wartość została opublikowana. Oto realizacja:
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); } } } }
Zauważ, że ponieważ xtragrid nie zapewnia modułu wyliczającego, konieczne jest użycie pętli for do iteracji po wierszach.
źródło
Usunięcie fokusu po zmianie wartości komórki umożliwia aktualizację wartości w DataGridView. Usuń fokus, ustawiając CurrentCell na null.
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); } }
źródło
Możesz wymusić na komórce zatwierdzenie wartości zaraz po kliknięciu pola wyboru, a następnie przechwyceniu zdarzenia CellValueChanged . CurrentCellDirtyStateChanged pożarów jak najszybciej kliknij pole wyboru.
U mnie działa następujący kod:
private void grid_CurrentCellDirtyStateChanged(object sender, EventArgs e) { SendKeys.Send("{tab}"); }
Następnie możesz wstawić kod w zdarzeniu CellValueChanged .
źródło
Ben Voigt znalazł najlepsze rozwiązanie w komentarzu-odpowiedzi powyżej:
private void dgvStandingOrder_CurrentCellDirtyStateChanged(object sender, EventArgs e) { if (dgvStandingOrder.CurrentCell is DataGridViewCheckBoxCell) dgvStandingOrder.CommitEdit(DataGridViewDataErrorContexts.Commit); }
Poważnie, to wszystko, czego potrzebujesz.
źródło