Class with combobox options

Hobbyist_programmer 621 Reputation points
2020-12-14T18:46:06.91+00:00

Hallo,

I am trying to make a class object which shows a options in a combobox and takes a parameters according to that object selection.

Lets say I have an object or class called Box, I want to show some options in a Combobox, for example one to calculate Area and other for Volume, etc and selected option should be calculated.

Also is there a possibility to populate the textbox controls on the form according to the object inputs needed? or it is only done by hiding and unhiding?

Public Class Box

Public Property Length as Double
Public Property Width as Double
Public Property Height as Double

Public Readonly Property Volume as double
Public Readonly Property Area as double
Public Readonly Property Other as double

End class

Thanks

VB
VB
An object-oriented programming language developed by Microsoft that is implemented on the .NET Framework. Previously known as Visual Basic .NET.
2,741 questions
0 comments No comments
{count} votes

Accepted answer
  1. Karen Payne MVP 35,441 Reputation points
    2020-12-19T16:46:12.463+00:00

    @Hobbyist_programmer

    In regards to CatProduct, I left that out but Visual Studio can auto create it for you although here it is in the code below. Concerting unique properties, the base Product class should have all properties even if not used for some products.

    Public Class CatProduct  
        Public Property Category As Category  
        Public Property List As List(Of Product)  
    End Class  
    

    Think of when a database is properly designed for orders as shown below. Perhaps some orders don't use discount or some products don't use discontinue. It's incorrect to stored some product types differently instead in this type of situation the property is empty in both cases, no harm no foul.

    49645-a1.png

    But if you want to break the rules you can by using base classes and overridable properties as per below.

    Visuals

    49508-a1a.png

    Base class

    Public Class Base  
        Public Property Id() As Integer  
        Public Overridable Property Name() As String  
    End Class  
    

    Revised Product class

    Public Class Product  
        Inherits Base  
        Implements INotifyPropertyChanged  
      
        Private _name As String  
        Private _category As Category  
        Private _price As Decimal  
        Private _quantity As Integer  
      
        Public Overrides Property Name() As String  
            Get  
                Return _name  
            End Get  
            Set  
                _name = Value  
                OnPropertyChanged()  
            End Set  
        End Property  
      
        Public Property Category() As Category  
            Get  
                Return _category  
            End Get  
            Set  
                _category = Value  
                OnPropertyChanged()  
            End Set  
        End Property  
      
        Public Property Price() As Decimal  
            Get  
                Return _price  
            End Get  
            Set  
                _price = Value  
                OnPropertyChanged()  
            End Set  
        End Property  
      
        Public Property Quantity() As Integer  
            Get  
                Return _quantity  
            End Get  
            Set  
                _quantity = Value  
                OnPropertyChanged()  
            End Set  
        End Property  
      
        Public Overrides Function ToString() As String  
            Return $"{Name} {Price}"  
        End Function  
      
        Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged  
        Protected Overridable Sub OnPropertyChanged(<CallerMemberName> Optional propertyName As String = Nothing)  
            PropertyChangedEvent?.Invoke(Me, New PropertyChangedEventArgs(propertyName))  
        End Sub  
      
    End Class  
    

    Other class with all properties

    For above but includes cost while cost should truly be in the classes above.

    Public Class SomeOther  
        Inherits Product  
      
        Private _cost As Integer  
      
        Public Property Cost() As Integer  
            Get  
                Return _cost  
            End Get  
            Set  
                _cost = Value  
                OnPropertyChanged()  
            End Set  
        End Property  
      
    End Class  
    

5 additional answers

Sort by: Most helpful
  1. Anonymous
    2020-12-14T19:09:57.69+00:00

    Hi
    I am almost sure that this is NOT what you are asking for, but it has all the elements you mention. This is a stand alone example. Only needs a BLANK Form1.

    ' BLANK Form1
    Option Strict On
    Option Explicit Off
    Public Class Form1
        Dim WithEvents cb As New ComboBox
        Dim lab As New Label
        Dim box1 As New Box(2, 3, 4)
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            With cb
                .Items.AddRange({"Volume", "Etcetera"})
                .Location = New Point(20, 20)
            End With
            With lab
                .Location = New Point(20, 50)
            End With
            Controls.AddRange({cb, lab})
        End Sub
        Private Sub Cb_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cb.SelectedIndexChanged
            Dim ind As Integer = cb.SelectedIndex
            Select Case ind
                Case 0 ' Volume
                    lab.Text = "Volume = " & box1.Volume.ToString("0.000")
                Case 1
                    lab.Text = "Etcetera = " & box1.etcetera.ToString("0.000")
            End Select
        End Sub
        Public Class Box
    
            Public Property Length As Double
            Public Property Width As Double
            Public Property Height As Double
    
            Sub New(l As Double, w As Double, h As Double)
                Length = l
                Width = w
                Height = h
            End Sub
    
            Function Volume() As Double
                Return Length * Width * Height
            End Function
            Function etcetera() As Double
                Return Length * Width * 2 + Width * Height * 2 + Length * Height * 2
            End Function
        End Class
    End Class
    
    0 comments No comments

  2. Hobbyist_programmer 621 Reputation points
    2020-12-19T08:45:01.623+00:00

    Hallo Les and Karen, May be i did not make it clear. I have a better example here . Lets say i have a shop where i have different objects for purchase (eg. toys, vegs, fruit..etc as different classes) and i have a main class called purchase where i want to have a listof objects called Basket. Now how can i add toys or vegs to my basket?

    at the same time it is possible to show the required input based on the object selected? or i have to first place all controls on the form and i have to hide them based on the object?

    Public Class Purchase
        Public Property Basket as List(of Objects)
        End property
    End class
    
    
    Public Class Toy
        Public Property prop1 as integer
        Public Property prop2 as integer
    End Class
    
    Public Class Grocery
        Public Property prop1 as integer
        Public Property prop2 as integer
    End Class
    
    Public Class Veg
        Public Property prop1 as integer
        Public Property prop2 as integer
    End Class
    
    Public Class Fruit
        Public Property prop1 as integer
        Public Property prop2 as integer
    End Class
    
    0 comments No comments

  3. Karen Payne MVP 35,441 Reputation points
    2020-12-19T11:31:36.75+00:00

    Hello @Hobbyist_programmer

    Rather than one class per type use a single class with a category type as shown below.

    49627-a1.png

    Categories

    Public Enum Category  
        Toy  
        Grocery  
        Produce  
        Beverages  
    End Enum  
    

    Container products

    Public Class Product  
        Implements INotifyPropertyChanged  
      
        Private _name As String  
        Private _category As Category  
        Private _price As Decimal  
        Private _quantity As Integer  
        Public Property Id() As Integer  
      
        Public Property Name() As String  
            Get  
                Return _name  
            End Get  
            Set  
                _name = Value  
                OnPropertyChanged()  
            End Set  
        End Property  
      
        Public Property Category() As Category  
            Get  
                Return _category  
            End Get  
            Set  
                _category = Value  
                OnPropertyChanged()  
            End Set  
        End Property  
      
        Public Property Price() As Decimal  
            Get  
                Return _price  
            End Get  
            Set  
                _price = Value  
                OnPropertyChanged()  
            End Set  
        End Property  
      
        Public Property Quantity() As Integer  
            Get  
                Return _quantity  
            End Get  
            Set  
                _quantity = Value  
                OnPropertyChanged()  
            End Set  
        End Property  
      
        Public Overrides Function ToString() As String  
            Return $"{Name} {Price}"  
        End Function  
      
        Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged  
        Protected Overridable Sub OnPropertyChanged(<CallerMemberName> Optional propertyName As String = Nothing)  
            PropertyChangedEvent?.Invoke(Me, New PropertyChangedEventArgs(propertyName))  
        End Sub  
      
    End Class  
    

    Mocked data

    Public Class MockedData  
        Public Shared Function Products() As List(Of Product)  
            Return New List(Of Product) From {  
                New Product With {  
                    .Id = 100,  
                    .Category = Category.Grocery,  
                    .Name = "Boysenberry Spread",  
                    .Price = 12.88D,  
                    .Quantity = 3},  
                New Product With {  
                    .Id = 342,  
                    .Category = Category.Produce,  
                    .Name = "Tofu",  
                    .Price = 2.99D,  
                    .Quantity = 1},  
                New Product With {  
                    .Id = 4,  
                    .Category = Category.Toy,  
                    .Name = "MatchBox car",  
                    .Price = 5.99D,  
                    .Quantity = 5},  
                New Product With {  
                    .Id = 50,  
                    .Category = Category.Produce,  
                    .Name = "Rössle Sauerkraut",  
                    .Price = 99D,  
                    .Quantity = 1}  
            }  
        End Function  
    End Class  
    

    Form code

    Public Class Form1  
        Private _bindingList As BindingList(Of Product)  
        Private ReadOnly _bindingSouce As New BindingSource  
      
        Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown  
      
            _bindingList = New BindingList(Of Product)(MockedData.Products())  
            _bindingSouce.DataSource = _bindingList  
      
            ComboBox1.DataSource = _bindingSouce  
      
        End Sub  
      
        Private Sub IterateItems_Click(sender As Object, e As EventArgs) Handles IterateItems.Click  
      
            ResultsTextBox.Text = ""  
            Dim sb As New StringBuilder  
      
            Dim results = _bindingList.  
                    GroupBy(Function(product) product.Category).  
                    Select(Function(item) New CatProduct With {.Category = item.Key, .List = item.ToList()}).  
                    ToList()  
      
            For Each catProduct As CatProduct In results  
      
                sb.AppendLine(  
                    $"{catProduct.Category} - " &  
                    $"{catProduct.List.Sum(Function(item) item.Price * item.Quantity)}")  
      
                For Each product As Product In catProduct.List  
                    sb.AppendLine($"   {product.Name} - {product.Quantity} - {product.Price.ToString("C2")}")  
                Next  
            Next  
      
            sb.AppendLine("")  
      
            Dim total = _bindingList.  
                    GroupBy(Function(product) product.Category).  
                    Select(Function(item) New With {.Total = item.Sum(Function(x) x.Price * x.Quantity)}).  
                    Sum(Function(x) x.Total)  
      
            sb.AppendLine($"Total: {total.ToString("C2")}")  
      
            ResultsTextBox.Text = sb.ToString()  
      
        End Sub  
    End Class  
    

    Now if this was part of a database we have something like the following
    49578-a1a.png

    0 comments No comments

  4. Karen Payne MVP 35,441 Reputation points
    2020-12-14T20:24:30.407+00:00

    Hello @Hobbyist_programmer

    Conceptually speaking when working with a control such as a ComboBox or ListBox and need to reflect changes to a property using INotifyPropertyChanged and a BindingList will be your foundation.

    Class

    Imports System.ComponentModel  
    Imports System.Runtime.CompilerServices  
      
    Public Class Box  
        Implements INotifyPropertyChanged  
      
        Private _length As Double  
        Private _width As Double  
        Private _height As Double  
      
        Public Property Length As Double  
            Get  
                Return _length  
            End Get  
            Set  
                _length = Value  
                OnPropertyChanged()  
            End Set  
        End Property  
      
        Public Property Width As Double  
            Get  
                Return _width  
            End Get  
            Set  
                _width = Value  
                OnPropertyChanged()  
            End Set  
        End Property  
      
        Public Property Height As Double  
            Get  
                Return _height  
            End Get  
            Set  
                _height = Value  
                OnPropertyChanged()  
            End Set  
        End Property  
      
        Public ReadOnly Property Volume As Double  
        get  
            Return Length * Width * Height  
        End Get  
        End Property  
        Public ReadOnly Property Area As Double  
        Public ReadOnly Property Other As Double  
      
        Public Overrides Function ToString() As String  
            Return $"{Volume}"  
        End Function  
      
        Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged  
        Protected Overridable Sub OnPropertyChanged(<CallerMemberName> Optional ByVal propertyName As String = Nothing)  
            PropertyChangedEvent?.Invoke(Me, New PropertyChangedEventArgs(propertyName))  
        End Sub  
      
    End Class  
    

    Form code

    Imports System.ComponentModel  
      
    Public Class Form1  
      
        Private ReadOnly _boxList As New List(Of Box) From {  
            New Box() With {.Width = 10, .Height = 20, .Length = 4},  
            New Box() With {.Width = 20, .Height = 40, .Length = 14},  
            New Box() With {.Width = 30, .Height = 60, .Length = 22}}  
      
        Private _boxBindingList As BindingList(Of Box)  
        Private ReadOnly _boxBindingSouce As New BindingSource  
      
        Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown  
      
            _boxBindingList = New BindingList(Of Box)(_boxList)  
            _boxBindingSouce.DataSource = _boxBindingList  
            ComboBox1.DataSource = _boxBindingSouce  
      
            LengthTextBox.DataBindings.Add(  
                "Text",  
                _boxBindingSouce,  
                "Length")  
      
        End Sub  
      
    End Class  
    

    Screenshot

    Change the value in the TextBox and the current item in the ComboBox is updated. This can also be done in code by casting

    _boxBindingList(_boxBindingSouce.Position).Length = 11  
    

    48091-a1.png

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.