绑定到 IList,但得到 "Complex DataBinding accepts as a data source either an IList or an IListSource"
Binding to IList, but getting "Complex DataBinding accepts as a data source either an IList or an IListSource"
如果您 运行 以下代码没有调试(或 "Enable Just My Code" 处于活动状态),它似乎可以工作。但是如果你用调试器启动它并关闭 "Enable Just My Code",你将得到这个异常(然后被库代码吞没):
System.ArgumentException occurred
HResult=-2147024809
Message=Complex DataBinding accepts as a data source either an IList or an IListSource.
Source=System.Windows.Forms
StackTrace:
at System.Windows.Forms.ListControl.set_DataSource(Object value)
InnerException:
这是我的代码的最小版本:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm(new MainModel()));
}
}
public class MainModel {
public IList Options { get; } = new List<string> { "Foo", "Bar" };
}
class MainForm : Form {
private System.ComponentModel.IContainer components;
private ComboBox comboBox;
private BindingSource bindingSource;
private ErrorProvider errorProvider;
public MainForm(MainModel mainModel) {
InitializeComponent();
bindingSource.DataSource = mainModel;
}
private void InitializeComponent() {
components = new System.ComponentModel.Container();
bindingSource = new BindingSource(components);
errorProvider = new ErrorProvider(components);
((System.ComponentModel.ISupportInitialize) bindingSource).BeginInit();
((System.ComponentModel.ISupportInitialize) errorProvider).BeginInit();
SuspendLayout();
bindingSource.DataSource = typeof(MainModel);
comboBox = new ComboBox();
comboBox.DataBindings.Add(new Binding("DataSource", bindingSource, "Options", true));
comboBox.DropDownStyle = ComboBoxStyle.DropDownList;
Controls.Add(comboBox);
errorProvider.ContainerControl = this;
errorProvider.DataSource = bindingSource;
((System.ComponentModel.ISupportInitialize) bindingSource).EndInit();
((System.ComponentModel.ISupportInitialize) errorProvider).EndInit();
ResumeLayout(false);
}
}
问题似乎与数据绑定有关。如果我注释掉 comboBox.DataBindings.Add(new Binding("DataSource", bindingSource, "Options", true));
行,则不会发生异常。
我在网上找到了很多关于此异常的引用,但似乎在所有这些情况下,问题都在于数据源不是 IList
(如异常消息所述)。然而,在这种情况下,Options
是 和 IList
。所以我无法解释这个例外。
我注意到如果我删除 ErrorProvider
,异常 不会 发生。但我不明白为什么会这样;我的实际程序中需要错误提供程序。
我在 Visual Studio 2015 年工作,目标是 .NET 4.6。
看起来您正在声明 DataBinding,而您的 bindingSource 仍在 BeginInit - EndInit 块中。尝试将该行移动到 之后 EndInit 行,或者改为在 OnLoad 覆盖中:
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
comboBox.DataBindings.Add(new Binding("DataSource", bindingSource, "Options", true));
}
为DataSource
属性 添加Binding
是错误的想法。
要设置 DataSource
,您应该为 DataSource
分配一些内容,而不是添加 Binding
。例如,添加 Binding
对 SelectedValue
有意义,但对 DataSource
.
无效
您的代码应该是:
bindingSource.DataSource = typeof(MainModel);
bindingSource.DataMember = "Options";
comboBox = new ComboBox();
comboBox.DataSource = bindingSource;
comboBox.DropDownStyle = ComboBoxStyle.DropDownList;
Controls.Add(comboBox);
那么您将不会收到任何错误。
注意:如果出于任何原因您只是想知道如何避免示例中的错误,只需设置 this.Visible = true
或准确调用 this.Show()
在 InitializeComponent
之后强制创建控制句柄并使数据绑定开始工作。我的代码不需要此修复程序。
为什么数据绑定到 DataSource
属性 不是一个好主意?
如果您要将 DataSource
属性 绑定到 MainModel
的 Optins
属性,则意味着您要更新 Options
属性 使用组合框!这也意味着 MainModel
class 应该实现 INotifyPropertyChanged
以通知组合框有关 Options
属性 的变化!(请记住选项 属性 是 IList
) 这是完全错误的想法!
那么如何通知 ComboBox
数据源的变化?
如果要通知 ComboBox
数据源的更改,数据源列表应实现 IBindingList
。 BindingList<T>
是实现的一个例子。所以设置 comboBox.DataSource = someDataSource;
而不是数据绑定到 DataSource
.
就足够了
如果您 运行 以下代码没有调试(或 "Enable Just My Code" 处于活动状态),它似乎可以工作。但是如果你用调试器启动它并关闭 "Enable Just My Code",你将得到这个异常(然后被库代码吞没):
System.ArgumentException occurred
HResult=-2147024809
Message=Complex DataBinding accepts as a data source either an IList or an IListSource.
Source=System.Windows.Forms
StackTrace:
at System.Windows.Forms.ListControl.set_DataSource(Object value)
InnerException:
这是我的代码的最小版本:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm(new MainModel()));
}
}
public class MainModel {
public IList Options { get; } = new List<string> { "Foo", "Bar" };
}
class MainForm : Form {
private System.ComponentModel.IContainer components;
private ComboBox comboBox;
private BindingSource bindingSource;
private ErrorProvider errorProvider;
public MainForm(MainModel mainModel) {
InitializeComponent();
bindingSource.DataSource = mainModel;
}
private void InitializeComponent() {
components = new System.ComponentModel.Container();
bindingSource = new BindingSource(components);
errorProvider = new ErrorProvider(components);
((System.ComponentModel.ISupportInitialize) bindingSource).BeginInit();
((System.ComponentModel.ISupportInitialize) errorProvider).BeginInit();
SuspendLayout();
bindingSource.DataSource = typeof(MainModel);
comboBox = new ComboBox();
comboBox.DataBindings.Add(new Binding("DataSource", bindingSource, "Options", true));
comboBox.DropDownStyle = ComboBoxStyle.DropDownList;
Controls.Add(comboBox);
errorProvider.ContainerControl = this;
errorProvider.DataSource = bindingSource;
((System.ComponentModel.ISupportInitialize) bindingSource).EndInit();
((System.ComponentModel.ISupportInitialize) errorProvider).EndInit();
ResumeLayout(false);
}
}
问题似乎与数据绑定有关。如果我注释掉 comboBox.DataBindings.Add(new Binding("DataSource", bindingSource, "Options", true));
行,则不会发生异常。
我在网上找到了很多关于此异常的引用,但似乎在所有这些情况下,问题都在于数据源不是 IList
(如异常消息所述)。然而,在这种情况下,Options
是 和 IList
。所以我无法解释这个例外。
我注意到如果我删除 ErrorProvider
,异常 不会 发生。但我不明白为什么会这样;我的实际程序中需要错误提供程序。
我在 Visual Studio 2015 年工作,目标是 .NET 4.6。
看起来您正在声明 DataBinding,而您的 bindingSource 仍在 BeginInit - EndInit 块中。尝试将该行移动到 之后 EndInit 行,或者改为在 OnLoad 覆盖中:
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
comboBox.DataBindings.Add(new Binding("DataSource", bindingSource, "Options", true));
}
为DataSource
属性 添加Binding
是错误的想法。
要设置 DataSource
,您应该为 DataSource
分配一些内容,而不是添加 Binding
。例如,添加 Binding
对 SelectedValue
有意义,但对 DataSource
.
您的代码应该是:
bindingSource.DataSource = typeof(MainModel);
bindingSource.DataMember = "Options";
comboBox = new ComboBox();
comboBox.DataSource = bindingSource;
comboBox.DropDownStyle = ComboBoxStyle.DropDownList;
Controls.Add(comboBox);
那么您将不会收到任何错误。
注意:如果出于任何原因您只是想知道如何避免示例中的错误,只需设置 this.Visible = true
或准确调用 this.Show()
在 InitializeComponent
之后强制创建控制句柄并使数据绑定开始工作。我的代码不需要此修复程序。
为什么数据绑定到 DataSource
属性 不是一个好主意?
如果您要将 DataSource
属性 绑定到 MainModel
的 Optins
属性,则意味着您要更新 Options
属性 使用组合框!这也意味着 MainModel
class 应该实现 INotifyPropertyChanged
以通知组合框有关 Options
属性 的变化!(请记住选项 属性 是 IList
) 这是完全错误的想法!
那么如何通知 ComboBox
数据源的变化?
如果要通知 ComboBox
数据源的更改,数据源列表应实现 IBindingList
。 BindingList<T>
是实现的一个例子。所以设置 comboBox.DataSource = someDataSource;
而不是数据绑定到 DataSource
.