【问题标题】:Customize StronglyTyped BindingSource Item Addition自定义 StronglyTyped BindingSource 项添加
【发布时间】:2014-04-30 02:02:30
【问题描述】:

我想自定义将新项目添加到 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 这让我进一步了解了我从未经历过的有关 DataSet 和 DataBinding 的详细信息。谢谢你也让我学习。

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


【解决方案1】:

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

另外,请注意该示例使用类对象DemoCustomer,它不是返回DataRowDataSet.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 可以具有以下四种不同版本状态之一:默认、原始、当前和建议。

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

编辑:(作者 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();

【讨论】:

  • 属性编辑器只允许我将 BindingSource.DataSource 设置为 DataSet。没有进一步展开的按钮。如果我更改 Designer.cs 文件中的值,它会反映在“属性”窗口中,但我仍然会收到相同的错误。
  • 通过表单设计器执行此操作可能会限制一些实际上可以通过代码执行的行为。我建议您提供一些进一步的代码示例,显示您的BindingSourceDataGridViewBindingNavigatorDataSet 是如何被初始化和以后使用的。这可能会为我提供更多详细信息,以便进一步帮助您。
  • 我将 myTypes DataTable 从“数据源”窗口拖到添加了以下所有内容的表单上:someDataSetmyTypesBindingSourcemyTypesTableAdaptertableAdapterManagermyTypesBindingNavigator。我将编辑我的原始帖子以包含更多可能相关的代码。
  • SomeDataSet 中有多少张桌子?尝试分配BindingSource.DataSource = someDataSet.Tables[0] 可能会有所帮助。在设计模式下创建所有内容后,您是否尝试过以编程方式初始化值?
  • 您的代码有效,但我想将值分配到强类型行中。我想通了(请参阅答案中附加的最终代码)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 2021-02-08
  • 2023-04-02
  • 2010-11-27
相关资源
最近更新 更多