自定义StronglyTyped BindingSource项添加
本文关键字:添加 BindingSource StronglyTyped 自定义 | 更新日期: 2023-09-27 18:00:46
我想自定义向BindingSource
(都是强类型的)中添加一个新项目,如以下MSDN文章所述:
如何:使用Windows窗体BindingSource 自定义项目添加
下面的代码导致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.List
时,BindingSource
"知道";它有一个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,则会丢弃建议的版本,并且该值将恢复为"原始"。如果调用EndEdit,则DataRowView不再具有Proposed版本;相反,建议的值变为当前值。默认值仅在具有定义了默认值的列的行上可用。
这意味着当添加新行时,实际上是在添加DataRowView
。您可以通过访问其DataRowView.Row
属性来访问当前行。
考虑到这一点,你可能会改变我最初回答中提出的解决方案:
var newRow = ((DataRowView)e.NewObject).Row;
newRow.Columns["intColumn"] = 99;
编辑:(Steven)最终代码
DataView dv = (DataView)myTypesBindingSource.List;
DataRowView drv = dv.AddNew();
SomeDataSet.myTypesRow newMyTypesRow = (SomeDataSet.myTypesRow)drv.Row;
newMyTypesRow.someIntValue = 53;
e.NewObject = drv;
myTypesBindingSource.MoveLast();