自定义StronglyTyped BindingSource项目添加

我想自定义添加一个新项目到BindingSource (所有强类型),如下面的MSDN文章所述:

如何:使用Windows窗体绑定源自定义项目添加

下面的代码导致InvalidOperationException :添加到BindingSource列表的对象必须都是相同的类型。 此外,对象myTypesBindingSource.Current似乎是一个DataRowView ,里面有我的相关行。

如何自定义强类型BindingSource

 private void InitializeComponent() { this.components = new System.ComponentModel.Container(); this.someDataSet = new myDB.SomeDataSet(); this.myTypesBindingSource = new System.Windows.Forms.BindingSource(this.components); this.myTypesTableAdapter = new myDB.SomeDataSetTableAdapters.myTypesTableAdapter(); this.tableAdapterManager = new myDB.SomeDataSetTableAdapters.TableAdapterManager(); this.myTypesBindingNavigator = new System.Windows.Forms.BindingNavigator(this.components); this.someIntValueTextBox = new System.Windows.Forms.TextBox(); // someDataSet this.someDataSet.DataSetName = "SomeDataSet"; this.someDataSet.SchemaSerializationMode = System.Data.SchemaSerializationMode.IncludeSchema; // myTypesBindingSource // As generated: // this.myTypesBindingSource.DataMember = "myTypes"; // this.myTypesBindingSource.DataSource = this.someDataSet; this.myTypesBindingSource.DataSource = this.someDataSet; this.myTypesBindingSource.AddingNew += new System.ComponentModel.AddingNewEventHandler(this.myTypesBindingSource_AddingNew); // myTypesTableAdapter this.myTypesTableAdapter.ClearBeforeFill = true; // tableAdapterManager this.tableAdapterManager.BackupDataSetBeforeUpdate = false; this.tableAdapterManager.myTypesTableAdapter = this.myTypesTableAdapter; this.tableAdapterManager.UpdateOrder = myDB.SomeDataSetTableAdapters.TableAdapterManager.UpdateOrderOption.InsertUpdateDelete; // someIntValueTextBox this.someIntValueTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.myTypesBindingSource, "someIntValue", true)); this.someIntValueTextBox.Name = "someIntValueTextBox"; } private void myTypesBindingSource_AddingNew(object sender, AddingNewEventArgs e) { SomeDataSet.myTypesRow newRow = someDataSet.myTypes.NewmyTypesRow(); newRow.someIntValue = 99; e.NewObject = newRow; } 

在该示例中,它不是强类型的BindingSource 。 事实上, AddingNewEventArgs.NewObject属性是一个对象。 因此,任何派生类型都应该分配它。

另外,请注意该示例使用了一个类对象DemoCustomer ,它没有返回DataRow DataSet.Tables[0].Row 。 在我看来,使用DataSet时游戏有点不同。

当一个人使用DataSet ,你必须只设置一个DataTable作为BindingSource.DataSource ,这样你就可以这样写:

 BindingSource.DataSource = DataSet.Tables[0]; 

这样,当您使用BindingSource.AddNew()将项添加到BindingSource.ListBindingSource “知道”它有一个DataTable作为其DataSource ,因此它调用DataTable.NewRow()方法并添加一个新的DataRow到您的DataTable ! 因此,要处理DataRow而不是简单的对象。

使用DataRow

如果你想做类似于MSDN上的例子,你必须自己创建行。

 DataRow newRow = DataSet.Tables[0].NewRow(); newRow.Columns["intColumn"] = 99; e.NewObject = newRow; 

这样,您就可以知道自己想要的默认值。

否则,如果没有,你可以试试这个:

 var newRow = (DataRow)e.NewObject; newRow["intColumn"] = 99; 

这里的弱点是每当您更改基础数据库表列名称时,您必须来到此处,更改intColumn的名称,并重新编译和重新部署。

此外,这不应经常发生,因此根据您的环境背景可能值得。

编辑#1

在更加关注之后:

此外,对象myTypesBindingSource.Current似乎是一个DataRowView,里面有我的相关行

来自MSDN: DataRowView

每当显示数据时,例如在DataGrid控件中,每行只能显示一个版本。 显示的行是DataRowView。

DataRowView可以具有四种不同版本状态之一:Default,Original,Current和Proposed。

在DataRow上调用BeginEdit后,任何已编辑的值都将成为Proposed值。 在调用CancelEdit或EndEdit之前,该行具有Original和Proposed版本。 如果调用CancelEdit,则丢弃建议的版本,并且值将恢复为Original。 如果调用EndEdit,则DataRowView不再具有Proposed版本; 相反,建议的值成为当前值。 默认值仅适用于具有已定义默认值的列的行。

这意味着在添加新行时,实际上是在添加DataRowView 。 您可以通过访问其DataRowView.Row属性来访问当前行。

考虑到这一点,您可能会在我最初的答案中更改建议的解决方案:

 var newRow = ((DataRowView)e.NewObject).Row; newRow.Columns["intColumn"] = 99; 

编辑:(史蒂文)最终法典

 DataView dv = (DataView)myTypesBindingSource.List; DataRowView drv = dv.AddNew(); SomeDataSet.myTypesRow newMyTypesRow = (SomeDataSet.myTypesRow)drv.Row; newMyTypesRow.someIntValue = 53; e.NewObject = drv; myTypesBindingSource.MoveLast();