问题
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:
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:
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
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.
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?
回答1:
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.
回答2:
I can't honestly answer questions 1 and 2, but I can give you this to answer question 3. You didn't do anything terribly wrong, just didn't include a helpful line of code.
Add the following line to FormLoad
:
ComboBox1.DataBindings.DefaultDataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged
I tested this out in Visual Studio 2010 and the label updates properly when a new value is selected from the combobox
.
来源:https://stackoverflow.com/questions/17556487/combobox-databinding-bug-wont-write-value-if-programmatically-losing-focus