[英]How to manage ListBox/CheckedListBox bound with List<> in WinForms?
如何將ListBox
或CheckedListBox
與程序員定義的對象的List<>
綁定? 綁定后如何編輯數據? 我可以通過哪個對象修改數據? 數據更改時如何使列表框視圖更新? 用戶單擊CheckedListBox
時,如何檢索項目復選框的檢查狀態?
我想分享我所擁有的一些知識,因為我在這個主題上看到了很多線程,但是沒有一個線程清楚地顯示如何處理數據綁定。 不要誤解我的嘗試,我只想展示一種輕松的方法。
隨時發表評論。 希望對您有所幫助!
在下文中,“ ListBox
”不同於“ listbox”,后者是用於ListBox
和CheckedListBox
的通用術語。
首先,綁定是在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.