2009-10-28 77 views
7

如果通過設置DataSourceUpdateMode = Never關閉自動更新綁定數據源,然後使用按鈕更新整個批次(使用binding.WriteValue),則會出現問題 - 即,只有第一個綁定控件的數據源被更新。所有其他控件重置爲原始值。使用WriteValue手動綁定數據

這是因爲噹噹前對象發生變化(就像在上面的WriteValue之後發生的那樣),如果ControlUpdateMode = OnPropertyChange,那麼所有其他控件會重新讀取數據源中的值。

避免此問題的標準方法是什麼?

一種方法是從BindingSource派生一個類並添加一個WriteAllValues方法。 該方法執行以下操作:

(1)對於每個綁定,保存ControlUpdateMode

(2)對於每種結合,設置ControlUpdateMode =從不

(3)對於每一個結合,調用WriteValue方法

(4)對於每個綁定,復位ControlUpdateMode爲保存的值

(5)對於每一個結合,如果ControlUpdateMode = OnPropertyChange,調用ReadValue方法。

你能看到這樣做的任何問題嗎?

如果使用自己的類,是否會實現IEditableObject解決該問題?

在我正在處理的另一個控件中,我實現了自己的綁定。我通過下面的代碼解決了這個問題。 (我已經把在最低限度,我希望你能理解!):

Private Shared ControlDoingExplicitUpdate As MyCustomControl = Nothing 

Private Sub UpdateDataSourceFromControl(ByVal item As Object, ByVal propertyName As String, ByVal value As Object) 
    Dim p As PropertyDescriptor = Me.props(propertyName) 
    Try 
    ControlDoingExplicitUpdate = Me 
    p.SetValue(item, value) 
    Catch ex As Exception 
    Throw 
    Finally 
    ControlDoingExplicitUpdate = Nothing 
    End Try 
End Sub 

Private Sub DataBindingSource_CurrentItemChanged(ByVal sender As Object, ByVal e As System.EventArgs) 
    If (ControlDoingExplicitUpdate IsNot Nothing) AndAlso (ControlDoingExplicitUpdate IsNot Me) Then Exit Sub 
    Me.UpdateControlFromDataSource() 'Uses ReadValue 
End Sub 

所以,當UpdateDataSourceFromControl被調用時,所有的CurrentItemChanged事件將被要求在相同的BindingSource所有其他控件。但是,由於設置了ControlDoingExplicitUpdate,它們將不會重新讀取來自數據源的值,除非它們恰好是進行更新的控件。 所有這些事件都完成後,ControlDoingExplicitUpdate設置爲Nothing,以便正常的服務恢復。

我希望你可以關注這個,再次 - 我問,你能看到這個問題嗎?

回答

4

我對錶單有類似的要求。在我的情況下,我只想在單擊窗體的保存按鈕時發生所有窗體控件的數據綁定。

我發現最好的解決辦法是,每一個綁定的DataSourceUpdateMode設置爲OnValidation然後將包含窗體的AutoValidate屬性爲禁用。這可以防止在您更改窗體上的控件之間的焦點時進行綁定。然後,在我的保存按鈕的Click事件中,我手動驗證了我的表單輸入,如果確定,則調用表單的ValidateChildren方法來觸發綁定。

此方法還具有讓您完全控制如何驗證輸入的優勢。 WinForms不包含默認情況下執行此操作的好方法。

2

我相信我最近看了在哪裏這是給出一個答案計算器: Disable Two Way Databinding

public static class DataBindingUtils 
{ 
    public static void SuspendTwoWayBinding(BindingManagerBase bindingManager) 
    { 
     if(bindingManager == null) 
     { 
      throw new ArgumentNullException ("bindingManager"); 
     } 

     foreach(Binding b in bindingManager.Bindings) 
     { 
      b.DataSourceUpdateMode = DataSourceUpdateMode.Never; 
     } 
    } 

    public static void UpdateDataBoundObject(BindingManagerBase bindingManager) 
    { 
     if(bindingManager == null) 
     { 
      throw new ArgumentNullException ("bindingManager"); 
     } 

     foreach(Binding b in bindingManager.Bindings) 
     { 
      b.WriteValue(); 
     } 
    } 
}