使用WriteValue手动绑定数据

问题描述:

如果通过设置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,以便正常的服务恢复。

我希望你可以关注这个,再次 - 我问,你能看到这个问题吗?

我对表单有类似的要求。在我的情况下,我只想在单击窗体的保存按钮时发生所有窗体控件的数据绑定。

我发现最好的解决办法是,每一个绑定的DataSourceUpdateMode设置为OnValidation然后将包含窗体的AutoValidate属性为禁用。这可以防止在您更改窗体上的控件之间的焦点时进行绑定。然后,在我的保存按钮的Click事件中,我手动验证了我的表单输入,如果确定,则调用表单的ValidateChildren方法来触发绑定。

此方法还具有让您完全控制如何验证输入的优势。 WinForms不包含默认情况下执行此操作的好方法。

我相信我最近看了在哪里这是给出一个答案计算器: 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(); 
     } 
    } 
}