vb.net - 组合框数据绑定(bind)错误 - 如果以编程方式失去焦点,则不会写入值

标签 vb.net winforms

我有一个空白表单,我在其中添加了默认的 ComboBox , TextBox (仅用于接收焦点)和 Label 。组合框具有设置为表单上私有(private)属性的数据绑定(bind)。

设置:

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 类型的私有(private)变量如下:

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

问题是这会破坏第一个选择的数据绑定(bind)。组合框肯定失去了焦点,它肯定有一个新的 SelectedValue验证肯定已触发,但数据绑定(bind)未将新值写入 SomePropertysomeClass (在本例中, setter 永远不会触发,并且标签不会更新)。在后续选择中,setter 将触发

如有必要,请从ComboBox1.SelectionChangeCommitted事件,我将手动编写数据绑定(bind),但感觉这是额外的工作,因为我还需要在验证事件期间处理代码。

ComboBox1.DataBindings.Item("SelectedValue").WriteValue()

问题:

  • 以编程方式和手动失去焦点不应该做同样的事情吗?
  • 为什么这适用于后续选择,但不适用于第一个选择?
  • 这实际上是 WinForms 中的一些错误,还是我做了一些严重错误的事情?

更新:

感谢您迄今为止的回答。我想我更多的是在寻找解释而不是解决方法。为什么会出现这样的情况:即使控件已验证,在验证时更新的绑定(bind)属性也不会更新。此外,为什么它不会第一次发生,而是适用于所有 future 的事件?

最佳答案

我会以不同的方式设置它。您确实不应该从 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 并修复您的数据绑定(bind),以便所有内容都是数据绑定(bind)的:

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 绑定(bind)到您的标签,以便当组合框更改时,标签也会更新。

最后一点是将组合框上的 DataSourceUpdateMode 设置为 OnPropertyChanged,这将允许您摆脱该事件处理程序。

更好的是,您应该让 SomeClass 继承自 INotifyPropertyChanged因为您正在对其进行数据绑定(bind),并且您希望确保对 SomeClass 的更改会通知 UI。

关于vb.net - 组合框数据绑定(bind)错误 - 如果以编程方式失去焦点,则不会写入值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17556487/

相关文章:

vb.net 使用 FindWindowex 在另一个应用程序中查找消息框

sql-server - 如何使用 CMD 将 SQL Server 实例 TCP 端口更改为 1433?

asp.net - 遍历文本框和标签

c# - 如何强制执行某个 UserControl 设计

.net - 向现有 WinForms 应用程序添加 Windows 8 触摸支持

vb.net - 用于循环类属性的 Lambda 表达式

javascript - 从javascript调用.ascx的vb.net函数,该函数也在.ascx中

vb.net - 有没有办法将表单放置在任何尺寸屏幕上的相同位置?

c# - 创建没有按钮且没有最小化和最大化按钮的自定义消息框

c# - 激活 C# Win 窗体的 MessageBox 对话框