我使用继承自vb.net
类的ComboBox
创建了一个用户控件。
我已经定义了一个名为“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
答案 0 :(得分:1)
您的代码有几个概念性问题,从这开始:I created a user control which inherits from ComboBox class
。如果它是UserControl,它继承自UserControl,但会有一个ComboBox。如果要从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
属性时,代码会填充Items。但是,正如您所看到的,在创建表单时,VS 还将这些项直接添加到Items
,作为设计器序列化的一部分。由于CBO填充自己很奇怪,这是可以预料的。如果/当您在运行时更改ComboBoxType时,它们不会加倍。
一个简单的解决方法是默认为None,仅在运行时设置Type,而不是通过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
点击最后一行的输入将为您的控件添加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
可以更新,你真的不需要它。