如果您在没有调试的情况下运行以下代码(或启用“仅启用我的代码”),它似乎可以正常工作。但是,如果您使用调试器启动它并关闭“启用我的代码”,您将获得此异常(然后被库代码吞噬):
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。
答案 0 :(得分:3)
当您的bindingSource仍然在BeginInit - EndInit块中时,看起来您正在声明您的DataBinding。尝试在 EndInit行之后将该行移动到,或者在OnLoad覆盖中移动:
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
comboBox.DataBindings.Add(new Binding("DataSource", bindingSource, "Options", true));
}
答案 1 :(得分:1)
为Binding
属性添加DataSource
是错误的想法。
要设置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
或在{{1}之后完全调用this.Show()
强制创建控制句柄并使数据绑定开始工作。我的代码不需要此修复程序。
为什么数据绑定到InitializeComponent
属性不是一个好主意?
如果要将DataSource
属性绑定到DataSource
的{{1}}属性,则意味着您将使用组合框更新Optins
属性!这也意味着MainModel
类应该实现Options
来通知组合框MainModel
属性的变化!(请记住,options属性是INotifyPropertyChanged
)&#39 ;完全错误的想法!
那么如何通知Options
数据源的变化?
如果您想通知IList
有关数据源的更改,则数据源列表应实现ComboBox
。 ComboBox
是实施的一个例子。因此,设置IBindingList
而非数据绑定到BindingList<T>
就足够了。