防止项目在组合框中重复
本文关键字:组合 项目 | 更新日期: 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
以便可以更新,那么您真的不需要它。