106

新しい状態でCheckedItemsを使用できるように、アイテムがチェックされた後にイベントが必要なCheckedListBoxがあります。

ItemCheckedは、CheckedItemsが更新される前に起動されるため、そのままでは機能しません。

CheckedItemsが更新されたときに通知を受け取るために、どのようなメソッドまたはイベントを使用できますか?

4

16 に答える 16

97

ItemCheckクリックされているアイテムの新しい状態も確認すれば、イベントを利用できます。これは、イベントargsで。として利用できます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());
        else
            checkedItems.Remove(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
        ...
}
于 2010-09-08T11:00:22.323 に答える
44

これには関連するStackOverflowの投稿がたくさんあります... Branimirのソリューションと同様に、さらに2つの簡単な投稿があります。

ItemCheckでの実行の遅延(これもここにあります):

    void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
    {
        this.BeginInvoke((MethodInvoker) (
            () => Console.WriteLine(checkedListBox1.SelectedItems.Count)));
    }

MouseUpイベントの使用

    void checkedListBox1_MouseUp(object sender, MouseEventArgs e)
    {
        Console.WriteLine(checkedListBox1.SelectedItems.Count);
    }

私は最初のオプションを好みます。2番目のオプションは誤検知を引き起こすためです(つまり、頻繁に発砲します)。

于 2013-06-05T09:43:24.580 に答える
26

私はこれを試しましたが、うまくいきました:

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();        
}
于 2013-07-07T11:26:41.483 に答える
11

派生し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);
}
于 2013-08-28T12:11:49.403 に答える
4

理想的ではありませんが、イベントに渡される引数を使用してCheckedItemsを計算できますItemCheckMSDNでこの例を見ると、新しく変更されたアイテムがチェックされているかどうかがわかります。これにより、アイテムを操作するのに適した位置になります。

アイテムがチェックされた後に発生する新しいイベントを作成することもできます。これにより、必要に応じて必要なものを正確に提供できます。

于 2010-09-08T11:01:47.980 に答える
4

いくつかのテストの後、イベントSelectedIndexChangedがイベントItemCheckの後にトリガーされることがわかりました。プロパティCheckOnClickをTrueのままにします

最高のコーディング

于 2014-08-11T19:02:19.737 に答える
3

これは機能しますが、どれほどエレガントかはわかりません。

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
于 2013-06-10T19:35:29.143 に答える
1

これが当てはまるかどうかはわかりませんが、チェックリストボックスを使用して結果をフィルタリングしたいと思いました。そのため、ユーザーがアイテムをオンまたはオフにしたときに、リストにアイテムを表示/非表示にしました。

私はこの投稿に私を導いたいくつかの問題を抱えていました。特別なことをせずに、私がどのようにそれをしたかを共有したかっただけです。

注:CheckOnClick = trueを使用していますが、それがなくても機能する可能性があります。

私が使用するイベントは「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
        }
   }

}
于 2015-08-14T17:26:24.043 に答える
1

からの引数を保持したいがItemCheck、モデルが変更された後に通知を受け取ると仮定すると、次のようになります。

CheckedListBox ctrl = new CheckedListBox();
ctrl.ItemCheck += (s, e) => BeginInvoke((MethodInvoker)(() => CheckedItemsChanged(s, e)));

どこCheckedItemsChangedにある可能性があります:

private void CheckedItemsChanged(object sender, EventArgs e)
{
    DoYourThing();
}
于 2018-02-06T14:40:00.940 に答える
1

私はこれを試しましたが、うまくいきました:

    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);
        }
    }

リストのインデックスによって決定します。

于 2020-06-26T09:10:26.707 に答える
0

チェックリストボックスではなく、チェックボックスリストを意味しますか?その場合、関連するイベントはSelectedIndexChangedになります。

例:VBのハンドラー定義ヘッド:

Protected Sub cblStores_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cblStores.SelectedIndexChanged
于 2020-12-01T11:45:47.007 に答える
0

コントロールの感覚を気にせず、チェックボックスの変更が実際にすでに行われたかのようにイベントを処理することにしました。CheckedIndicesリストを取得し、オブジェクト内の情報を使用しItemCheckEventArgsて新しい状態に調整するだけです。

Items次に、そのリストをループして、コントロールのプロパティから指定されたアイテムを取得するだけで、リストが作成されますCheckedItems

private void CheckedList_ItemCheck(Object sender, ItemCheckEventArgs e)
{
    CheckedListBox checkedList = sender as CheckedListBox;
    if (checkedList == null)
        return;
    // Somehow this still returns the state before the check, so update it manually.
    List<Int32> checkedIndices = checkedList.CheckedIndices.Cast<Int32>().ToList();
    if (e.NewValue == CheckState.Unchecked)
        checkedIndices.Remove(e.Index);
    else if (e.NewValue == CheckState.Checked)
        checkedIndices.Add(e.Index);
    checkedIndices.Sort()
    Int32 checkedItemCount = checkedIndices.Length;
    Object[] checkedItems = new Object[checkedItemCount]
    for (Int32 i = 0; i < checkedItemCount; i++)
        checkedItems[i] = checkedList.Items[checkedIndices[i]];
    this.UpdateAfterCheckChange(checkedItems);
}

結果は、変更後にのみイベントがトリガーされるという仮想の望ましいケースと機能的に同じです。

于 2021-02-25T17:54:32.623 に答える
0

アイテムがチェックされるように、ハンドラーに対するDuncの回答のVB.NETバージョン。BeginInvoke

Private Sub ChkListBox1_ItemCheck(sender As Object, e As ItemCheckEventArgs) Handles ChkListBox1.ItemCheck


  Debug.WriteLine($"checked item count {ChkListBox1.CheckedItems.Count}")

  Debug.WriteLine($"{ChkListBox1.Items(e.Index)} - {e.Index} - {e.NewValue}")

  BeginInvoke(Sub() HandleItemCheck(e))

End Sub


Private Sub HandleItemCheck(e As ItemCheckEventArgs)

  Debug.WriteLine($"handle item {ChkListBox1.Items(e.Index)} - {e.Index} - {e.NewValue}")

  Debug.WriteLine($"checked item count handle item - {ChkListBox1.CheckedItems.Count}")

End Sub
于 2021-06-24T16:27:58.600 に答える
0

私のように、選択を1つのインジケーター(ユーザーが選択したアイテム)として使用しようとしていて、ユーザーがティックを変更したい場合は、卑劣な解決策を見つけました。

Form variables
    Private IsTicked As Boolean = False
    Private ListIndex = -1

ページ上にタイマーを作成します。たとえば、私のものはと呼ばれtmrBan、私はとCheckBoxList呼ばれていclbFTIます。

次に、のクリックイベントを作成しますCheckBoxList

Private Sub clbFTI_Click(sender As Object, e As EventArgs) Handles lbFTI.MouseClick
    ListIndex = sender.SelectedIndex
    IsTicked = clbFTI.SelectedIndices.Contains(ListIndex)
    tmrBan.Interval = 10
    tmrBan.Enabled = True
End Sub

次に、タイマーのティックイベントを作成します

Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles tmrBan.Tick
    clbFTI.SetItemChecked(ListIndex, IsTicked)
End Sub

ティックのちらつきが表示されますが、タイマーの間隔を試して、ケースに合わせてこれを改善してください。

于 2021-08-01T13:47:55.700 に答える
-1

私はこの問題を解決するためにタイマーを使用しています。ItemCheckイベントを介してタイマーを有効にします。タイマーのティックイベントでアクションを実行します。

これは、アイテムがマウスクリックでチェックされているか、スペースバーを押してチェックされているかに関係なく機能します。チェックしたばかりの(またはチェックしていない)アイテムが常に選択されたアイテムであるという事実を利用します。

タイマーの間隔は1まで低くすることができます。ティックイベントが発生するまでに、新しいチェック済みステータスが設定されます。

このVB.NETコードは概念を示しています。使用できるバリエーションはたくさんあります。タイマーの間隔を長くして、ユーザーがアクションを実行する前にいくつかの項目のチェックステータスを変更できるようにすることができます。次に、Tickイベントで、リスト内のすべてのアイテムを順次パスするか、そのCheckedItemsコレクションを使用して適切なアクションを実行します。

そのため、最初にItemCheckイベントでタイマーを無効にします。無効にしてから有効にすると、インターバル期間が再開されます。

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
于 2015-04-10T20:29:51.187 に答える
-1

通常の動作では、1つのアイテムをチェックすると、イベントハンドラーが発生する前にアイテムのチェック状態が変化します。ただし、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());}
于 2015-11-17T05:32:11.443 に答える