2009-10-28 3 views
7

Если я отключу автоматическое обновление источника данных привязки, установив DataSourceUpdateMode = Never и затем используя кнопку для обновления всей партии (используя binding.WriteValue), возникает проблема - А именно, только первая обновлен источник данных связанного управления. Все остальные элементы управления возвращаются к исходным значениям.Ручное связывание данных с использованием WriteValue

Это связано с тем, что, когда текущий объект изменяется (как это происходит после вышеупомянутого WriteValue), если ControlUpdateMode = OnPropertyChange, то все остальные элементы управления перечитываются в значение из источника данных.

Каков стандартный способ избежать этой проблемы?

Один из способов - получить класс из BindingSource и добавить метод WriteAllValues. Этот метод выполняет следующие действия:

(1) Для каждого связывания, сохранить ControlUpdateMode

(2) Для каждого Binding, установить ControlUpdateMode = Никогда

(3) Для каждого связывания, вызовите WriteValue метод

(4) для каждого связывания, сброс ControlUpdateMode к сохраненному значению

(5) для каждого Binding, если 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 содержащейся формы в Disable. Это предотвращает привязку при изменении фокуса между элементами управления в форме. Затем в событии Click для моей кнопки «Сохранить» я вручную проверяю ввод формы и, если все в порядке, вызовите метод ValidateChildren формы, чтобы вызвать привязку.

Этот метод также имеет то преимущество, что дает вам полный контроль над тем, как вы проверяете ввод. WinForms не включают хороший способ сделать это по умолчанию.

2

Я считаю, что я недавно прочитал на StackOverflow, где это было дано в ответ: 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(); 
     } 
    } 
} 
Смежные вопросы