[英]Why doesn't a bound value persist to the datasource the first time it changes when using EndCurrentEdit?
我有一個CheckBox
,它的Checked
屬性綁定到bool值。 在CheckedChanged
事件期間,某些邏輯運行使用數據源上的bool屬性。
我的問題是第一次用戶檢查CheckBox
時,綁定的數據源不會更新。 后續更新工作正常。
這是一些用於測試問題的示例代碼。 只需創建一個空白表單並添加一個CheckBox
。
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());
}
}
第一次選中該框時,即使checkBox1.Checked
設置為true
, TestBool
屬性仍為false。 后續更改會正確更新TestBool
屬性以匹配checkBox1.Checked
。
如果我向CheckedChanged
事件添加斷點並從立即窗口檢出checkBox1.BindingContext[this].Bindings[0]
,我可以看到第一次運行時modified = false
,這可能就是為什么EndCurrentEdit()
不是正確更新數據源。
使用TextBox
和TextChanged
事件也會出現同樣的情況,因此這不僅限於CheckBox.Checked
。
為什么是這樣? 是否有解決問題的通用方法?
編輯:到目前為止我知道一些解決方法,雖然沒有一個是理想的,因為它們不是通用的,每次我們想要使用Changed
事件時都需要記住。
WriteValue()
我更關心的是為什么會發生這種情況,盡管如果有人知道一個標准的通用解決方案來防止它發生,而不依賴於Changed
事件中的任何特殊編碼,我也會對此感到高興。
控件通常希望在寫入數據源之前首先完成驗證,因此在您嘗試離開控件之前通常不會寫入值。
您可以自己強制寫入值:
void checkBox1_CheckedChanged(object sender, EventArgs e) {
Binding b = checkBox1.DataBindings["Checked"];
if (b != null) {
b.WriteValue();
}
Debug.WriteLine(TestBool.ToString());
}
顯然, 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何時發生變化。 它的作用是,綁定到屬性(例如CheckedValue)時BindingManager在控件上查找名為propertynameChanged的事件(例如“CheckedValueChanged”)。 這與您的代碼在示例表單中掛鈎的事件相同。
當控件觸發事件時,偵聽器接收事件的順序是任意的。 沒有可靠的方法來判斷BindingManager是先獲取事件還是將表單。
我的CheckBox1_CheckChanged
事件在BindingManager
處理更改的事件之前運行,因此此時數據源尚未更新。
我最好的猜測為什么這只是第一次發生的是控件還不可見,所以有些代碼沒有運行應該修復訂單事件得到處理。我看過其他 帖子關於不能由於尚未創建句柄而綁定到不可見的項目,並且一個答案指出
在控件第一次可見之前,一些后端初始化永遠不會發生,並且該初始化的一部分是啟用數據綁定。
所以我懷疑這是某種相關的。
我可以驗證,如果我稍后在Load
事件期間附加Changed處理程序,它會像我期望的那樣工作。
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());
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.