我有一个空白表单,我已添加默认ComboBox
,TextBox
(仅用于接收焦点)和Label
。组合框具有在表格上设置为私有财产的数据绑定。
设定:
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
其中someClass是下面SomeClass
类型的私有变量:
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
预期行为:
默认Binding.DataSourceUpdateMode
是更改将传播OnValidation
。
如果我从ComboBox
中选择一个值然后将其单击到TextBox
,则DataBinding会将新值写入指定的属性,并且我的主窗体上的Label将会更新
可能的错误:
问题出现了,因为我们有一个业务规则要求我们在做出选择时立即执行验证。为了激活验证,ComboBox必须失去焦点,因此通过将以下代码添加到SelectionChangeCommitted
事件,我们可以通过编程方式强制验证
Private Sub ComboChanged(sender As System.Object, e As EventArgs) _
Handles ComboBox1.SelectionChangeCommitted
TextBox1.Focus()
End Sub
问题是这会破坏第一次选择的数据绑定。组合框肯定失去了焦点,它肯定有一个新的SelectedValue
并且验证肯定已经解雇,但是数据绑定没有将新值写入SomeProperty
someClass
(setter永远不会触发和在此示例中,标签不会更新)。在随后的选择中,setter将触发
如果有必要,从ComboBox1.SelectionChangeCommitted
事件开始,我将手动编写数据绑定,但感觉这是额外的工作,因为我还需要在验证事件期间处理代码。
ComboBox1.DataBindings.Item("SelectedValue").WriteValue()
问题:
更新
感谢目前为止的答案。我想我更多的是寻求解释而不是解决方法。为什么即使控件已经过验证,在验证时更新的绑定属性也不会更新。此外,为什么它不是第一次发生,而是为所有未来事件工作?
答案 0 :(得分:2)
我会以不同的方式设置它。您真的不应该从SomeClass
对象更改UI。它应该只存储数据:
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
然后,更改FormLoad并修复数据绑定,以便所有内容都是数据绑定:
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
请注意,上面我们将someClass
绑定到您的Label,以便在更改组合框时更新标签。
最后一点是将你的组合框上的DataSourceUpdateMode
设置为OnPropertyChanged,这样你就可以摆脱那个事件处理程序。
更好的是,你应该SomeClass
继承INotifyPropertyChanged,因为你是数据绑定它,你想确保对SomeClass的更改会让它通知用户界面。
答案 1 :(得分:1)
我不能诚实地回答问题1和2,但我可以给你这个回答问题3.你没有做任何可怕的错误,只是没有包含一行有用的代码。
将以下行添加到FormLoad
:
ComboBox1.DataBindings.DefaultDataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged
我在Visual Studio 2010中对此进行了测试,当从combobox
中选择新值时,标签会正确更新。