Saya memiliki aplikasi winforms dan ingin memicu beberapa kode ketika kotak centang yang disematkan dalam DataGridView
kontrol dicentang / tidak dicentang. Setiap acara saya coba juga
- Memicu segera setelah
CheckBox
diklik tetapi sebelum status yang dicentang berubah, atau - Memicu hanya setelah
CheckBox
kehilangan fokusnya
Sepertinya saya tidak dapat menemukan peristiwa yang terpicu segera setelah status yang dicentang berubah.
Edit:
Apa yang saya coba capai adalah ketika status yang dicentang dari a CheckBox
dalam satu DataGridView
berubah, data di dua lainnya DataGridView
berubah. Namun semua kejadian yang telah saya gunakan, data di kisi lain hanya berubah setelah CheckBox
di kisi pertama DataGridView
kehilangan fokus.
c#
winforms
datagridview
PJW
sumber
sumber
CurrentCellDirtyStateChanged
Acara?Jawaban:
Untuk menangani peristiwa
DatGridView
s,CheckedChanged
pertama-tama Anda harusCellContentClick
mengaktifkan to (yang tidak memiliki statusCheckBox
es saat ini!) Lalu panggilCommitEdit
. Ini pada gilirannya akan mengaktifkanCellValueChanged
peristiwa yang dapat Anda gunakan untuk melakukan pekerjaan Anda. Ini adalah pengawasan dari Microsoft . Lakukan beberapa hal seperti berikut ...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(); }
Saya harap ini membantu.
PS Periksa artikel ini https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.currentcelldirtystatechanged(v=vs.110).aspx
sumber
DataGridViewCheckBox
. Ini bukan WPF dan mengklik dua kali kontrol tidak melanggar pengikatan data apa pun, ini adalah WinForms. Mengklik dua kali mungkin tidak memperbarui kontrol secara visual tetapi tidak merusak apa pun dan dalam kasus ini mungkin solusi di bawah ini adalah yang lebih baik. Terima kasih.CellContentClick
keCellContentDoubleClick
juga.CellMouseUp
is akan aktif bahkan jika sel dipilih tetapi kotak centang tidak diklik - yang bukan merupakan perilaku yang diinginkan.Saya menemukan solusi @ Killercam untuk bekerja tetapi agak cerdik jika pengguna mengklik dua kali terlalu cepat. Tidak yakin apakah orang lain juga menemukan kasus itu. Saya menemukan solusi lain di sini .
Ini menggunakan datagrid
CellValueChanged
danCellMouseUp
. Changhong menjelaskan ituIni dia tindakan dari contohnya:
private void myDataGrid_OnCellValueChanged(object sender, DataGridViewCellEventArgs e) { if (e.ColumnIndex == myCheckBoxColumn.Index && e.RowIndex != -1) { // Handle checkbox state change here } }
Dan kode untuk memberi tahu kotak centang itu selesai mengedit saat diklik, alih-alih menunggu sampai pengguna meninggalkan bidang:
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(); } }
Edit: Peristiwa DoubleClick diperlakukan terpisah dari peristiwa MouseUp. Jika peristiwa DoubleClick terdeteksi, aplikasi akan mengabaikan sepenuhnya peristiwa MouseUp pertama. Logika ini perlu ditambahkan ke acara CellDoubleClick selain acara 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(); } }
sumber
KeyPreview
ke true pada formulir dan kapane.KeyCode == Keys.Space
, setele.Handled = true
. Dengan kata lain, saya baru saja menonaktifkan pengeditan keyboard.Solusi jsturtevants bekerja dengan baik. Namun, saya memilih untuk melakukan pemrosesan di acara EndEdit. Saya lebih suka pendekatan ini (dalam aplikasi saya) karena, tidak seperti acara CellValueChanged, acara EndEdit tidak menyala saat Anda mengisi kisi.
Ini kode saya (sebagian dicuri dari 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(); } }
sumber
CellContentClick
daripadaCellMouseUp
karena yang terakhir akan dipanggil saat pengguna mengklik di mana saja di dalam sel sedangkan yang pertama hanya dipanggil saat kotak centang diklik.Ini juga menangani aktivasi keyboard.
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..... }
sumber
Berikut beberapa kode:
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); } }
sumber
CommitEdit
dariCurrentCellDirtyStateChanged
adalah solusi keseluruhan.mengikuti jawaban Killercam, kode saya
private void dgvProducts_CellContentClick(object sender, DataGridViewCellEventArgs e) { dgvProducts.CommitEdit(DataGridViewDataErrorContexts.Commit); }
dan:
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 } } }
sumber
Ini semua tentang mengedit sel, masalahnya adalah sel tidak diedit sebenarnya, jadi Anda perlu menyimpan Perubahan sel atau baris untuk mendapatkan acara saat Anda mengklik kotak centang sehingga Anda dapat menggunakan fungsi ini:
dengan ini, Anda dapat menggunakannya bahkan dengan acara yang berbeda.
sumber
Saya telah menemukan jawaban yang lebih sederhana untuk masalah ini. Saya hanya menggunakan logika terbalik. Kode ada di VB tetapi tidak jauh berbeda dengan 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
Salah satu hal terbaik tentang ini adalah tidak perlu mengadakan banyak acara.
sumber
Apa yang berhasil bagi saya adalah
CurrentCellDirtyStateChanged
kombinasi dengandatagridView1.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(); }
sumber
Kode akan berputar di DataGridView dan Akan memeriksa apakah Kolom Kotak Centang Dicentang
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; } } }
sumber
Dalam acara CellContentClick Anda dapat menggunakan strategi ini:
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; } } }
sumber
Saya sudah mencoba beberapa jawaban dari sini, tetapi saya selalu mengalami masalah (seperti mengklik dua kali atau menggunakan keyboard). Jadi, saya menggabungkan beberapa di antaranya dan mendapatkan perilaku yang konsisten (tidak sempurna, tetapi berfungsi dengan baik).
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. }
sumber
Untuk melakukan ini saat menggunakan devexpress xtragrid, perlu untuk menangani acara EditValueChanged item repositori terkait seperti yang dijelaskan di sini . Penting juga untuk memanggil metode gridView1.PostEditor () untuk memastikan nilai yang diubah telah diposting. Berikut implementasinya:
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); } } } }
Perhatikan bahwa karena xtragrid tidak menyediakan enumerator, maka perlu menggunakan loop for untuk mengulang baris.
sumber
Menghapus fokus setelah perubahan nilai sel memungkinkan nilai untuk diperbarui di DataGridView. Hapus fokus dengan mengatur CurrentCell ke 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); } }
sumber
Anda bisa memaksa sel untuk memasukkan nilai segera setelah Anda mengklik kotak centang dan kemudian menangkap acara CellValueChanged . The CurrentCellDirtyStateChanged kebakaran segera setelah Anda klik kotak centang.
Kode berikut berfungsi untuk saya:
private void grid_CurrentCellDirtyStateChanged(object sender, EventArgs e) { SendKeys.Send("{tab}"); }
Anda kemudian dapat memasukkan kode Anda di acara CellValueChanged .
sumber
Ben Voigt menemukan solusi terbaik dalam balasan komentar di atas:
private void dgvStandingOrder_CurrentCellDirtyStateChanged(object sender, EventArgs e) { if (dgvStandingOrder.CurrentCell is DataGridViewCheckBoxCell) dgvStandingOrder.CommitEdit(DataGridViewDataErrorContexts.Commit); }
Serius, hanya itu yang Anda butuhkan.
sumber