3

我在刷新使用 BindingSource 对象的 Windows 窗体控件时遇到了困难。我们有一个 CAB/MVP/SCSF 客户端,我(实际上是“我们”,因为它是一个团队的努力)正在开发它将与远程服务器上运行的 WCF 服务进行交互。(这是我们第一次尝试,所以我们处于学习模式)。对服务的调用之一(来自 Presenter)返回一个包含 3 个 DataTables 的 DataSet,名为“Contract”、“Loan”和“Terms”。每个表只包含一行。当服务返回数据集时,我们将其存储在 SmartPart/View 中的类成员变量中,方法是调用视图中名为 BindData() 的函数并将数据集从演示者类传递给视图;

private System.Data.DataSet _ds = null;
public void BindData(System.Data.DataSet ds)
{
    string sErr = "";
    try
    {
        _ds = ds;  // save to private member variable

        // more code goes down here
    }
}

我们正在尝试将三个 DataTable 中的每一个绑定到各种 Windows 窗体 TextBox、MaskedEditBox 和 Infragistics UltraComboEditor Dropdown 组合框 我们使用 VS2008 IDE 创建了三个 BindingSource 对象,每个 DataTable 一个。

private System.Windows.Forms.BindingSource bindsrcContract;
private System.Windows.Forms.BindingSource bindsrcLoan;
private System.Windows.Forms.BindingSource bindsrcTerms;

我们正在绑定这样的值

if (bindsrcContract.DataSource == null)
{
    bindsrcContract.DataSource = _ds;
    bindsrcContract.DataMember = “contract”;

    txtContract.DataBindings.Add(new Binding("Text", bindsrcContract, "contract_id", true));                       

    txtLateFeeAmt.DataBindings.Add(new Binding("Text", bindsrcContract, "fee_code", true));

    txtPrePayPenalty.DataBindings.Add(new Binding("Text", bindsrcContract, "prepay_penalty", true));

    txtLateFeeDays.DataBindings.Add(new Binding("Text", bindsrcContract, "late_days", true));
}

if (bindsrcLoan.DataSource == null)
{
    bindsrcLoan.DataSource = _ds;
    bindsrcLoan.DataMember = “loan”;

    mskRecvDate.DataBindings.Add(new Binding("Text", bindsrcLoan, "receive_date", true));

    cmboDocsRcvd.DataBindings.Add(new Binding("Value", bindsrcLoan, "docs", true));     
}

当我们第一次从服务中读取数据并取回数据集时,这很有效。信息显示在表单的控件上,我们可以使用表单对其进行更新,然后通过将更改后的值传递回 WCF 服务来“保存”它。

这是我们的问题。如果我们选择一个不同的贷款密钥并对服务进行相同的调用并获得一个新的数据集,同样有 3 个表,每个表有一行,控件(文本框、屏蔽编辑框等)不会使用新信息更新. 请注意,smartPart/View 没有关闭或关闭,而是在调用服务之间保持加载。在第二次调用中,我们没有重新绑定调用,而只是尝试从更新的 DataSet 中刷新数据。

我们已经尝试了我们能想到的一切,但显然我们缺少了一些东西。这是我们第一次尝试使用 BindingSource 控件。我们已经尝试过

bindsrcContract.ResetBindings(false);

bindsrcContract.ResetBindings(true);

bindsrcContract.RaiseListChangedEvents = true;

for (int i = 0; i < bindsrcContract.Count; i++)
{
    bindsrcContract.ResetItem(i);
}

以及再次重置 DataMember 属性。

bindsrcContract.DataMember = ”Contract”;

我们看过很多例子。许多示例都引用了 BindingNavigator,但由于 DataTables 只有一行,我们认为我们不需要它。有很多关于网格的示例,但我们在这里没有使用一个。任何人都可以指出我们哪里出错了,或者指出我们可以提供更多信息的资源吗?

我们使用 VisualStudio 2008、C# 和 .Net 2.0、XP 客户端、W2K3 服务器。

提前致谢

韦斯

4

5 回答 5

2

我今天遇到了类似的问题,发现这行得通。

private void btnCancel_Click(object sender, EventArgs e)
{
    this.MyTable.RejectChanges();
    this.txtMyBoundTextBox.DataBindings[0].ReadValue();
    this.EditState = EditStates.NotEditting;
}
于 2011-01-19T21:21:37.523 回答
1

第一件事:这篇文章需要一些组织。请记住,答案不是按顺序排列的。顺序由投票决定。

因此,如果您还有其他问题,只需修改您的原始问题(用“编辑”标记以避免混淆)。

支持您认为有用的答案。

哦,顺便说一下,在包含代码示例时,请使用代码示例按钮(在编辑窗口上方)。这将为您提供良好的代码格式,包括语法突出显示。

现在开始讨论:这两个问题的根本问题是 Binding-Manager 保留了指向原始对象的链接。

当您将 _ds 指定为 DataSource 时,Binding-Manager 会分析 DataSet 并采取相应措施。如果您将一些其他 DataSet 分配给 _ds,则 Binding-Manager 无法知道这一点。它仍然具有对原始数据集对象的引用。所以这就解释了为什么必须将 DataSource 属性重置为新的 DataSet。

它还解释了为什么删除和添加表格不会导致您的预期结果。同样,Binding-Manager 保存对旧表(或该表中的第一行)的引用。新表永远不会被绑定。同样在这种情况下,重新分配 _ds 也无济于事,因为 _ds 指向与以前相同的 DataSet 对象。Binding-Manager 足够聪明,可以注意到它是同一个对象并且不执行重新绑定操作。

您要么必须修改绑定对象的内容(它会触发 Binding-Manager 订阅的 PropertyChanged-Event),要么必须通过将不同的对象分配给 DataSource-property 来触发完整的重新绑定。

这是对实际情况的简化描述,但我希望它足以解释和解决您的问题。不幸的是,我还没有在网络上(或其他地方)找到关于 WinForms 数据绑定的全面解释。

于 2008-11-05T15:23:55.053 回答
0

Wes, I'm very glad I could help. I still remember an issue very similar to yours taking me weeks to figure out in the wild...

Regarding your questions, here's all I know:

  1. If you set the DataSource first, then the DataMember, your data source will be scanned twice, since setting the DataMember subsequently changes the existing (valid) binding. If you do it the other way around, setting DataMember first (with DataSource being null or better, typeof(YourData)), binding only takes place once when you set the DataSource.

  2. I think you can apply the same solution here. Instead of just

    bindsrcContract.DataSource = _ds;
    

    in your last line, you should write

    bindsrcContract.DataSource = typeof(System.Data.DataSet);
    bindsrcContract.DataSource = _ds;
    
  3. Sorry to disappoint, but I learned all I know about data binding from MSDN as well as trial-and-error. It was quite painful. Hopefully someone else can chime in with a useful link or two.

于 2008-10-29T20:29:06.880 回答
0

尝试组合:

bindingsource.EndEdit() // writting data to underlying source 
bindingSource.ResetBindings(false)  // force controls to reread data from bindingSource

每当您向控件写入内容时使用它。

于 2013-05-02T20:13:34.587 回答
0

如果其他一切都失败了,您可以在每次收到新数据集时重新分配 DataSource,执行以下操作:

bindsrcContract.DataSource = typeof(System.Data.DataSet);
bindsrcContract.DataSource = _ds;

(另外,先初始化 DataMember 再初始化 DataSource 会给你更好的性能。)

于 2008-10-28T21:44:58.693 回答