ListBox.DataSource 集合与 ListBox.Items 之间的区别
本文关键字:ListBox 区别 之间 DataSource 集合 Items | 更新日期: 2023-09-27 18:02:04
我正在动态创建一个Winforms多选列表框并将其添加到流面板控件中。 我从我创建的对象绑定数据源,并验证数据源实际上确实有大约 14 个元素。 当我执行listBox.SetSelected(0, true)
时,我抛出了一个System.ArgumentOutOfRangeException
错误。
我已经确定问题是,虽然数据源有 14 个元素,但 Item 集合没有 (0(,因此会引发异常。 我的问题是为什么这两者彼此不同,为什么我不简单地将数据源中的 foreach 项添加到项集合中?
以下是我到目前为止的代码:
case InsertableItemParameter.ParameterType.ListBox:
//note: two-way bindings are not possible with multiple-select listboxes
Label lblListBox = new Label();
lblListBox.Text = param.DisplayText;
ListBox listBox = new ListBox();
listBox.DataSource = param.Values;
listBox.DisplayMember = "Value";
listBox.SelectionMode = SelectionMode.MultiExtended;
listBox.Size = new System.Drawing.Size(flowPanel.Size.Width - lblListBox.Size.Width - 10, 100);
listBox.SetSelected(0, true); //will throw argument out of range exception here!
listBox.SetSelected(1, true);
flowPanel.Controls.Add(lblListBox);
flowPanel.Controls.Add(listBox);
flowPanel.SetFlowBreak(listBox, true);
break;
以下是我尝试并工作的替代解决方案,但为什么我要使用数据源与项目集合?
case InsertableItemParameter.ParameterType.ListBox:
//note: two-way bindings are not possible with multiple-select listboxes
Label lblListBox = new Label();
lblListBox.Text = param.DisplayText;
ListBox listBox = new ListBox();
//listBox.DataSource = param.Values;
listBox.DisplayMember = "Value";
listBox.SelectionMode = SelectionMode.MultiExtended;
listBox.Size = new System.Drawing.Size(flowPanel.Size.Width - lblListBox.Size.Width - 10, 100);
listBox.BeginUpdate();
foreach (String paramater in param.Values)
{
listBox.Items.Add(paramater);
}
listBox.EndUpdate();
listBox.SetSelected(0, true);
listBox.SetSelected(1, true);
flowPanel.Controls.Add(lblListBox);
flowPanel.Controls.Add(listBox);
flowPanel.SetFlowBreak(listBox, true);
break;
答:感谢您的所有回复。 这里的问题是可见性和获胜形式渲染。 虽然除了少数人之外,数据源和 Items 集合之间的区别并没有真正解决,但我问题的真正来源是通过在表单完成绘制后调用 SetSelected()
方法来解决的。 这在我的应用程序设计中导致了很多问题,我必须解决这些问题,但这就是问题所在。 请参阅我标记为答案的回复。
您的问题可能出在其他地方,因为此代码工作正常:
string[] ds = {"123","321"};
listBox1.DataSource = ds;
listBox1.SetSelected(1, true);
MessageBox.Show(listBox1.Items.Count.ToString()); //returns 2
在一个全新的 C# 项目中进行了测试,并在窗体上放了一个listBox1
,上面的代码位于 Form_Load
中。
编辑:我没有意识到在运行时创建ListBox
可能会有所作为,特别是因为何时设置所选项目很重要。此代码有效:
string[] ds = { "123", "321" };
ListBox lst = new ListBox();
lst.DataSource = ds;
lst.Size = new Size(100,100);
this.Controls.Add(lst);
//make sure to call SetSelected after adding the ListBox to the parent
lst.SetSelected(1, true);
感谢@Brad指出这一点。所以回到原来的问题,替换这个:
listBox.SetSelected(0, true);
listBox.SetSelected(1, true);
flowPanel.Controls.Add(lblListBox);
flowPanel.Controls.Add(listBox);
有了这个:
flowPanel.Controls.Add(lblListBox);
flowPanel.Controls.Add(listBox);
listBox.SetSelected(0, true);
listBox.SetSelected(1, true);
它应该有效。
对于如何在ListBox
中提供数据,您有两种选择。您可以设置DataSource
,也可以通过 listBox.Items.Add(paramater)
手动添加项目。你不能同时做这两件事,因为它们会互相踩到,因此你的错误
...cannot add items to the Item collection when DataSource is set.
来自 MSDN 的项目
此属性使您能够获取对当前存储在 ListBox 中的项列表的引用。使用此引用,可以添加项、删除项以及获取集合中项的计数。有关可以使用项集合执行的任务的详细信息,请参阅 ListBox.ObjectCollection 类参考主题。
来自 MSDN 的数据源
我实现 IList 或 IListSource 接口(如数据集或数组(的对象。默认值为空
不是这方面的专家,但从我读到的内容来看,Items 允许您添加/修改列表中的内容,而数据源检索和设置内容。
仅当控件可见时,才会从数据源填充 Items 集合。 由于控件是动态创建的,因此它不会添加到父控件中,因此不可见。因此,您首先需要有一个在屏幕上可见的控件。在代码中,设置数据源,然后在Control
在FlowChart
上可见之前设置所选项,因为它不会添加到Parent
控件中。您应该更改语句的顺序。应将listBox
添加到FlowPanel
,该将从可对其执行SetSelected()
方法的DataSource
填充 Items 集合。试试这个,并注意初始代码执行顺序的更改:
ListBox listBox = new ListBox();
listBox.DataSource = param.Values;
listBox.DisplayMember = "Value";
listBox.SelectionMode = SelectionMode.MultiExtended;
listBox.Size = new System.Drawing.Size(flowPanel.Size.Width - lblListBox.Size.Width - 10, 100);
flowPanel.Controls.Add(lblListBox);
flowPanel.Controls.Add(listBox); //notice that you first add the listBox to the flowChart
listBox.SetSelected(0, true); //and then you have items in the Items collection which you can select
listBox.SetSelected(1, true);
我不确定为什么有两个不同的集合。Items
属性似乎更简单。
我找到了异常的原因:显然,您必须按特定顺序执行操作,如下所示:
//init the listbox
var listBox1 = new ListBox();
listBox1.Location = new System.Drawing.Point(122, 61);
listBox1.Size = new System.Drawing.Size(205, 147);
listBox1.SelectionMode = SelectionMode.MultiExtended;
Controls.Add(listBox1); //<-- point of interest
//then set the DataSource
listBox1.DataSource = lst;
listBox1.DisplayMember = "Name";
listBox1.ValueMember = "Age";
//then set the selected values
listBox1.SetSelected(0, true);
listBox1.SetSelected(1, true);
我的Test
类看起来像这样:
public class Test
{
private static Random r = new Random();
public Test (string name)
{
Name = name;
Age = r.Next(16, 45);
}
public string Name { get; set; }
public int Age{ get; set; }
}
lst
是这样声明的:
var lst = new List<Test>()
{
new Test("jens"),
new Test("Tom"),
new Test("John"),
new Test("Don"),
new Test("Jenny"),
};