我有一個CheckedListBox,我想要一個事件後一個項目被選中,以便我可以使用CheckedItems與新狀態。檢查項目後,哪個CheckedListBox事件觸發?
由於ItemChecked是在CheckedItems更新之前觸發的,因此它將無法正常工作。
什麼樣的方法或事件可以用來在CheckedItems更新時得到通知?
我有一個CheckedListBox,我想要一個事件後一個項目被選中,以便我可以使用CheckedItems與新狀態。檢查項目後,哪個CheckedListBox事件觸發?
由於ItemChecked是在CheckedItems更新之前觸發的,因此它將無法正常工作。
什麼樣的方法或事件可以用來在CheckedItems更新時得到通知?
如果您還檢查正在單擊的項目的新狀態,則可以使用ItemCheck
事件。這在事件參數中可用,如e.NewValue
。如果NewValue
檢查,包括當前項目與集合在你的邏輯正確一起:
private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
{
List<string> checkedItems = new List<string>();
foreach (var item in checkedListBox1.CheckedItems)
checkedItems.Add(item.ToString());
if (e.NewValue == CheckState.Checked)
checkedItems.Add(checkedListBox1.Items[e.Index].ToString());
foreach (string item in checkedItems)
{
...
}
}
再舉一個例子,以確定是否徵收將是空後此項目是(未)檢查:
private void ListProjects_ItemCheck(object sender, ItemCheckEventArgs args)
{
if (ListProjects.CheckedItems.Count == 1 && args.NewValue == CheckState.Unchecked)
// The collection is about to be emptied: there's just one item checked, and it's being unchecked at this moment
...
else
// The collection will not be empty once this click is handled
...
}
雖然不理想,但您可以使用傳遞給ItemCheck
事件的參數來計算CheckedItems。如果你看看這個example on MSDN,你可以計算出新更改的項目是否已被選中或未選中,這使您處於合適的位置來處理項目。
你甚至可以創建一個新的事件,在檢查一個項目後觸發,如果你願意,它會給你想要的東西。
關於如何創建這個新事件,您有什麼具體的想法嗎?我怎麼知道CheckCheckItems在ItemChecke事件之後何時更新? – hultqvist 2010-09-09 12:09:04
有很多對本次關聯的StackOverflow職位...以及Branimir's解決方案,這裏有兩個簡單的:
Delayed execution on ItemCheck(也here):
void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
{
this.BeginInvoke((MethodInvoker) (
() => Console.WriteLine(checkedListBox1.SelectedItems.Count)));
}
void checkedListBox1_MouseUp(object sender, MouseEventArgs e)
{
Console.WriteLine(checkedListBox1.SelectedItems.Count);
}
我更喜歡第一個選項,因爲第二個選項會導致誤報(即觸發 太頻繁)。
第二種方法也會錯過通過鍵盤選中或取消選中的項目。 – 2014-01-07 21:56:15
BeginInvoke正是我所需要的,因爲我的事件實際上正在調用一個接口,它不知道它處理的是什麼樣的控制。被接受的答案只適用於邏輯可以在事件處理程序中執行的情況,或者直接從事件處理程序中調用的東西。對我來說情況並非如此。感謝這個真棒但簡單的解決方案。 – Jesse 2017-02-10 14:54:02
這個工程,不知道它有多優雅!
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
我想這和它的工作:
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();
}
這個! ...應該是正確的答案,這是最不幸的。這是一種荒謬的黑客行爲,因爲M $的某個人忘記了執行「ItemChecked」事件,並且從來沒有人說過它不存在。 – RLH 2014-09-26 16:26:30
雖然它不是定義我認爲應該實現的錯誤,如果您同意考慮通過單擊+1支持此錯誤報告:https://connect.microsoft.com/VisualStudio/feedback/details/1759293 – Sebastian 2015-09-06 13:42:12
@Sebastian - 不要在這裏要求解決。對此的任何「修復」都會破壞現有的解決方案。如果有兩個事件:ItemChecking,ItemChecked,那麼你可以使用後者。但是,如果只實現了一個('ItemCheck'),它正確地做了事情,即在* value被檢查之前觸發事件*,新值和索引作爲參數提供。無論誰想要「變更後」事件,他們都可以簡單地使用上述內容。如果向微軟建議,然後建議**新事件** ItemChecked,而不是改變現有的:請參閱[diimdeep的回答](http://stackoverflow.com/a/18487539/2392157) – miroxlav 2015-10-16 08:29:56
派生從CheckedListBox
和實施
/// <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);
}
我用一個定時器來解決這個問題。通過ItemCheck事件啓用計時器。在定時器的滴答事件中採取行動。
無論項目是通過鼠標單擊還是通過按空格鍵進行檢查,這都可以工作。我們將利用這個事實,即剛剛選中的項目(或未選中)始終是選定項目。
定時器的間隔可以低至1.在引發滴答事件時,將設置新的檢查狀態。
這個VB.NET代碼顯示了這個概念。你可以使用很多變化。您可能需要增加計時器間隔,以便用戶在採取措施之前更改多個項目的檢查狀態。然後在Tick事件中,依次傳遞List中的所有Items或使用其CheckedItems集合採取適當的操作。
這就是爲什麼我們首先禁用ItemCheck事件中的Timer。禁用然後啓用導致間隔期重新開始。
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
Thak you for sharing。另一方面,也許您可以從其他答案中學到更好的解決方案。在這種情況下,它是錯誤的工具,因爲你實際上已經獲得了新的值作爲參數,所以你可以使用[這個答案](http://stackoverflow.com/a/17511730/2392157)關閉解決方案或[this one](http://stackoverflow.com/a/18487539/2392157)以獲得系統化解決方案。使用其中一種在線轉換工具將它們從C#轉換爲VB。 – miroxlav 2015-10-16 08:39:10
不知道這是否適用,但我想用checklistbox來過濾結果。因此,當用戶選中和取消選中項目時,我希望列表顯示\隱藏項目。
我遇到了一些問題,導致我到這篇文章。只是想分享我沒做過什麼特別的事情。
注:我有CheckOnClick =真,但它很可能仍然沒有
工作,我使用的事件是 「的SelectedIndexChanged」
我用枚舉 「.CheckedItems」
這給出了我認爲我們可能預期的結果。因此簡化它歸結爲....
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
}
}
}
在正常的行爲,當我們檢查一個項目,項目的檢查狀態將事件處理程序提薪之前改變。 但CheckListBox使用不同的行爲:事件處理程序在檢查項目更改狀態之前引發,並使其難以糾正我們的作業。
在我看來,要解決這個問題,我們應該推遲事件處理程序。
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());}
假設你想從ItemCheck
保留的論據,但得到通知的模式改變了之後應該看起來像:
CheckedListBox ctrl = new CheckedListBox();
ctrl.ItemCheck += (s, e) => BeginInvoke((MethodInvoker)(() => CheckedItemsChanged(s, e)));
凡CheckedItemsChanged
可能是:
private void CheckedItemsChanged(object sender, EventArgs e)
{
DoYourThing();
}
在
首先爲每個,我們可能需要添加一個條件..如果不是項目= checkedListBox1.Items [e.Index] .ToString()' – emaillenin 2012-05-15 10:54:51
問題是,ItemCheck事件是f在檢查處理之前發生。您的解決方案將涉及保留自己的列表,基本上覆制標準代碼。 Dunc的第一個建議(對ItemCheck的延遲執行)是對phq問題最乾淨的回答,因爲它不需要任何額外的處理。 – 2014-08-29 04:48:09