防止项目在组合框中重复

时间:2014-10-26 11:04:00

标签: c# vb.net combobox duplicates

我使用继承自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

1 个答案:

答案 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可以更新,你真的不需要它。