Saya memiliki CheckedListBox di mana saya ingin acara setelah item dicentang sehingga saya dapat menggunakan CheckedItems dengan status baru.
Karena ItemChecked diaktifkan sebelum CheckedItems diperbarui, itu tidak akan berfungsi di luar kotak.
Jenis metode atau acara apa yang dapat saya gunakan untuk diberi tahu saat CheckedItems diperbarui?
c#
winforms
checkedlistbox
hultqvist
sumber
sumber
if not item = checkedListBox1.Items[e.Index].ToString()
Ada banyak posting StackOverflow terkait tentang ini ... Selain solusi Branimir , berikut dua yang lebih sederhana:
Eksekusi tertunda di ItemCheck (juga di sini ):
void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e) { this.BeginInvoke((MethodInvoker) ( () => Console.WriteLine(checkedListBox1.SelectedItems.Count))); }
Menggunakan acara MouseUp :
void checkedListBox1_MouseUp(object sender, MouseEventArgs e) { Console.WriteLine(checkedListBox1.SelectedItems.Count); }
Saya lebih suka opsi pertama, karena yang kedua akan menghasilkan positif palsu (mis. Menembak terlalu sering).
sumber
The check state is not updated until after the ItemCheck event occurs
. Acara yang berbeda atau solusi yang tidak sewenang-wenang akan menjadi IMO yang bagus.Saya mencoba ini dan berhasil:
private void clbOrg_ItemCheck(object sender, ItemCheckEventArgs e) { CheckedListBox clb = (CheckedListBox)sender; // Switch off event handler clb.ItemCheck -= clbOrg_ItemCheck; clb.SetItemCheckState(e.Index, e.NewValue); // Switch on event handler clb.ItemCheck += clbOrg_ItemCheck; // Now you can go further CallExternalRoutine(); }
sumber
ItemChecked
acara tersebut, dan tidak ada yang pernah membahas bahwa acara tersebut tidak ada.ItemChecking
,ItemChecked
, maka Anda bisa menggunakan salah satu yang terakhir. Tetapi jika hanya satu yang diimplementasikan (ItemCheck
) itu melakukan hal-hal dengan benar, yaitu mengaktifkan peristiwa sebelum nilai diperiksa dengan nilai baru dan indeks disediakan sebagai parameter. Siapa pun yang menginginkan acara "setelah perubahan", mereka dapat menggunakan cara di atas. Jika menyarankan sesuatu kepada Microsoft kemudian sarankan acara baruItemChecked
, bukan mengubah yang sudah ada: lihat jawabanBerasal dari
CheckedListBox
dan terapkan/// <summary> /// Raises the <see cref="E:System.Windows.Forms.CheckedListBox.ItemCheck"/> event. /// </summary> /// <param name="ice">An <see cref="T:System.Windows.Forms.ItemCheckEventArgs"/> that contains the event data. /// </param> protected override void OnItemCheck(ItemCheckEventArgs e) { base.OnItemCheck(e); EventHandler handler = AfterItemCheck; if (handler != null) { Delegate[] invocationList = AfterItemCheck.GetInvocationList(); foreach (var receiver in invocationList) { AfterItemCheck -= (EventHandler) receiver; } SetItemCheckState(e.Index, e.NewValue); foreach (var receiver in invocationList) { AfterItemCheck += (EventHandler) receiver; } } OnAfterItemCheck(EventArgs.Empty); } public event EventHandler AfterItemCheck; public void OnAfterItemCheck(EventArgs e) { EventHandler handler = AfterItemCheck; if (handler != null) handler(this, e); }
sumber
BeginInvoke
solusi dari jawaban kedua.Meskipun tidak ideal, Anda bisa menghitung CheckedItems menggunakan argumen yang diteruskan ke
ItemCheck
acara. Jika Anda melihat contoh ini di MSDN , Anda dapat mengetahui apakah item yang baru diubah telah dicentang atau tidak, yang membuat Anda berada dalam posisi yang sesuai untuk bekerja dengan item tersebut.Anda bahkan dapat membuat acara baru yang aktif setelah item dicentang, yang akan memberi Anda apa yang Anda inginkan jika Anda mau.
sumber
Setelah beberapa tes, saya bisa melihat bahwa acara SelectedIndexChanged dipicu setelah acara ItemCheck. Pertahankan properti CheckOnClick True
Pengkodean terbaik
sumber
Ini berfungsi, meskipun tidak yakin seberapa elegannya!
Private Sub chkFilters_Changed(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkFilters.ItemCheck Static Updating As Boolean If Updating Then Exit Sub Updating = True Dim cmbBox As CheckedListBox = sender Dim Item As ItemCheckEventArgs = e If Item.NewValue = CheckState.Checked Then cmbBox.SetItemChecked(Item.Index, True) Else cmbBox.SetItemChecked(Item.Index, False) End If 'Do something with the updated checked box Call LoadListData(Me, False) Updating = False End Sub
sumber
Tidak tahu apakah ini berlaku tetapi saya ingin menggunakan kotak daftar periksa untuk memfilter hasil. Jadi saat pengguna mencentang dan menghapus centang item, saya ingin daftar menampilkan \ sembunyikan item.
Saya mengalami beberapa masalah yang membawa saya ke posting ini. Hanya ingin berbagi bagaimana saya melakukannya tanpa sesuatu yang istimewa.
Catatan: Saya memiliki CheckOnClick = true tetapi mungkin masih akan berfungsi tanpa
Acara yang saya gunakan adalah " SelectedIndexChanged "
pencacahan yang saya gunakan adalah " .CheckedItems "
Ini memberikan hasil yang saya pikir bisa kita harapkan. Sederhananya, itu bermuara pada ....
private void clb1_SelectedIndexChanged(object sender, EventArgs e) { // This just spits out what is selected for testing foreach (string strChoice in clb1.CheckedItems) { listBox1.Items.Add(strChoice); } //Something more like what I'm actually doing foreach (object myRecord in myRecords) { if (clb1.CheckItems.Contains(myRecord["fieldname"]) { //Display this record } } }
sumber
Dengan asumsi Anda ingin mempertahankan argumen dari
ItemCheck
tetapi mendapatkan pemberitahuan setelah model diubah, akan terlihat seperti itu:CheckedListBox ctrl = new CheckedListBox(); ctrl.ItemCheck += (s, e) => BeginInvoke((MethodInvoker)(() => CheckedItemsChanged(s, e)));
Dimana
CheckedItemsChanged
bisa:private void CheckedItemsChanged(object sender, EventArgs e) { DoYourThing(); }
sumber
Saya mencoba ini dan berhasil:
private List<bool> m_list = new List<bool>(); private void Initialize() { for(int i=0; i < checkedListBox1.Items.Count; i++) { m_list.Add(false); } } private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e) { if (e.NewValue == CheckState.Checked) { m_list[e.Index] = true; checkedListBox1.SetItemChecked(e.Index, true); } else { m_list[e.Index] = false; checkedListBox1.SetItemChecked(e.Index, false); } }
tentukan dengan indeks daftar.
sumber
Saya menggunakan Timer untuk mengatasi masalah ini. Aktifkan pengatur waktu melalui acara ItemCheck. Ambil tindakan dalam acara Tik Pengatur Waktu.
Ini berfungsi baik item diperiksa melalui klik mouse atau dengan menekan Space-Bar. Kami akan memanfaatkan fakta bahwa item yang baru saja dicentang (atau tidak dicentang) selalu merupakan Item yang Dipilih.
Interval Pengatur Waktu bisa serendah 1. Pada saat event Tick dimunculkan, status baru yang Dicentang akan ditetapkan.
Kode VB.NET ini menunjukkan konsepnya. Ada banyak variasi yang bisa Anda terapkan. Anda mungkin ingin meningkatkan Interval Pengatur Waktu untuk memungkinkan pengguna mengubah status pemeriksaan pada beberapa item sebelum mengambil tindakan. Kemudian di acara Tick, lakukan pengoperan berurutan dari semua Item dalam Daftar atau gunakan koleksi CheckedItems untuk mengambil tindakan yang sesuai.
Itu sebabnya kami pertama-tama menonaktifkan Timer di acara ItemCheck. Nonaktifkan lalu Aktifkan menyebabkan periode Interval dimulai kembali.
Private Sub ckl_ItemCheck(ByVal sender As Object, _ ByVal e As System.Windows.Forms.ItemCheckEventArgs) _ Handles ckl.ItemCheck tmr.Enabled = False tmr.Enabled = True End Sub Private Sub tmr_Tick(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles tmr.Tick tmr.Enabled = False Debug.Write(ckl.SelectedIndex) Debug.Write(": ") Debug.WriteLine(ckl.GetItemChecked(ckl.SelectedIndex).ToString) End Sub
sumber
Dalam perilaku normal, ketika kita memeriksa satu item, status pemeriksaan item akan berubah sebelum penanganan kejadian dimunculkan. Tetapi CheckListBox memiliki perilaku yang berbeda: Pengendali kejadian dimunculkan sebelum status pemeriksaan item berubah dan itu membuatnya sulit untuk memperbaiki pekerjaan kita.
Menurut pendapat saya, untuk mengatasi masalah ini, kita harus menunda pengendali acara.
private void _clb_ItemCheck(object sender, ItemCheckEventArgs e) { // Defer event handler execution Task.Factory.StartNew(() => { Thread.Sleep(1000); // Do your job at here }) .ContinueWith(t => { // Then update GUI at here },TaskScheduler.FromCurrentSynchronizationContext());}
sumber