簡體   English   中英

為什么在使用EndCurrentEdit時第一次更改數據源時綁定值是否仍然存在?

[英]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設置為trueTestBool屬性仍為false。 后續更改會正確更新TestBool屬性以匹配checkBox1.Checked

如果我向CheckedChanged事件添加斷點並從立即窗口檢出checkBox1.BindingContext[this].Bindings[0] ,我可以看到第一次運行時modified = false ,這可能就是為什么EndCurrentEdit()不是正確更新數據源。

使用TextBoxTextChanged事件也會出現同樣的情況,因此這不僅限於CheckBox.Checked

為什么是這樣? 是否有解決問題的通用方法?

編輯:到目前為止我知道一些解決方法,雖然沒有一個是理想的,因為它們不是通用的,每次我們想要使用Changed事件時都需要記住。

  • 直接從CheckedChanged事件設置數據源的屬性
  • 找到綁定並調用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM