使用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();
}
}
}