简体   繁体   中英

prevent items become duplicated in combo box

I've created a user control using vb.net which inherits from ComboBox class.

I have defined a property named "ComboType" of type of an enum and some arrays and a method named "ComboPopulate" which populates combo box depend on ComboType property (I have used a select case or switch block for this) and also defined an event named "SelectedTypeChanged" which occurs whenever value of ComboType property changes.

Problem:

When I add this UI to a form and change the ComboType property it works but it inserts each array twice despite I've put the Me.Items.Clear() method on top of ComboPopulate method.

Why is this happening and what is the solution?

This is the code

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

Your code has several conceptual problems, starting with this: I created a user control which inherits from ComboBox class . If it is a UserControl it inherits from UserControl but would have a ComboBox on it. If you want to inherit from ComboBox, you are missing a key statement:

Public Class AdvancedComboBox 
    Inherits ComboBox                   ' this is missing
    Implements INotifyPropertyChanged

The code references look more like an inherited control than UserControl, so I took a guess that is what you are after (confirmed via comments). The core problem is in the designer code:

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

When you add a control to the form and set the ComboBoxType property, your code populates the Items. But, as you can see, when creating the form, VS is also adding those items directly to Items as part of designer serialization. Since it is pretty odd for a CBO to populate itself, this is to be expected. If/when you change ComboBoxType at runtime, they don't double up.

One easy fix is to default to None and only set the Type at runtime, not via the IDE props window:

Dim _type As ComboTypes = ComboTypes.None

Sub Form1_Load(....
   myAdvCBO.ComboBoxType = ComboTypes.Type2

If you do this, you might want to hide the Property from the IDE window:

<Browsable(False)>
Public Property ComboBoxType As ComboTypes

Another way to fix it is to implement ISupportInitialize :

Public Class ComboEx
    Inherits ComboBox
    Implements ISupportInitialize

Tapping enter on that last line will add 2 new methods to your control:

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

These will be called before any properties are set on your control, and after all properties are set. EndInit will allow you to undo the VS designer code (you can see these being called at the start and end of the designer code).

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

Your ComboPopulate already clears Items which should fix the problem.


There are a few other potential issues:

Your property setter will raise false events because you are not testing if it actually changed. If the SelectedTypeChanged event is supposed to hook into a ControlDesigner or something, the extra events might cause problems because VS will set/get repeatedly. Your setter should probably be:

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

Since your local handler, AdvancedComboBox_SelectedTypeChanged does so little, it seems like overkill as well. I got rid of it. Finally, since there is no way for the user to change the selected type, it can happen only via your form code:

ComboEx1.ComboBoxType = ComboEx.ComboTypes.Type3

So, what is the point of firing an event to tell your form code it just changed what it just changed? Perhaps this is part of some bigger scheme we are not privy to, but as presented it doesnt add any value.

If this was intended to react to the property being changed so Items could be updated, you really dont need it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM