Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/270.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么';当使用EndCurrentEdit时,绑定值是否会在第一次更改时保留到数据源?_C#_Data Binding_.net 3.5 - Fatal编程技术网

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是先获取事件,还是先获取表单

My
CheckBox1\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()
事件。@DonBoitnott
Click
事件确实有效,但是当用户以其他方式(例如,使用制表符和空格键)选中该框时,它不会捕获。总的来说,我认为我更喜欢在
CheckChanged
事件中设置数据源值的解决方法,尽管您可能会发现操作顺序有问题。数据源更新可能是由某种“验证”调用触发的。当这种情况发生时,这无疑是解决问题的关键。我同意Click不是理想的方法,但它始终是我第一次测试我怀疑与订单相关的事情,因为它几乎总是发生(接近)最后一次。@DonBoitnott是的,如果我包装我的
EndCurrentEdit
Debug。在
BeginInvoke
中写入
语句,它的值会正确更新。我仍然不明白为什么这只会在值第一次更改时发生,以及为什么这样的错误(如果是这样的话)会首先存在。我希望MS能够更好地测试数据绑定系统的基本功能。当项目第一次更改时,
BindingComplete
事件不会运行。我不确定这是否重要,但我使用的是.NET3.5。我的小测试应用程序也设置为3.5,并且在那里工作。无法说明差异可能是什么。啊,我看到了差异,我没有指定DataSourceUpdateMode.OnPropertyChanged的第5个参数