防止项目在组合框中重复

本文关键字:组合 项目 | 更新日期: 2023-09-27 18:27:48

我使用从类继承ComboBox vb.net创建了一个用户控件。

我已经定义了一个名为"ComboType"的属性,其类型为enum和一些arrays,以及一个名为"ComboPopulate"的方法,该方法填充组合框依赖于ComboType属性(我为此使用了选择案例或开关块(,并且还定义了一个名为"SelectedTypeChanged"的事件,每当ComboType属性的值发生变化时都会发生。

问题:

当我将此 UI 添加到窗体并更改 ComboType 属性时,它可以工作,但尽管我将Me.Items.Clear()方法放在ComboPopulate方法之上,但它还是插入每个数组两次。

为什么会发生这种情况,解决方案是什么?

这是代码

Public Class AdvancedComboBox
    Implements INotifyPropertyChanged
    Dim Array1() As String = New String() {"item1", "item2", "item3"}
    Dim Array2() As String = New String() {"number1", "number2", "city3"}
    Dim Array3() As String = New String() {"city1", "city2", "city3"}
    Public Event SelectedTypeChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
    Private Sub NotifyPropertyChanged(info As String)
        RaiseEvent SelectedTypeChanged(Me, New PropertyChangedEventArgs(info))
    End Sub

    Public Enum ComboTypes
       None
       Type1
       Type2
       Type3
    End Enum
    Dim _type As ComboTypes
    Public Property ComboBoxType As ComboTypes
        Get
            Return _type
        End Get
        Set(value As ComboTypes)
            _type = value
            NotifyPropertyChanged("shomething")
        End Set
    End Property

    Public Sub ComboPopulate()
        Me.Items.Clear()
        Select Case Me.ComboBoxType
            Case ComboTypes.Type1
                Items.Clear()
                Items.AddRange(Array1)
            Case ComboTypes.Type2
                Items.Clear(         
                Items.AddRange(Array2)
            Case ComboTypes.Type3
                Items.Clear()
                Items.AddRange(Array3)
            Case ComboTypes.None
                Items.Clear()
        End Select
    End Sub

    Private Sub AdvancedComboBox_SelectedTypeChanged(sender As Object, e As PropertyChangedEventArgs) Handles Me.SelectedTypeChanged
        ComboPopulate()
    End Sub

End Class

防止项目在组合框中重复

您的代码有几个概念问题,首先是:I created a user control which inherits from ComboBox class . 如果它是一个用户控件,它继承自用户控件,但上面会有一个组合框。 如果要从 ComboBox 继承,则缺少一个键语句:

Public Class AdvancedComboBox 
    Inherits ComboBox                   ' this is missing
    Implements INotifyPropertyChanged

代码引用看起来更像是继承的控件而不是UserControl,所以我猜测这就是你所追求的(通过注释确认(。 核心问题出在设计器代码中:

Me.ComboEx1.ComboBoxType = WindowsApplication1.ComboEx.ComboTypes.Type2
Me.ComboEx1.FormattingEnabled = True
Me.ComboEx1.Items.AddRange(New Object() {"number1", "number2", "city3"})

向窗体添加控件并设置 ComboBoxType 属性时,代码将填充项。 但是,如您所见,在创建窗体时,VS 还会将这些项作为设计器序列化的一部分直接添加到Items。 由于CBO填充自己很奇怪,这是意料之中的。 如果/当您在运行时更改 ComboBoxType 时,它们不会加倍。

一个简单的解决方法是默认为 None 并且仅在运行时设置类型,而不是通过 IDE props 窗口:

Dim _type As ComboTypes = ComboTypes.None
Sub Form1_Load(....
   myAdvCBO.ComboBoxType = ComboTypes.Type2

如果执行此操作,则可能需要在 IDE 窗口中隐藏"属性":

<Browsable(False)>
Public Property ComboBoxType As ComboTypes

修复它的另一种方法是实现ISupportInitialize

Public Class ComboEx
    Inherits ComboBox
    Implements ISupportInitialize

点击最后一行的 Enter 将向控件添加 2 个新方法:

Public Sub BeginInit() Implements ISupportInitialize.BeginInit
Public Sub EndInit() Implements ISupportInitialize.EndInit

在控件上设置任何属性之前以及设置所有属性之后,将调用这些属性。 EndInit将允许您撤消 VS 设计器代码(您可以看到在设计器代码的开头和结尾调用这些代码(。

Public Sub EndInit() Implements ISupportInitialize.EndInit
    ComboPopulate()
End Sub

您的ComboPopulate已经清除了应该解决问题Items


还有其他一些潜在问题:

属性资源库将引发错误事件,因为您没有测试它是否实际更改。 如果SelectedTypeChanged事件应该挂接到ControlDesigner或其他东西,那么额外的事件可能会导致问题,因为VS会重复设置/获取。 您的二传手可能应该是:

Set(value As ComboTypes)
    If value <> _type Then     ' see if it really did change
        _type = value
        NotifyPropertyChanged("shomething")    ' sic
        ComboPopulate()        ' same as reacting to event
    End If
End Set

由于您的本地处理程序AdvancedComboBox_SelectedTypeChanged做的很少,这似乎也有些矫枉过正。我摆脱了它。 最后,由于用户无法更改所选类型,因此只能通过表单代码进行:

ComboEx1.ComboBoxType = ComboEx.ComboTypes.Type3

那么,触发一个事件来告诉你的表单代码它刚刚改变了它刚刚改变的内容有什么意义呢? 也许这是我们不知道的更大计划的一部分,但正如所呈现的那样,它并没有增加任何价值。

如果这是为了对正在更改的属性做出反应Items以便可以更新,那么您真的不需要它。