来自 BindingSource 的 C# 刷新文本框
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/244640/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# refreshing textbox from BindingSource
提问by
I am having difficulty refreshing windows forms controls that are using a BindingSource object. We have a CAB/MVP/SCSF client that I (actually “we” since it is a team effort) are developing that will interact with WCF services running on a remote server. (This is our first attempt at this, so we are in a learning mode). One of the calls (from the Presenter) to the service returns a DataSet that contains 3 DataTables, named “Contract”, “Loan” and “Terms”. Each table contains just one row. When the service returns the dataset, we store it in the SmartPart/View in a class member variable, by calling a function in the view called BindData() and passing the dataset in to the view from the presenter class;
我无法刷新使用 BindingSource 对象的 Windows 窗体控件。我们有一个 CAB/MVP/SCSF 客户端,我(实际上是“我们”,因为这是一个团队努力)正在开发,它将与运行在远程服务器上的 WCF 服务进行交互。(这是我们第一次尝试,所以我们处于学习模式)。对服务的调用之一(来自演示者)返回一个包含 3 个数据表的数据集,名为“合同”、“贷款”和“条款”。每个表只包含一行。当服务返回数据集时,我们将其存储在 SmartPart/View 中的类成员变量中,方法是调用视图中名为 BindData() 的函数并将数据集从 Presenter 类传递给视图;
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
}
}
We are trying to bind each of the three DataTables to an assortment of Windows Forms TextBoxes, MaskedEditBoxes, and Infragistics UltraComboEditor Dropdown comboboxes We created three BindingSource objects, one for each DataTable using the VS2008 IDE.
我们正在尝试将三个 DataTable 中的每一个绑定到各种 Windows Forms TextBox、MaskedEditBox 和 Infragistics UltraComboEditor Dropdown 组合框。我们创建了三个 BindingSource 对象,使用 VS2008 IDE 为每个 DataTable 创建了一个对象。
private System.Windows.Forms.BindingSource bindsrcContract;
private System.Windows.Forms.BindingSource bindsrcLoan;
private System.Windows.Forms.BindingSource bindsrcTerms;
We are binding the values like this
我们正在绑定这样的值
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));
}
This works when we do the first read from the service and get a dataset back. The information is displayed on the form's controls, we can update it using the form, and then “save” it by passing the changed values back to the WCF service.
当我们从服务中进行第一次读取并取回数据集时,这会起作用。信息显示在表单的控件上,我们可以使用表单更新它,然后通过将更改的值传递回 WCF 服务来“保存”它。
Here is our problem. If we select a different loan key and make the same call to the service and get a new DataSet, again with 3 tables with one row each, the controls (textboxes, masked edit boxes, etc.) are not being updated with the new information. Note that the smartPart/View is not closed or anything, but remains loaded in between calls to the service. On the second call we are not rebinding the calls, but simply trying to get the data to refresh from the updated DataSet.
这是我们的问题。如果我们选择不同的贷款键并对服务进行相同的调用并获得一个新的数据集,同样有 3 个表,每个表一行,控件(文本框、屏蔽编辑框等)不会用新信息更新. 请注意, smartPart/View 没有关闭或任何东西,但在调用服务之间保持加载。在第二次调用时,我们不会重新绑定调用,而只是尝试从更新的 DataSet 中获取要刷新的数据。
We have tried everything we can think of, but clearly we are missing something. This is our first attempt at using the BindingSource control. We have tried
我们已经尝试了我们能想到的一切,但显然我们错过了一些东西。这是我们第一次尝试使用 BindingSource 控件。我们试过了
bindsrcContract.ResetBindings(false);
and
和
bindsrcContract.ResetBindings(true);
and
和
bindsrcContract.RaiseListChangedEvents = true;
and
和
for (int i = 0; i < bindsrcContract.Count; i++)
{
bindsrcContract.ResetItem(i);
}
As well as resetting the DataMember property again.
以及再次重置 DataMember 属性。
bindsrcContract.DataMember = ”Contract”;
We've looked at a lot of examples. Many examples make reference to the BindingNavigator but since the DataTables only have one row, we did not think we needed that. There are a lot of examples for grids, but we're not using one here. Can anyone please point out where we are going wrong, or point us to resources that will provide some more information?
我们看了很多例子。许多示例都引用了 BindingNavigator,但由于 DataTables 只有一行,我们认为我们不需要它。有很多关于网格的例子,但我们没有在这里使用一个。任何人都可以指出我们哪里出错了,或者指出我们可以提供更多信息的资源吗?
We're using VisualStudio 2008, C# and .Net 2.0, XP client, W2K3 server.
我们使用 VisualStudio 2008、C# 和 .Net 2.0、XP 客户端、W2K3 服务器。
Thanks in advance
提前致谢
wes
韦斯
回答by Alan
Failing all else, you can reassign the DataSource every time you receive a new dataset, doing something like this:
如果其他方法都失败了,您可以在每次收到新数据集时重新分配 DataSource,执行如下操作:
bindsrcContract.DataSource = typeof(System.Data.DataSet);
bindsrcContract.DataSource = _ds;
(Also, initializing DataMember first and then DataSource will give you better performance.)
(另外,先初始化 DataMember 然后再初始化 DataSource 会给你更好的性能。)
回答by Alan
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:
关于你的问题,我只知道以下几点:
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.
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;
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.
如果您先设置 DataSource,然后设置 DataMember,您的数据源将被扫描两次,因为设置 DataMember 随后会更改现有(有效)绑定。如果反过来,首先设置 DataMember(DataSource 为 null 或更好,typeof(YourData)),则在设置 DataSource 时只进行一次绑定。
我认为您可以在这里应用相同的解决方案。而不是仅仅
bindsrcContract.DataSource = _ds;
在你的最后一行,你应该写
bindsrcContract.DataSource = typeof(System.Data.DataSet); bindsrcContract.DataSource = _ds;
很抱歉让您失望,但我从 MSDN 以及反复试验中学到了我所知道的关于数据绑定的所有知识。这是相当痛苦的。希望其他人可以提供一两个有用的链接。
回答by TToni
First thing: This post needs some organizing. Pease remember that answers are not kept in order. The order is determined by the voting.
第一件事:这篇文章需要一些组织。皮斯记住,答案不是按顺序排列的。顺序由投票决定。
So if you have additional questions, just modify your original question (mark with "Edit" to avoid confusion).
因此,如果您有其他问题,只需修改您的原始问题(用“编辑”标记以避免混淆)。
Upvote answers that you find useful.
为您认为有用的答案点赞。
Oh and by the way, please use the code-sample button (above the edit-window) when including code-samples. That will give you nice formatting of the code including syntax-highlighting.
哦,顺便说一句,当包含代码示例时,请使用代码示例按钮(在编辑窗口上方)。这将为您提供良好的代码格式,包括语法突出显示。
Now to the meat: The underlying problem in both your questions is that the Binding-Manager keeps the links to the original objects.
现在到了重点:您的两个问题的根本问题是 Binding-Manager 保持与原始对象的链接。
When you assign _ds as the DataSource, the Binding-Manager analyzes the DataSet and acts accordingly. If you assign some other DataSet to _ds, the Binding-Manager has no way of knowing this. It still has the reference on the original DataSet-object. So this explains why you have to reset the DataSource-property to the new DataSet.
当您将 _ds 指定为数据源时,绑定管理器会分析数据集并采取相应的行动。如果您将一些其他数据集分配给 _ds,则 Binding-Manager 无法知道这一点。它仍然具有对原始 DataSet 对象的引用。所以这解释了为什么您必须将 DataSource-property 重置为新的 DataSet。
It also explains why the removing and adding of the table doesn't lead to your expected result. Again, the Binding-Manager holds the reference to the old table (or the first row in that table). The new table is never bound. Also in this case the reassigning of _ds does not help, because _ds points to the same DataSet-object as before. The Binding-Manager is smart enough to notice that it's the same object and does no rebinding action.
它还解释了为什么删除和添加表格不会导致您预期的结果。同样,绑定管理器保存对旧表(或该表中的第一行)的引用。新表永远不会被绑定。在这种情况下,重新分配 _ds 也无济于事,因为 _ds 指向与以前相同的 DataSet 对象。Binding-Manager 足够聪明,可以注意到它是同一个对象并且不执行重新绑定操作。
You either have to modify the contents of your bound objects (which fires a PropertyChanged-Event to which the Binding-Manager subscribes) or you have to trigger a complete rebind by assigning a different object to the DataSource-property.
您要么必须修改绑定对象的内容(它会触发 Binding-Manager 订阅的 PropertyChanged-Event),要么必须通过将不同的对象分配给 DataSource-property 来触发完全重新绑定。
This is a simplified description of what actually happens, but I hope it's enough to explain and solve your problem. Unfortunately I have yet to find a comprehensive explanation of WinForms databinding on the web (or elsewhere).
这是对实际发生情况的简化描述,但我希望它足以解释和解决您的问题。不幸的是,我还没有在网络(或其他地方)上找到对 WinForms 数据绑定的全面解释。
回答by Jimmy V
I was having a similar issue today and found this works.
我今天遇到了类似的问题,发现这有效。
private void btnCancel_Click(object sender, EventArgs e)
{
this.MyTable.RejectChanges();
this.txtMyBoundTextBox.DataBindings[0].ReadValue();
this.EditState = EditStates.NotEditting;
}
回答by zeljko
try combination :
尝试组合:
bindingsource.EndEdit() // writting data to underlying source
bindingSource.ResetBindings(false) // force controls to reread data from bindingSource
use this whenever you write something to controls.
每当您向控件写入内容时使用它。