自定义StronglyTyped BindingSource项目添加

时间:2014-04-30 02:02:30

标签: c# winforms data-binding .net-4.5 bindingsource

我想自定义将新项目添加到BindingSource(所有强类型)中,如以下MSDN文章中所述:

How to: Customize Item Addition with the Windows Forms 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; 
}

1 个答案:

答案 0 :(得分:2)

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

另外,请注意该示例使用类对象DemoCustomer,而DataSet.Tables[0].Row则返回DataRow。在我的观点中,当使用DataSet时,游戏有点不同。

当使用DataSet时,您只需要设置DataTable作为BindingSource.DataSource,这样就可以写出:

BindingSource.DataSource = DataSet.Tables[0];

这样,当您使用BindingSource.ListBindingSource.AddNew()添加项目时,BindingSource"知道"它的DataTableDataSource,因此它调用了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可以具有四种不同版本状态之一:默认,原始,当前和建议。

     

在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();