কোন চেকডলিস্টবক্স ইভেন্টটি কোনও আইটেম চেক করার পরে ট্রিগার করে?


96

আমার একটি চেকডলিস্টবক্স রয়েছে যেখানে আমি কোনও আইটেম চেক করার পরে একটি ইভেন্ট চাই যাতে আমি নতুন রাষ্ট্রের সাথে চেকড আইটেমগুলি ব্যবহার করতে পারি।

যেহেতু চেকড আইটেমগুলি আপডেট হওয়ার আগে আইটেমচেকডকে বরখাস্ত করা হয় এটি বাক্স থেকে কার্যকর হবে না।

চেকড আইটেমগুলি আপডেট করা হলে আমি কী ধরণের পদ্ধতি বা ইভেন্টটি অবহিত হতে ব্যবহার করতে পারি?

উত্তর:


89

আপনি 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());
        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
        ...
}

4
প্রত্যেকের জন্য প্রথমটিতে শর্ত থাকলে আমাদের একটি যোগ করার প্রয়োজন হতে পারে ..if not item = checkedListBox1.Items[e.Index].ToString()
লেনিন রাজ রাজাসেকরন

8
সমস্যাটি হ'ল চেকটি প্রক্রিয়া করার আগে আইটেমচেক ইভেন্টটি বরখাস্ত করা হয়। আপনার সমাধানটি আপনার নিজের তালিকা রাখা, মূলত স্ট্যান্ডার্ড কোডটিকে নকল করে জড়িত। ডানকের প্রথম পরামর্শ (আইটেমচেকের উপর বিলম্বিত কার্যকরকরণ) পিএইচকিউর প্রশ্নের সবচেয়ে পরিষ্কার উত্তর ইমো, কারণ এটির জন্য কোনও অতিরিক্ত হ্যান্ডলিংয়ের প্রয়োজন হয় না।
বেরেন্ড এঞ্জেলব্রেচট

35

এই উপর সংশ্লিষ্ট Stackoverflow পোস্ট ... পাশাপাশি প্রচুর আছে Branimir এর সমাধান, এখানে আরো দুটি সহজ বেশী:

আইটেমচেক (এছাড়াও এখানে ) বিলম্বিত কার্যকর :

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

আমি প্রথম বিকল্পটি পছন্দ করি, কারণ দ্বিতীয়টির ফলে মিথ্যা ধনাত্মক হবে (অর্থাত্ প্রায়শই গুলি চালানো)।


13
দ্বিতীয় পদ্ধতিটি কীবোর্ডের সাহায্যে চেক করা বা চেক করা আইটেমগুলি মিস করবে।

4
আমার ইভেন্টটি আসলে কোনও ইন্টারফেসে ডেকে আসার সাথে সাথে বিগিনভোকের আমার ঠিক কী প্রয়োজন ছিল, এটি কোন ধরণের নিয়ন্ত্রণের সাথে কাজ করছে তার কোনও ধারণা ছিল না। গ্রহণযোগ্য উত্তর কেবলমাত্র সেই ক্ষেত্রে কাজ করে যখন ইভেন্ট হ্যান্ডলারের মধ্যে যুক্তিটি সম্পাদন করা যায় বা ইভেন্ট হ্যান্ডলার থেকে সরাসরি ডেকে আনা কিছু। এটা আমার জন্য ছিল না। এই দুর্দান্ত এখনও সহজ সমাধানের জন্য ধন্যবাদ।
জেসি

থেক্স, বিগিনিউভোকের সাথে প্রথম বিকল্পটি আমার পক্ষে কাজ করে। সম্ভবত একটি নির্বোধ মন্তব্য ভাবেন .. তবে কেন এই বিইউজি 2010 সালে শুরু হওয়া একটি বিষয়ে রিপোর্ট করা হয়েছে 2018 সালে সমাধান হয়নি ??
গুডিজ

4
@ গুডিজ একমত হয়েছেন, যদিও আমার ধারণা মাইক্রোসফ্ট যদি এখন আচরণটি পরিবর্তন করে তবে এটি প্রচুর কোড ভঙ্গ করতে পারে। ডক্স স্পষ্টভাবে রাষ্ট্র The check state is not updated until after the ItemCheck event occurs। একটি ভিন্ন ইভেন্ট বা অ-স্বেচ্ছাসেবী কর্মসূচি চমৎকার আইএমও হবে।
ডানচ

24

আমি এটি চেষ্টা করেছিলাম এবং এটি কাজ করেছে:

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

8
এই! ... সঠিক উত্তর হওয়া উচিত, যা দুর্ভাগ্যক্রমে। এটি একটি হাস্যকর হ্যাক যা কাজ করে কারণ এম at এ থাকা কেউ এই ItemCheckedইভেন্টটি বাস্তবায়ন করতে ভুলে গিয়েছিল এবং কেউই কখনও বলেনি যে এটি বিদ্যমান নেই।
আরএলএইচ

যদিও সংজ্ঞা দ্বারা নয় একটি বাগ আমি এই প্রয়োগ করতে হবে মনে করি, একমত হলে +1 টি ক্লিক করে এই বাগ রিপোর্ট সমর্থন বিবেচনা করুন: connect.microsoft.com/VisualStudio/feedback/details/1759293
SCBuergel.eth

@ সেবাস্তিয়ান - এখানে ঠিক করার জন্য জিজ্ঞাসা করবেন না। এর যে কোনও "ফিক্স" হ'ল উপস্থিত সমাধানগুলি ভেঙে দেবে। যদি দুটি ঘটনার ছিল: ItemChecking, ItemChecked, তাহলে আপনি আধুনিক এক ব্যবহার করতে পারেন। তবে যদি কেবলমাত্র একটি প্রয়োগ করা হয় ( ItemCheck) এটি জিনিসগুলি সঠিকভাবে করছে, অর্থাত নতুন মান এবং প্যারামিটার হিসাবে সরবরাহ করা সূচক দিয়ে মান পরীক্ষা করার আগে ইভেন্টটিকে গুলি করা। "পরিবর্তনের পরে" ইভেন্টটি যে চায়, তারা কেবল উপরেরটি ব্যবহার করতে পারে। মাইক্রোসফ্টকে যদি কিছু পরামর্শ দেয় তবে একটি নতুন ইভেন্টের পরামর্শ দিন ItemChecked, বিদ্যমান ঘটনাটি পরিবর্তন করে না: দেখুন দিমদীপের উত্তর
মিরোক্ল্যাভ

এটির মতো, তবে একটি সামান্য বিকল্প যা আমি সব সময় ব্যবহার করি তা হ'ল কিছু ধরণের "এড়িয়ে যান" পতাকা সেট করা যাতে সেটআইটেমচেকস্টেট একই ইভেন্টটিকে পুনরায় ট্রিগার না করে। হয় সাধারণ গ্লোবাল, বা আমি যা করতে চাই তা হ'ল ট্যাগটি নিশ্চিত করা। উদাহরণস্বরূপ, যদি কোনও MyCheckListBox.Tag! = নাল, এবং তারপরে ইভেন্টটি মুছুন \ যোগের জায়গায় ক্রিয়াটি মোড়ুন করুন, কেবল কোনও কিছুতে (একটি খালি স্ট্রিং) ট্যাগ সেট করুন এবং তারপরে আবার চালু করতে নাল থেকে ফিরে যান।
দা_জোককার

10

থেকে প্রাপ্ত 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);
}

BeginInvokeদ্বিতীয় উত্তরটি থেকে সমাধানটি ব্যবহার করার সময় আপনি এড়াতে পারেন এমন অনেক অতিরিক্ত কোড ।
ƨukasƨ Fronczyk

4

আদর্শ না হলেও, আপনি ItemCheckইভেন্টটিতে যে আর্গুমেন্ট পাঠিয়েছেন তা ব্যবহার করে আপনি চেকড আইটেমগুলি গণনা করতে পারেন । আপনি যদি এমএসডিএন-তে এই উদাহরণটি দেখেন তবে সদ্য পরিবর্তিত আইটেমটি চেক করা হয়েছে বা চেক করা হয়েছে কিনা তা আপনি কাজ করতে পারেন যা আপনাকে আইটেমগুলির সাথে কাজ করার উপযুক্ত অবস্থানে ফেলেছে।

এমনকি আপনি কোনও নতুন ইভেন্ট তৈরি করতে পারেন যা কোনও আইটেম যাচাইয়ের পরে জ্বলে ওঠে, যা আপনি চাইলে ঠিক কী চান তা আপনাকে দিতে পারে।


4
এই নতুন ইভেন্টটি কীভাবে তৈরি করা যেতে পারে সে সম্পর্কে কী কী নির্দিষ্ট ধারণা পেয়েছেন, আইটেমচেক ইভেন্টের পরে যখন চেকড আইটেমগুলি আপডেট করা হয়েছে তখন আমি কীভাবে জানতে পারি?
hultqvist

4

কিছু পরীক্ষার পরে, আমি দেখতে পেতাম যে ইভেন্টটি সিলেক্ট ইন্ডেক্সচেন্জড ইভেন্ট আইটেমচেকের পরে ট্রিগার হয়েছে। সম্পত্তিটি চেক-অন ক্লিক করুন সত্য রাখুন

সেরা কোডিং


আপনি ঠিক বলেছেন, এটি সবচেয়ে সহজ উপায়। তবে এটি এখনও হ্যাকের মতো কিছু, কারণ এটি অনিবন্ধিত এবং অব্যক্ত আচরণ নয়। মাইক্রোসফ্টের যে কোনও নবীন ভাবতে পারে: ওহ ভাল, কেবল চেকস্টেট পরিবর্তিত হলেই কেন আগুন নির্বাচন করা সিলেক্ট ইন্ডেক্সে বদলে যায়। আসুন এটি অপ্টিমাইজ করা যাক। এবং ব্যাং আপনার কোডে চলে গেছে :(
রলফ

অতিরিক্তভাবে, আপনি প্রোগ্রামটি চেক স্টেট পরিবর্তন করার সময় সিলেক্ট ইন্ডেক্সচেন্জেডগুলি ফায়ার হয় না।
রলফ

4
আপনি যখন স্পেস কী দিয়ে চেকের স্থিতি পরিবর্তন করেন তখন এটি আগুন হয় না। এটি ব্যবহার করা ভুল।
এলময়ে

2

এটি কার্যকর, যদিও এটি কত মার্জিত তা নিশ্চিত নয়!

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

1

এটি প্রযোজ্য কিনা তা জানেন না তবে আমি ফলাফলগুলি ফিল্টার করতে একটি চেকলিস্টবক্স ব্যবহার করতে চেয়েছিলাম। ব্যবহারকারী হিসাবে চেক করা এবং চেক করা আইটেম হিসাবে আমি তালিকাটি লুকিয়ে থাকা আইটেমগুলি প্রদর্শন করতে চেয়েছিলাম।

আমার কিছু সমস্যা ছিল যা আমাকে এই পোস্টে নিয়ে গেছে। আমি কীভাবে বিশেষ কিছু ছাড়াই এটি করেছি তা কেবল ভাগ করে নিতে চেয়েছিলাম।

দ্রষ্টব্য: আমার কাছে চেকঅনক্লিক = সত্য তবে এটি সম্ভবত এখনও ছাড়াই কাজ করবে

আমি যে ইভেন্টটি ব্যবহার করি তা হ'ল " SelectedIndexChanged "

আমি যে গণনাটি ব্যবহার করি তা হ'ল " .চেকড আইটেম "

এটি আমাদের প্রত্যাশা করতে পারে এমন ফলাফল দেয়। সরলীকৃত এটি নেমে আসে ....

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

}

ব্যবহারকারী যখন স্পেস কী দিয়ে চেকের স্থিতি পরিবর্তন করে সেলেক্টড ইন্ডেক্সচেনজড আগুন জ্বলে না।
এলমিউ

কোডযুক্ত কোনও আইটেম চেক বা চেক করতে কলিন সেটআইটেম চেক করা হলে সিলেক্টড ইন্ডেক্সচেনজড আগুন হয় না।
বিকেকিসি

1

ধরে নিই যে আপনি আর্গুমেন্টগুলি সংরক্ষণ করতে চান ItemCheckতবে মডেলটি পরিবর্তিত হওয়ার পরে অবহিত হয়ে উঠলে এটি দেখতে এমন হওয়া উচিত:

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

কোথায় CheckedItemsChangedহতে পারে:

private void CheckedItemsChanged(object sender, EventArgs e)
{
    DoYourThing();
}

0

আমি এটি চেষ্টা করেছিলাম এবং এটি কাজ করেছে:

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

তালিকার সূচী দ্বারা নির্ধারণ করুন।


-1

আমি এই সমস্যাটি সমাধান করার জন্য একটি টাইমার ব্যবহার করি। আইটেমচেক ইভেন্টের মাধ্যমে টাইমার সক্ষম করুন। টাইমার টিক ইভেন্টে পদক্ষেপ নিন।

এটি আইটেমটি মাউস ক্লিকের মাধ্যমে বা স্পেস-বার টিপে চেক করা হয়েছে কিনা তা কাজ করে। আমরা এই আইটেমটি স্রেফ চেক করা (বা চেক না করা) সর্বদা নির্বাচিত আইটেমটি গ্রহণ করব।

টাইমার ব্যবধানটি ১ এর মতো কম হতে পারে the টিক ইভেন্টটি উত্থাপিত হওয়ার সাথে সাথে নতুন পরীক্ষিত স্থিতি সেট করা হবে।

এই ভিবি.এনইটি কোডটি ধারণাটি দেখায়। আপনি নিযুক্ত করতে পারেন বিভিন্ন বৈচিত্র আছে। পদক্ষেপ নেওয়ার আগে আপনি বেশ কয়েকটি আইটেমটিতে চেকের স্থিতি পরিবর্তন করতে ব্যবহারকারীকে টাইমারের ব্যবধান বাড়াতে চাইতে পারেন। তারপরে টিক ইভেন্টে তালিকার সমস্ত আইটেমের একটি ক্রমিক পাস করুন বা যথাযথ পদক্ষেপ নিতে তার চেকড আইটেম সংগ্রহটি ব্যবহার করুন।

এজন্য আমরা প্রথমে আইটেমচেক ইভেন্টে টাইমারটি অক্ষম করে রেখেছি। অক্ষম করুন সক্ষম করুন এর পরে বিরতিকালীন সময়কাল পুনরায় শুরু হয়।

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

4
আপনাকে ভাগ করে নেওয়ার জন্য ধন্যবাদ অন্যদিকে, সম্ভবত আপনি অন্যান্য উত্তরগুলি থেকে আরও ভাল সমাধানগুলি শিখতে পারেন। টাইমার ব্যবহার করা তুলনামূলকভাবে জটিল এবং এই ক্ষেত্রে এটি কাজের জন্য ভুল সরঞ্জাম, কারণ আপনি ইতিমধ্যে পরামিতি হিসাবে নতুন মান পাচ্ছেন। সুতরাং আপনি হয় এই উত্তরটি এক-অফ সমাধানের জন্য বা এটি উত্তরোক্ত পদ্ধতিগত সমাধানের জন্য ব্যবহার করতে পারেন । একটি অনলাইন রূপান্তর সরঞ্জাম ব্যবহার করে সেগুলিকে সি # থেকে ভিবিতে রূপান্তর করুন।
মিরোক্লাভ

-1

স্বাভাবিক আচরণে, যখন আমরা একটি আইটেম চেক করি, ইভেন্ট হ্যান্ডলারটি উত্থাপিত হওয়ার আগে আইটেমটির চেকের অবস্থা পরিবর্তন হবে। তবে একটি চেকলিস্টবক্সের একটি আলাদা আচরণ রয়েছে: আইটেমটির চেকের স্থিতি পরিবর্তনের আগে ইভেন্ট হ্যান্ডলারটি উত্থাপিত হয় এবং এটি আমাদের কাজ সংশোধন করতে সমস্যা করে।

আমার মতে, এই সমস্যাটি সমাধান করার জন্য আমাদের ইভেন্ট হ্যান্ডলারটি স্থগিত করা উচিত।

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());}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.