winform控件之checkedListBox

checkedlistbox控件也是我們常用的控件,我們仿照上一篇checkbox的例程,這回用checkedlistbox來實現

本來以爲是很容易實現的,結果發現想讓功能做的完善以下,中間有許多坑需要填,下面我們一起來看一下吧

 

1.界面佈局

界面佈局如下

具體的佈局代碼就不貼了,總之就是在在上一篇的基礎上使用checkedlistbox來實現全選,並新增了刪除和添加的功能

 

2.用法示例

需要注意的有這麼幾點

1.事件順序

當我們點擊某一項的時候,checkedlistbox調用事件的順序是這樣的

ItemCheck -> SelectedValueChanged -> SelectedIndexChanged

 

2.點擊空白

如上圖所示,當我們已經選中一項的時候,再點擊空白處,這一項的狀態依然會改變,避免的方法可以參考這篇博文

CheckedListBox 當中項的狀態改變

 

3.雙擊事件DoubleClick

如果我們某一項點擊的比較快,會觸發DoubleClick事件,這時候全選框狀態和是否全選的狀態會不一致,我們需要在這個事件裏面重新進行檢測

 

4.全選框狀態

如上一篇CheckBox所述,全選按鈕只能在Click事件裏面進行處理,否則會出現事件嵌套

當我們點擊全選按鈕的時候,checkedlistbox會檢測到我們點擊的是空白,但是這時候我們檢測全選框狀態的時候,其狀態並未改變,導致我們無法區分是點擊了空白還是點擊了全選框,所以只能單獨設置個變量來判斷是否點擊了全選按鈕

 

實現的時候遇到的問題基本上就是上面幾條,大家可以自己實現下,因該會遇到不少問題,下面來看看具體的實現代碼

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class FormMain : Form
    {
        public FormMain(ArrayList arrip_list)
        {
            InitializeComponent();
        }

        private void buttonShow_Click(object sender, EventArgs e)
        {
            string sb = "您的興趣愛好是 ";

            for (int i = 0; i < checkedListBox1.Items.Count; i++)
            {
                if (checkedListBox1.GetItemChecked(i) == true)
                {
                    sb = sb + checkedListBox1.GetItemText(checkedListBox1.Items[i]) + ",";
                }
            }
            label2.Text = "" + sb;
        }

        private void checkedListBox1_SelectedValueChanged(object sender, EventArgs e)
        {
            CheckedListBox clb = sender as CheckedListBox;

            ////點擊空白處會觸發該事件,如果之前沒有選中任何項,則index爲-1
            if (clb.SelectedIndex != -1)
            {
                int SelectCount = 0;
                if (bIsSelectAll == false && clb.GetItemChecked(clb.SelectedIndex) == true)
                {
                    for (int i = 0; i < clb.Items.Count; i++)
                    {
                        if (clb.GetItemChecked(i) == true)
                        {
                            SelectCount++;
                        }
                    }

                    if (SelectCount == clb.Items.Count)
                    {
                        checkBoxSelectAll.CheckState = CheckState.Checked;
                        //Console.WriteLine("Checked");
                    }
                }
                else if (bIsSelectAll == false && clb.GetItemChecked(clb.SelectedIndex) == false)
                {
                    checkBoxSelectAll.CheckState = CheckState.Unchecked;
                    //Console.WriteLine("UnChecked");
                }

            }
            //Console.WriteLine("Value Changed");

            //這裏爲了避免點擊空白處依然會更改之前的選中項,每次都將index清空爲-1
            //clb.SelectedIndex = -1;
        }

        //這裏單獨個變量用於記錄全選按鈕是否按下
        //如之前CheckBox所述,全選按鈕只能在Click事件裏面進行處理,否則會出現事件嵌套
        //但是在Click事件裏面的問題就是,在其他地方獲取全選按鈕的狀態時候,狀態並未改變
        //導致在Checklistbox判斷是點擊空白還是點擊全選的時候無法進行判斷
        private bool bIsSelectAll = false;
        private void checkBoxSelectAll_Click(object sender, EventArgs e)
        {
            CheckBox cb = sender as CheckBox;

            
            if (cb.CheckState == CheckState.Checked)
            //if (checkBoxSelectAll.CheckState == CheckState.Checked)
            {
                bIsSelectAll = true;
                for (int i = 0; i < checkedListBox1.Items.Count; i++)
                {
                    //這裏需要手動設置以下索引,否則在直接設置某項狀態的時候
                    //SelectedItem是null
                    checkedListBox1.SelectedIndex = i;
                    checkedListBox1.SetItemChecked(i, true);
                }
                
            }
            else if (cb.CheckState == CheckState.Unchecked)
            {
                bIsSelectAll = true;
                for (int i = 0; i < checkedListBox1.Items.Count; i++)
                {
                    //這裏需要手動設置以下索引,否則在直接設置某項狀態的時候
                    //SelectedItem是null
                    checkedListBox1.SelectedIndex = i;
                    checkedListBox1.SetItemChecked(i, false);
                }
            }
            bIsSelectAll = false;
            //這裏清空下索引,否則每次點擊後最後一項都會被選中
            //清空索引後,讓所有項都取消反藍
            checkedListBox1.SelectedIndex = -1;
        }

        private ArrayList listM_moteeui = new ArrayList();

        private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
        {
            CheckedListBox clb = sender as CheckedListBox;

            //檢測是否點擊到空白的方法,可以參考下面這篇博文
            //https://blog.csdn.net/apgk1/article/details/50787435
            
            //判斷如果點擊的座標是空白的地方則不更改值
            if (bIsSelectAll == false && clb.IndexFromPoint(
                clb.PointToClient(Cursor.Position).X,
                clb.PointToClient(Cursor.Position).Y) == -1)
            {
                e.NewValue = e.CurrentValue;
            }
            else    //這邊開始判斷集合當中是不是已經有ID,如果沒有就加入
            {
                string temp = clb.SelectedItem.ToString();
                if (!listM_moteeui.Contains(temp))
                {
                    listM_moteeui.Add(temp);
                }
                else
                {
                    listM_moteeui.Remove(temp);
                }
            }
        }

        private void checkedListBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            CheckedListBox clb = sender as CheckedListBox;
        }

        private void checkedListBox1_DoubleClick(object sender, EventArgs e)
        {
            CheckedListBox clb = sender as CheckedListBox;


            //這裏需要在DoubleClick中重新判斷以下,因爲如果點擊的太快
            //DoubleClick事件觸發,全選按鈕和checklistbox的狀態會不一致
            if (clb.SelectedIndex != -1)
            {
                int SelectCount = 0;
                if (clb.GetItemChecked(clb.SelectedIndex) == true)
                {
                    for (int i = 0; i < clb.Items.Count; i++)
                    {
                        if (clb.GetItemChecked(i) == true)
                        {
                            SelectCount++;
                        }
                    }

                    if (SelectCount == clb.Items.Count)
                    {
                        checkBoxSelectAll.CheckState = CheckState.Checked;
                    }
                }
                else if (clb.GetItemChecked(clb.SelectedIndex) == false)
                {
                    checkBoxSelectAll.CheckState = CheckState.Unchecked;
                }
            }
        }

        private void buttonDelete_Click(object sender, EventArgs e)
        {
            if (checkedListBox1.SelectedIndex != -1)
            {
                //刪除選中項
                checkedListBox1.Items.Remove(checkedListBox1.GetItemText(checkedListBox1.Items[checkedListBox1.SelectedIndex]));

                //重新檢查是否需要選中全選按鈕
                int SelectCount = 0;
                for (int i = 0; i < checkedListBox1.Items.Count; i++)
                {
                    if (checkedListBox1.GetItemChecked(i) == true)
                    {
                        SelectCount++;
                    }
                }

                if (SelectCount == checkedListBox1.Items.Count)
                {
                    checkBoxSelectAll.CheckState = CheckState.Checked;
                    //Console.WriteLine("Checked");
                }
                else
                {
                    checkBoxSelectAll.CheckState = CheckState.Unchecked;
                }
            }
        }

        private void buttonAdd_Click(object sender, EventArgs e)
        {
            //如果內容不爲空
            if (textBoxAdd.Text != "")
            {
                //添加新內容到checklistbox
                checkedListBox1.Items.Add(textBoxAdd.Text);

                //清空內容
                textBoxAdd.Text = "";
            }
        }
    }
}

 

 

不足之處希望能多批評指正,謝謝

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章