组合框数据绑定错误 - 如果以编程方式失去焦点,则不会写入值 [英] Combobox DataBinding Bug - Won't write value if programmatically losing focus

查看:29
本文介绍了组合框数据绑定错误 - 如果以编程方式失去焦点,则不会写入值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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.

设置:

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 类型的私有变量:

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

预期行为:

默认 Binding.DataSourceUpdateMode 是更改将被传播OnValidation.

如果我从 ComboBox 中选择一个值,然后在 TextBox 上单击它,那么 DataBinding 会将新值写入指定的属性,然后将 Label 写入我的主表单将更新.

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.

可能的错误:

问题出现是因为我们有一个业务规则,要求我们在做出选择时立即执行验证.为了触发验证,ComboBox 必须失去焦点,因此通过将以下代码添加到 SelectionChangeCommitted 事件,我们可以以编程方式强制验证

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

问题是这破坏了第一个选择的数据绑定.组合框肯定失去了焦点,它肯定有一个新的 SelectedValue 并且验证肯定已经触发,但数据绑定没有将新值写入 someClass<上的 SomeProperty/code> (setter 永远不会触发并且标签,在这个例子中,不会更新).在随后的选择中,setter 将触发

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

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

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

问题:

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

更新:

感谢到目前为止的答案.我想我更多的是寻找解释而不是解决方法.为什么会出现在验证时更新的绑定属性即使在控件已验证时也不会更新的情况.此外,为什么它不会在第一次发生,而是适用于所有未来事件?

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?

推荐答案

我会以不同的方式进行设置.您真的不应该从 SomeClass 对象更改您的 UI.它应该只存储数据:

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

然后,更改您的 FormLoad 并修复您的数据绑定,以便所有内容都是数据绑定的:

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

请注意,上面我们将 someClass 绑定到您的标签,以便在更改组合框时,标签将更新.

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

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

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

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

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.

这篇关于组合框数据绑定错误 - 如果以编程方式失去焦点,则不会写入值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆