将数据源与 CheckBoxList 一起使用

Posted

技术标签:

【中文标题】将数据源与 CheckBoxList 一起使用【英文标题】:Using datasource with CheckBoxList 【发布时间】:2011-10-10 06:34:35 【问题描述】:

我在我的Windows Forms 应用程序中使用 CheckBoxList 并尝试为其应用数据源。

有一个 DataTable,'dt',列有 idnameischecked,我使用这样的代码:

((ListBox)MyCheckBoxList).DataSource = dt;
((ListBox)MyCheckBoxList).DisplayMember = "name";
((ListBox)MyCheckBoxList).ValueMember = "id";

如何为 MyCheckBoxList 中的所有项目设置 CheckState?

我将此值保存在我的数据表中,并希望将它们与 MyCheckBoxList 链接。

【问题讨论】:

会不会是因为ValueMember = "id"而不是=“你的布尔值”? 你是怎么做到的?如果我在网页上执行此操作,我会收到 Cannot convert type 'System.Web.UI.WebControls.CheckBoxList' to 'System.Web.UI.WebControls.ListBox' 【参考方案1】:

我不确定是否可以通过 ValueMember 属性设置检查。

你可以试试看:

foreach (DataRow item in dt.Rows)

     MyCheckedListBox.Items.Add(item["Name"].ToString(), Convert.ToBoolean(item["Checked"]));

【讨论】:

这是一种方式,但在这种情况下,我失去了调用数据源的优势【参考方案2】:

我分两步解决了我的问题。首先,我应用了数据源,然后循环设置每个项目的 Checked 属性,如下代码所示:

((ListBox)MyCheckBoxList).DataSource = dt;
((ListBox)MyCheckBoxList).DisplayMember = "name";
                    ...

for (int i = 0; i < folloving.Items.Count; i++ )

    DataRowView row = (DataRowView)MyCheckBoxList.Items[i];
    bool isChecked = Convert.ToBoolean(row["checked"]);
    MyCheckBoxList.SetItemChecked(i, isChecked);

【讨论】:

真正可绑定的 CheckedListBox 不需要循环。我们应该能够以某种方式将 ListBox 项的 IsChecked 属性绑定到底层对象的属性。【参考方案3】:

作为另一种解决方法,我实现了 CheckedListBox.Format 事件以使用数据自动更新显示的 CheckedState;并实现 CheckedListBox.ItemCheck 事件以自动更新带有 CheckedState 的数据。

private DataTable myDataTable = null;
private BindingSource myBindingSource = new BindingSource();

// Column Name Constants
private const string C_ITEM_INDEX = "Item_Index";      // CheckedListBox Item's Index
private const string C_ITEM_TEXT = "Item_Text";        // Item's Text
private const string C_ITEM_CHECKED = "Item_Checked";  // Item's Checked State
private const string C_DATA_KEY = "Data_Key";          // Arbitrary Key Value for Relating Item to Other Data

private void Startup()

  // Create DataTable 
  // This DataTable has 4 Columns described by the constants above
  myDataTable = new DataTable();
  myDataTable.Columns.Add(new DataColumn(C_ITEM_INDEX, typeof(Int32)));
  myDataTable.Columns[C_ITEM_INDEX].DefaultValue = 0;
  myDataTable.Columns.Add(new DataColumn(C_ITEM_TEXT, typeof(string)));
  myDataTable.Columns[C_ITEM_TEXT].DefaultValue = "";

  // I personally like Integer 1=true, 0=false values.  typeof(bool) will also work.
  myDataTable.Columns.Add(new DataColumn(C_ITEM_CHECKED, typeof(Int32)));
  myDataTable.Columns[C_ITEM_CHECKED].DefaultValue = 0;

  // Other columns can be included in the DataTable
  myDataTable.Columns.Add(new DataColumn(C_DATA_KEY, typeof(Int32)));
  myDataTable.Columns[C_DATA_KEY].DefaultValue = 0;     
  myDataTable.AcceptChanges();

  // Bind the DataTable's DefaultView to the CheckedListBox
  myBindingSource.DataSource = myDataTable.DefaultView;
  this.myCheckedListBox.DataSource = myBindingSource;

  // Set the DisplayMember to the DataColumn you want displayed as the CheckedListBox Items's Text
  this.myCheckedListBox.DisplayMember = C_ITEM_TEXT;

  // Set the ValueMember to the Data.  Note:  The ValueMember is not displayed and is Not the CheckBox value.
  this.myCheckedListBox.ValueMember = C_DATA_KEY;

  // Hookup Event Handler for the CheckedListBox.Format Event.  
  /// * The Format event enables us to just in time update the CheckBoxes with the values in the DataTable
  this.myCheckedListBox.Format += myCheckedListBox_Format;

  // Hookup Event Handler for the CheckedListBox.ItemCheck Event.
  /// * The ItemCheck event enables us to just in time update the DataTable with the values from the Item CheckBoxes
  this.myCheckedListBox.ItemCheck += myCheckedListBox_ItemCheck;



void myCheckedListBox_Format(object sender, ListControlConvertEventArgs e)

  /// * The Format event enables us to just in time update the CheckBoxes with the values in the DataTable
  // Retrieve the Index of the Item in the CheckedListBox by finding the DataRowView in the BindingSource
  //   Note:  Use a column with unique values for the BindingSource.Find() function
  int listindex = myBindingSource.Find(C_ITEM_INDEX, ((DataRowView)e.ListItem)[C_ITEM_INDEX]);

  // The argument, e.ListItem, is the current DataRowView in the DataTable's DefaultView
  // Check to see if the checkbox value is different from the data
  if (((CheckedListBox)sender).GetItemChecked(listindex) !=  Convert.ToBoolean(((DataRowView)e.ListItem)[C_ITEM_CHECKED]))
  
    // Set the CheckList Item's CheckState to match the data
    ((CheckedListBox)sender).SetItemChecked(listindex, Convert.ToBoolean(((DataRowView)e.ListItem)[C_ITEM_CHECKED]));
  



void myCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e)

  /// * The ItemCheck event enables us to just in time update the DataTable with the values from the Item CheckBoxes
  // Update the data with the new CheckState value.  
  if (e.NewValue == CheckState.Checked)
  
    myDataTable.DefaultView[e.Index][C_ITEM_CHECKED] = 1;
  
  else
  
    myDataTable.DefaultView[e.Index][C_ITEM_CHECKED] = 0;
  
  // Update other data values too if you need to.

【讨论】:

这里的一切都很好,除了使用BindingSource,因为它不会延续到System.Web。希望那些在System.Windows.Forms 工作的人能够使他们的代码足够通用,以便在这两个领域中使用。但我喜欢这个概念,而且肯定有很多想法——对于视觉形式来说非常实用。不是这样,对于 Web 应用程序页面表单。如果你能适应两者,我很乐意看到结果。

以上是关于将数据源与 CheckBoxList 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

禁用 CheckboxList 中的特定项目

MVC CheckBoxList 模型绑定与非布尔值

如何将 onchange 事件附加到 CheckBoxList?缺少输入属性?

LINQ to CheckBoxList 数据项

我需要在GridView中使用Checkboxlist来绑定来自其他表的数据

checkboxlist 如何配置数据源?