Привязка данных вручную с помощью WriteValue

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

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

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

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

(1) для каждой привязки сохраните ControlUpdateMode

(2) для каждой привязки установите ControlUpdateMode = Never

(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 после завершения всех этих событий, так что нормальная служба возобновляется.

Я надеюсь, что вы можете следить за этим, и-снова-я спрашиваю, вы видите какие-либо проблемы с этим?

2 ответов


У меня были аналогичные требования к форме. В моем случае я только хотел, чтобы привязка данных для всех элементов управления формы происходила при нажатии кнопки сохранения формы.

лучшим решением, которое я нашел, было установить DataSourceUpdateMode каждой привязки в OnValidation, а затем установить свойство AutoValidate содержащей формы для отключения. Это предотвращает привязку при изменении фокуса между элементами управления в форме. Затем в событии Click для кнопки "Сохранить" я вручную проверяю ввод моей формы и, если это нормально, вызовите метод ValidateChildren формы для запуска привязки.

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


Я считаю, что недавно прочитал на stackoverflow, где это было дано в качестве ответа: Отключить Двустороннюю Привязку Данных

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