I have a blank form, to which I've added a default ComboBox, TextBox (just for receiving focus), and Label. The combobox has a databinding set up to a private property on the form.

Setup:

<!-- language: lang-vb -->
Private Sub FormLoad(sender As System.Object, e As System.EventArgs) _
      Handles MyBase.Load
    Dim data = {New With {.Display = "", .Value = ""},
                New With {.Display = "A", .Value = "A"},
                New With {.Display = "B", .Value = "B"},
                New With {.Display = "C", .Value = "C"}}

    ComboBox1.DataSource = data
    ComboBox1.DisplayMember = "Display"
    ComboBox1.ValueMember = "Value"
    ComboBox1.DataBindings.Add("SelectedValue", someClass, "SomeProperty")
End Sub

Where someClass is a private variable of type SomeClass below:

<!-- language: lang-vb -->
Public Class SomeClass

	Private _someProperty As String = ""

	Public Property SomeProperty() As String
		Get
			Return _someProperty
		End Get
		Set(ByVal value As String)
			_someProperty = value
			Form1.Label1.Text = String.Format("Some property = ""{0}""", value)
		End Set
	End Property

End Class

Expected Behavior:

The default Binding.DataSourceUpdateMode is that changes will be propagated OnValidation.

If I select a value from the ComboBox and then click off it onto the TextBox, then the DataBinding will write the new value to the specified property and the Label on my main form will be updated.

Possible Bug:

The problem comes in because we have a business rule that requires us to perform validation immediately when a selection is made. In order for validation to fire, the ComboBox has to lose focus, so by adding the following code to the SelectionChangeCommitted event, we can programmatically force validation

<!-- language: lang-vb -->
Private Sub ComboChanged(sender As System.Object, e As EventArgs) _
        Handles ComboBox1.SelectionChangeCommitted
    TextBox1.Focus()
End Sub

The problem is that this breaks the databinding for the very first selection. The combobox has definitely lost focus, it definitely has a new SelectedValue and validation has definitely fired, but the databinding did not write the new value to SomeProperty on someClass (The setter never fires and the label, in this example, doesn't update). In subsequent selections, the setter will fire

If necessary, from the ComboBox1.SelectionChangeCommitted event, I'll manually write the databinding, but feel like this is extra work since I need to process code during the Validation Event as well.

<!-- language: lang-vb -->
ComboBox1.DataBindings.Item("SelectedValue").WriteValue()

Questions:

  • Shouldn't programmatically and manually losing focus do the same thing?
  • Why does this work on subsequent selections, but not on the first one?
  • Is this in fact some bug in WinForms, or have i done something horribly wrong?

Update:

Thanks for the answers so far. I guess I was looking more for an explanation than a workaround. Why would it be the case that a bound property that updates on validation doesn't update even when the control has validated. Further, why would it not happen the first time, but work for all future events?

I would set this up differently. You really shouldn't be changing your UI from your SomeClass object. It should just store data:

Public Class SomeClass

    Private _someProperty As String = ""

    Public Property SomeProperty() As String
        Get
            Return _someProperty
        End Get
        Set(ByVal value As String)
            _someProperty = value
        End Set
    End Property

End Class

Then, change your FormLoad and fix your data bindings so that everything is data bound:

Private Sub FormLoad(sender As System.Object, e As System.EventArgs) _
      Handles MyBase.Load
    Dim data = {New With {.Display = "", .Value = ""},
                New With {.Display = "A", .Value = "A"},
                New With {.Display = "B", .Value = "B"},
                New With {.Display = "C", .Value = "C"}}

    Label1.DataBindings.Add("Text", someClass, "SomeProperty");

    ComboBox1.DataSource = data
    ComboBox1.DisplayMember = "Display"
    ComboBox1.ValueMember = "Value"
    ComboBox1.DataBindings.Add("SelectedValue", someClass, "SomeProperty", 
          false, DataSourceUpdateMode.OnPropertyChanged)
End Sub

Notice that above we bind someClass to your Label so that when the combobox is changed, the label will be updated.

The final bit is to set the DataSourceUpdateMode on your combobox to OnPropertyChanged which will allow you to get rid of that event handler.

Better still, you should have SomeClass inherit from INotifyPropertyChanged because you are data binding it and you want to make sure that changes to SomeClass will have it notify the UI.