C# 为什么';当使用EndCurrentEdit时,绑定值是否会在第一次更改时保留到数据源?
我有一个C# 为什么';当使用EndCurrentEdit时,绑定值是否会在第一次更改时保留到数据源?,c#,data-binding,.net-3.5,C#,Data Binding,.net 3.5,我有一个复选框,它将属性绑定到bool值。在CheckedChanged事件期间,某些逻辑运行,使用数据源上的bool属性 我的问题是,当用户第一次选中复选框时,绑定的数据源不会得到更新。不过后续的更新工作正常 下面是一些测试问题的示例代码。只需创建一个空白表单并添加一个复选框 public partial class Form1 : Form { private bool _testBool; public bool TestBool { get { r
复选框
,它将属性绑定到bool值。在CheckedChanged
事件期间,某些逻辑运行,使用数据源上的bool属性
我的问题是,当用户第一次选中复选框时,绑定的数据源不会得到更新。不过后续的更新工作正常
下面是一些测试问题的示例代码。只需创建一个空白表单并添加一个复选框
public partial class Form1 : Form
{
private bool _testBool;
public bool TestBool
{
get { return _testBool; }
set { _testBool = value; }
}
public Form1()
{
InitializeComponent();
checkBox1.DataBindings.Add(new Binding("Checked", this, "TestBool"));
checkBox1.CheckedChanged += new EventHandler(checkBox1_CheckedChanged);
}
void checkBox1_CheckedChanged(object sender, EventArgs e)
{
checkBox1.BindingContext[this].EndCurrentEdit();
Debug.WriteLine(TestBool.ToString());
}
}
第一次选中该框时,TestBool
属性保持为false,即使checkBox1.Checked
设置为true
。随后的更改确实正确地更新了TestBool
属性,以匹配checkBox1。但已选中
如果我向CheckedChanged
事件添加断点,并从即时窗口中签出checkBox1.BindingContext[this].Bindings[0]
,我可以看到它第一次运行时modified=false
,这可能就是EndCurrentEdit()
没有正确更新数据源的原因
使用TextBox
和TextChanged
事件也会发生同样的情况,因此这不仅仅限于复选框。选中的
为什么会这样?有没有解决问题的通用方法
编辑:到目前为止,我知道一些变通方法,但没有一种是理想的,因为它们不是通用的,每次我们想要使用更改的事件时都需要记住
- 直接从CheckedChanged事件设置数据源上的属性
- 查找绑定并调用
WriteValue()
- 加载控件后连接绑定
我更关心的是了解为什么会发生这种情况,尽管如果有人知道一种标准的通用解决方案来防止这种情况发生,而该解决方案不依赖于Changed
事件中的任何特殊编码,我也会对此感到高兴。显然,CheckedChanged
事件在这个过程中为时过早
但您可以利用BindingComplete
:
public partial class Form1 : Form
{
private Boolean _testBool;
public Boolean TestBool
{
get { return _testBool; }
set { _testBool = value; }
}
public Form1()
{
InitializeComponent();
checkBox1.DataBindings.Add(new Binding("Checked", this, "TestBool", true, DataSourceUpdateMode.OnPropertyChanged));
checkBox1.DataBindings[0].BindingComplete += Form1_BindingComplete;
}
private void Form1_BindingComplete(Object sender, BindingCompleteEventArgs e)
{
Debug.WriteLine("BindingComplete: " + TestBool.ToString());
}
}
注意,当初始绑定链接发生时,事件将在启动时触发。您必须处理可能出现的意外后果,否则,它在第一次单击和每次单击时都会起作用
还请注意,Binding
构造函数中需要true
(格式)来触发事件。我能找到的最接近此行为的解释是
基本上,这是一个时间问题。DotNet中绑定的工作方式
其实很简单。在DotNet框架中没有神奇的东西
当某些内容发生更改时通知BindingManager。它的作用是,当
绑定到BindingManager看起来的属性(如CheckedValue)
对于名为propertynameChanged的控件上的事件(例如。
“CheckedValueChanged”)。这与代码挂起的事件相同
在你的样本表格上
当控件触发事件时,侦听器的顺序
接收事件是任意的。没有可靠的方法来判断
BindingManager是先获取事件,还是先获取表单
MyCheckBox1\u CheckChanged
事件在BindingManager
处理更改的事件之前运行,因此此时尚未更新数据源
关于为什么这种情况只在第一次发生,我的最佳猜测是控件还不可见,因此一些代码没有运行,这些代码应该修复事件处理的顺序。我已经看到,由于句柄尚未创建,无法绑定到不可见项,其中一个状态为
在控件第一次可见之前,某些后端初始化永远不会发生,而初始化的一部分是启用数据绑定
所以我怀疑这有某种关联
我可以验证,如果我稍后在Load
事件期间附加更改的处理程序,它是否能像我预期的那样工作
public partial class Form1 : Form
{
private bool _testBool;
public bool TestBool
{
get { return _testBool; }
set { _testBool = value; }
}
public Form1()
{
InitializeComponent();
checkBox1.DataBindings.Add(new Binding("Checked", this, "TestBool"));
Load += new EventHandler(Form1_Load);
}
void Form1_Load(object sender, EventArgs e)
{
checkBox1.CheckedChanged += new EventHandler(checkBox1_CheckedChanged);
}
void checkBox1_CheckedChanged(object sender, EventArgs e)
{
// Not needed anymore
//checkBox1.BindingContext[this].EndCurrentEdit();
Debug.WriteLine(TestBool.ToString());
}
}
控件通常希望在写入数据源之前先进行验证,因此在尝试离开控件之前,通常不会写入值
您可以自己强制写入该值:
void checkBox1_CheckedChanged(object sender, EventArgs e) {
Binding b = checkBox1.DataBindings["Checked"];
if (b != null) {
b.WriteValue();
}
Debug.WriteLine(TestBool.ToString());
}
可能是操作顺序问题,请尝试使用Click()
事件。@DonBoitnottClick
事件确实有效,但是当用户以其他方式(例如,使用制表符和空格键)选中该框时,它不会捕获。总的来说,我认为我更喜欢在CheckChanged
事件中设置数据源值的解决方法,尽管您可能会发现操作顺序有问题。数据源更新可能是由某种“验证”调用触发的。当这种情况发生时,这无疑是解决问题的关键。我同意Click不是理想的方法,但它始终是我第一次测试我怀疑与订单相关的事情,因为它几乎总是发生(接近)最后一次。@DonBoitnott是的,如果我包装我的EndCurrentEdit
和Debug。在BeginInvoke
中写入语句,它的值会正确更新。我仍然不明白为什么这只会在值第一次更改时发生,以及为什么这样的错误(如果是这样的话)会首先存在。我希望MS能够更好地测试数据绑定系统的基本功能。当项目第一次更改时,BindingComplete
事件不会运行。我不确定这是否重要,但我使用的是.NET3.5。我的小测试应用程序也设置为3.5,并且在那里工作。无法说明差异可能是什么。啊,我看到了差异,我没有指定DataSourceUpdateMode.OnPropertyChanged的第5个参数