簡體   English   中英

如何在WinForms中管理與List <>綁定的ListBox / CheckedListBox?

[英]How to manage ListBox/CheckedListBox bound with List<> in WinForms?

如何將ListBoxCheckedListBox與程序員定義的對象的List<>綁定? 綁定后如何編輯數據? 我可以通過哪個對象修改數據? 數據更改時如何使列表框視圖更新? 用戶單擊CheckedListBox時,如何檢索項目復選框的檢查狀態?

我想分享我所擁有的一些知識,因為我在這個主題上看到了很多線程,但是沒有一個線程清楚地顯示如何處理數據綁定。 不要誤解我的嘗試,我只想展示一種輕松的方法。

隨時發表評論。 希望對您有所幫助!

在下文中,“ ListBox ”不同於“ listbox”,后者是用於ListBoxCheckedListBox的通用術語。


首先,綁定是在testForm_Load事件處理程序中完成的。 必須告訴要綁定的對象以及要在列表框中顯示的屬性/字段。

((ListBox)m_checkedListBox).DataSource = m_underList;
((ListBox)m_checkedListBox).DisplayMember = "PropToDisplay";

據我了解的過程,綁定的列表框的行為類似於只讀的單向(數據源=>列表框)鏡像視圖。 我們只能通過處理基礎數據對象或控件的事件機制(忘記Items &co。)的方式來影響列表框並檢索其數據。

對於CheckListBox ,我們可以通過將ItemCheckEventHandler方法添加到ItemCheck事件中來檢索已檢查的項目,然后將其存儲到屬性/字段的程序員定義的對象中。

m_checkedListBox.ItemCheck += new ItemCheckEventHandler(this.ItemCheck);

但是我們無法定義要在CheckListBox顯示為選中狀態的數據源(基礎列表)中內部選中項的狀態。 CheckListBox似乎並非設計為具有這種行為。

然后,可以通過基礎列表Userclass添加或刪除Userclass對象,或調用所需的任何方法。 只是不在乎列表框。

m_underList.Add(new UserClass("Another example", 0, true));

最后,刷新列表框。 我看到許多文章都在談論將DataSource設置為null,然后將其重新分配回其先前的對象。 我正在尋找一種更好的方法(更好或更漂亮?)。 下面的方法非常簡單。

void refreshView(ListBox lb, object dataSource);

參考文獻:

有關從列表框中檢索用戶選擇的補充信息,請訪問MSDN ListControl類示例。

以下是綁定,填充數據和清除CheckedListBox的簡單示例的完整代碼。 為簡單起見,請注意,我是從對列表框或數據列表進行排序的原則開始的。


UserClass.cs:用於存儲顯示/檢查狀態/隱藏數據的類

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TestForm
{
    class UserClass
    {
        private int m_underProp;

        // ctors
        public UserClass(string prop2Disp, int anotherObj, bool isChecked = false)
        {
            PropToDisplay = prop2Disp;
            IsChecked = isChecked;
            AnotherProp = anotherObj;
        }

        public UserClass()
        {
            PropToDisplay = string.Empty;
            IsChecked = false;
            AnotherProp = 0;
        }

        //  Property to be displayed in the listbox
        public string PropToDisplay
        {
            get;
            set;
        }

        //  For CheckedListBox only!
        //  Property used to store the check state of a listbox
        //  item when a user select it by clicking on his checkbox
        public bool IsChecked
        {
            get;
            set;
        }

        //  Anything you want
        public int AnotherProp
        {
            get
            {
                return m_underProp;
            }

            set
            {
                m_underProp = value;
                //  todo, processing...
            }
        }

        //  For monitoring
        public string ShowVarState()
        {
            StringBuilder str = new StringBuilder();

            str.AppendFormat("- PropToDisplay: {0}", PropToDisplay);
            str.AppendLine();
            str.AppendFormat("- IsChecked: {0}", IsChecked);
            str.AppendLine();
            str.AppendFormat("- AnotherProp: {0}", AnotherProp.ToString());

            return str.ToString();
        }
    }
}

TestForm.Designer.cs:表單的設計

namespace TestForm
{
    partial class testForm
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.m_checkedListBox = new System.Windows.Forms.CheckedListBox();
            this.m_toggle = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // m_checkedListBox
            // 
            this.m_checkedListBox.CheckOnClick = true;
            this.m_checkedListBox.FormattingEnabled = true;
            this.m_checkedListBox.Location = new System.Drawing.Point(13, 13);
            this.m_checkedListBox.Name = "m_checkedListBox";
            this.m_checkedListBox.Size = new System.Drawing.Size(171, 109);
            this.m_checkedListBox.TabIndex = 0;
            // 
            // m_toggle
            // 
            this.m_toggle.Location = new System.Drawing.Point(190, 53);
            this.m_toggle.Name = "m_toggle";
            this.m_toggle.Size = new System.Drawing.Size(75, 23);
            this.m_toggle.TabIndex = 1;
            this.m_toggle.Text = "Fill";
            this.m_toggle.UseVisualStyleBackColor = true;
            this.m_toggle.Click += new System.EventHandler(this.m_toggle_Click);
            // 
            // testForm
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(275, 135);
            this.Controls.Add(this.m_toggle);
            this.Controls.Add(this.m_checkedListBox);
            this.Name = "testForm";
            this.Text = "Form";
            this.Load += new System.EventHandler(this.testForm_Load);
            this.ResumeLayout(false);

        }

        #endregion

        private System.Windows.Forms.CheckedListBox m_checkedListBox;
        private System.Windows.Forms.Button m_toggle;
    }
}

TestForm.cs:表單的行為

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

namespace TestForm
{
    public partial class testForm : Form
    {
        //  a List which will contain our external data. Named as the underlying list
        private List<UserClass> m_underList;

        public testForm()
        {
            InitializeComponent();

            m_underList = new List<UserClass> (3);
        }

        private void testForm_Load(object sender, EventArgs e)
        {
            //  Bind the CheckedListBox with the List
            //  The DataSource property is hidden so cast the object back to ListBox
            ((ListBox)m_checkedListBox).DataSource = m_underList;

            //  Tell which property/field to display in the CheckedListBox
            //  The DisplayMember property is hidden so cast the object back to ListBox
            ((ListBox)m_checkedListBox).DisplayMember = "PropToDisplay";

            /*
             * The CheckedListBox is now in "read-only" mode, that means you can't add/remove/edit
             * items from the listbox itself or edit the check states. You can't access
             * the underlying list through the listbox. Considers it as a unidirectionnal mirror
             * of the underlying list. The internal check state is disabled too, however
             * the ItemCheck event is still raised...
             */

            //  Manually set the ItemCheck event to set user defined objects
            m_checkedListBox.ItemCheck += new ItemCheckEventHandler(this.ItemCheck);
        }

        private void ItemCheck(object sender, ItemCheckEventArgs evnt)
        {
            if (sender == m_checkedListBox)
            {
                if (!m_checkedListBox.Sorted)
                {
                    //  Set internal object's flag to remember the checkbox state
                    m_underList[evnt.Index].IsChecked = (evnt.NewValue != CheckState.Unchecked);

                    //  Monitoring
                    Debug.WriteLine(m_underList[evnt.Index].ShowVarState());
                }
                else
                {
                    //  If sorted... DIY
                }
            }
        }

        private void m_toggle_Click(object sender, EventArgs e)
        {
            if (sender == m_toggle)
            {
                if (m_toggle.Text == "Fill")
                {
                    //  Fill the checkedListBox with some data
                    //  Populate the list with external data.
                    m_underList.Add(new UserClass("See? It works!", 42));
                    m_underList.Add(new UserClass("Another example", 0, true));
                    m_underList.Add(new UserClass("...", -7));
                    m_toggle.Text = "Clear";
                }
                else
                {
                    //  Empty the checkedListBox
                    m_underList.Clear();
                    m_toggle.Text = "Fill";
                }

                //  Refresh view
                //  Remember CheckedListBox inherit from ListBox
                refreshView(m_checkedListBox, m_underList);
            }
        }

        //  Magic piece of code which refresh the listbox view
        void refreshView(ListBox lb, object dataSource)
        {
            CurrencyManager cm = (CurrencyManager)lb.BindingContext[dataSource];
            cm.Refresh();
        }
    }
}

這是表格的視圖。 第一個圖像是加載時的表單,第二個圖像是單擊“填充”按鈕時的表單。 可能會注意到,盡管將IsChecked屬性添加到數據源時將其設置為true,但不會選中列表框中的第二項。

表格已加載單擊填充按鈕

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM