Find an existing item in an item collection - vb.net

below is my code. I am trying to find a specific item after an item or before an item is added. We have two paticular product codes that can't be in the same item colleciton.
One is like "%CNBG%"
the other is Like "%CN-%"
These two products codes and not be added to the same collection for reason of separate transactions. I just want to display an error that CN- products can not be entered with CNBG products.
This is my AddStormItem that ads it to the collection and I think my check needs to go here. How do I find an existing item in the collection that I am adding to below? That way I can run a check on it.
Private Sub AddStoreItem(ByVal ProductCd As String, ByVal ddlSearchField As String, ByVal tbSearchValue As String)
Dim cartitems As Cart = OnsiteCart
Dim s As New dB.Product
Dim dt As DataTable = Store.GetProductbyCd(ProductCd)
Dim ds As New DataSet
Dim er As New Visitor
ds = Common.GetCustomerByParam(OnsiteCart.CustomerCD, "", "", "", "", "")
er.IsMemberFlg = nullCStr(ds.Tables(0).Rows(0)("IsMemberFlg"))
VisitorData = er
Try
If VisitorData.IsMemberFlg <> "N" Then
s.Amount = Format(dt.Rows(0)("UDEF2AMT"), "0.00")
s.Description = dt.Rows(0)("PRODUCTNAME")
s.ItemCD = dt.Rows(0)("PRODUCTCD")
s.Quantity = 1
Else
s.Amount = Format(dt.Rows(0)("UNITPRICE"), "0.00")
s.Description = dt.Rows(0)("PRODUCTNAME")
s.ItemCD = dt.Rows(0)("PRODUCTCD")
s.Quantity = 1
End If
Catch ex As Exception
lblProductError.Text = "Product not found"
lblProductError.Visible = True
End Try
If s.Amount <> 0 Then
cartitems.ItemCollection.Add(s)
lblProductError.Visible = False
End If
End Sub
This is my Cart Class
Imports system
Imports System.Configuration
Imports System.Web.Configuration
Imports System.Data
Imports System.Data.SqlClient
Imports System.Web
Imports System.Web.UI
Imports System.Collections.ObjectModel
<Serializable()> _
Public Class Cart
#Region " Private Variables "
Private strenterusercd As String
Private strinvoicenum As String
Private strinvoicenumreused As Boolean
Private strpayeecd As String
Private strpayeetypecd As String
Private strcustomercd As String
Private strpaymenttype As enPaymentType
Private dblcashamount As Double
Private dblcheckamount As Double
Private strchecknumber As String
Private strponumber As String
Private strCCType As String
Private strCCNumber As String
Private strCCNumberEncrypted As String
Private strCCExp As String
Private strCCZip As String
Private strCCCVV As String
Private strCCVerificationcd As String
Private strCCResponsecd As String
Private strCCRejectioncd As String
Private strCCTransactioncd As String
Private intmaxID As Int32
Private dblCCAmount As Double
#End Region
Public ItemCollection As New CartItems(Of iInvoiceItem)
Enum enPaymentType
CreditCard
Cash
Check
PO
End Enum
#Region " Public Properties "
Public Property EnterUserCd() As String
Get
Return strenterusercd
End Get
Set(ByVal value As String)
strenterusercd = value
End Set
End Property
Public Property InvoiceNumReUsed() As Boolean
Get
Return strinvoicenumreused
End Get
Set(ByVal value As Boolean)
strinvoicenumreused = value
End Set
End Property
Public Property InvoiceNum() As String
Get
Return strinvoicenum
End Get
Set(ByVal value As String)
strinvoicenum = value
End Set
End Property
Public Property PayeeCd() As String
Get
Return strpayeecd
End Get
Set(ByVal value As String)
strpayeecd = value
End Set
End Property
Public Property PayeeTypeCd() As String
Get
Return strpayeetypecd
End Get
Set(ByVal value As String)
strpayeetypecd = value
End Set
End Property
Public Property CustomerCD() As String
Get
Return strcustomercd
End Get
Set(ByVal value As String)
strcustomercd = value
End Set
End Property
Public Property PaymentType() As enPaymentType
Get
Return strpaymenttype
End Get
Set(ByVal value As enPaymentType)
strpaymenttype = value
End Set
End Property
Public Property CashAmount() As Double
Get
Return dblcashamount
End Get
Set(ByVal value As Double)
dblcashamount = value
End Set
End Property
Public Property CheckAmount() As Double
Get
Return dblcheckamount
End Get
Set(ByVal value As Double)
dblcheckamount = value
End Set
End Property
Public Property CheckNumber() As String
Get
Return strchecknumber
End Get
Set(ByVal value As String)
strchecknumber = value
End Set
End Property
Public Property PONumber() As String
Get
Return strponumber
End Get
Set(ByVal value As String)
strponumber = value
End Set
End Property
Public Property CCType() As String
Get
Return strCCType
End Get
Set(ByVal value As String)
strCCType = value
End Set
End Property
Public Property CCNumber() As String
Get
Return strCCNumber
End Get
Set(ByVal value As String)
strCCNumber = value
End Set
End Property
Public ReadOnly Property CCNumberEncrypted() As String
Get
If CCNumber Is Nothing Then
Return ""
ElseIf CCNumber.Length = 16 Then
Return "************" & Right(CCNumber, 4)
Else
Return "***********" & Right(CCNumber, 4)
End If
End Get
End Property
Public Property CCExp() As String
Get
Return strCCExp
End Get
Set(ByVal value As String)
strCCExp = value
End Set
End Property
Public Property CCZip() As String
Get
Return strCCZip
End Get
Set(ByVal value As String)
strCCZip = value
End Set
End Property
Public Property CCCVV() As String
Get
Return strCCCVV
End Get
Set(ByVal value As String)
strCCCVV = value
End Set
End Property
Public Property CCAmount() As Double
Get
Return dblCCAmount
End Get
Set(ByVal value As Double)
dblCCAmount = value
End Set
End Property
Public Property CCVerificationcd() As String
Get
Return strCCVerificationcd
End Get
Set(ByVal value As String)
strCCVerificationcd = value
End Set
End Property
Public Property CCResponsecd() As String
Get
Return strCCResponsecd
End Get
Set(ByVal value As String)
strCCResponsecd = value
End Set
End Property
Public Property CCRejectioncd() As String
Get
Return strCCRejectioncd
End Get
Set(ByVal value As String)
strCCRejectioncd = value
End Set
End Property
Public Property CCTransactioncd() As String
Get
Return strCCTransactioncd
End Get
Set(ByVal value As String)
strCCTransactioncd = value
End Set
End Property
Public Property MaxID() As Int32
Get
Return intmaxID
End Get
Set(ByVal value As Int32)
intmaxID = value
End Set
End Property
#End Region
<Serializable()> _
Public Class CartItems(Of itemType As iInvoiceItem)
Inherits Collection(Of iInvoiceItem)
End Class
Public Sub New()
Me.EnterUserCd = HttpContext.Current.User.Identity.Name
Me.InvoiceNumReUsed = False
Me.InvoiceNum = Nothing 'Common.getAutonumber("INVOICE")
Me.MaxID = 0
End Sub
Public Sub New(ByVal invoicenum As String)
Me.EnterUserCd = HttpContext.Current.User.Identity.Name
Me.InvoiceNumReUsed = True
Me.InvoiceNum = invoicenum
Me.MaxID = 0
End Sub
Public Sub New(ByVal payeecd As String, ByVal payeetypecd As String)
Me.EnterUserCd = HttpContext.Current.User.Identity.Name
Me.InvoiceNum = Nothing 'Common.getAutonumber("INVOICE")
Me.InvoiceNumReUsed = False
Me.PayeeCd = payeecd
Me.PayeeTypeCd = payeetypecd
Me.MaxID = 0
End Sub
Public Sub New(ByVal invoicenum As String, ByVal payeecd As String, ByVal payeetypecd As String)
Me.EnterUserCd = HttpContext.Current.User.Identity.Name
Me.InvoiceNum = invoicenum
Me.InvoiceNumReUsed = True
Me.PayeeCd = payeecd
Me.PayeeTypeCd = payeetypecd
Me.MaxID = 0
End Sub
Public Function CartTotal()
Dim total As Double = 0
For Each item As iInvoiceItem In Me.ItemCollection
total += item.getPrice
'total += item.Amount * item.Quantity
Next
Return total
End Function
Public Function getNewCartItemID() As Int32
Dim ID As Int32 = 0
Me.MaxID += 1
ID = Me.MaxID
Return ID
End Function
Public Function getParentIndSession(ByVal assignedsessioncd As String) As IndSession
Dim S As New IndSession
For Each item As iInvoiceItem In Me.ItemCollection
If item.Type = "Session" Then
If CType(item, dB.IndSession).Assignedsessioncd = assignedsessioncd Then
S = CType(item, dB.IndSession)
End If
End If
Next
Return S
End Function
Public Function getChildIndfunctions(ByVal assignedsessioncd As String) As CartItems(Of iInvoiceItem)
Dim tempcart As New CartItems(Of iInvoiceItem)
For Each item As iInvoiceItem In Me.ItemCollection
If item.Type = "Function" Then
If CType(item, dB.IndFunction).Assignedsessioncd = assignedsessioncd Then
tempcart.Add(CType(item, dB.IndFunction))
End If
End If
Next
Return tempcart
End Function
Public Sub DeleteByAssignedsessioncd(ByVal assignedsessioncd As String)
Dim tempcart As New CartItems(Of iInvoiceItem)
For Each item As iInvoiceItem In Me.ItemCollection
If item.Type = "Session" Then
If CType(item, dB.IndSession).Assignedsessioncd = assignedsessioncd Then
tempcart.Add(item)
End If
ElseIf item.Type = "Function" Then
If CType(item, dB.IndFunction).Assignedsessioncd = assignedsessioncd Then
tempcart.Add(item)
End If
End If
Next
For Each deleteditem As iInvoiceItem In tempcart
Me.ItemCollection.Remove(deleteditem)
Next
End Sub
Public Function getCompCodes() As ArrayList
Dim arrCompCodes As New ArrayList
For Each item As iInvoiceItem In Me.ItemCollection
If item.Type = "Function" Then
If Not CType(item, dB.IndFunction).Compcd Is Nothing Then
arrCompCodes.Add(CType(item, dB.IndFunction).Compcd)
End If
End If
Next
Return arrCompCodes
End Function
Public Function getUsedFreeFullRegistrations() As Int32
Dim count As Int32 = 0
For Each item As iInvoiceItem In Me.ItemCollection
If item.Type = "Session" Then
If CType(item, dB.IndSession).ItemCD = "EXHIB_XC" Then
count += 1
End If
End If
Next
Return count
End Function
Public Function getUsedFreeExhibitOnlyRegistrations() As Int32
Dim count As Int32 = 0
For Each item As iInvoiceItem In Me.ItemCollection
If item.Type = "Session" Then
If CType(item, dB.IndSession).ItemCD = "EXHIB_XD" Then
count += 1
End If
End If
Next
Return count
End Function
Public Function getUsedFreeExhibitDailyRegistrations() As Int32
Dim count As Int32 = 0
For Each item As iInvoiceItem In Me.ItemCollection
If item.Type = "Session" Then
If CType(item, dB.IndSession).ItemCD = "EXHIB_XE" Then
count += 1
End If
End If
Next
Return count
End Function
Public Sub Checkout()
If Me.CartTotal > 0 Then
System.Web.HttpContext.Current.Response.Redirect("payment.aspx")
Else
System.Web.HttpContext.Current.Response.Redirect("confirm.aspx")
End If
End Sub
Public Sub Clear()
Me.CashAmount = Nothing
Me.CCAmount = Nothing
Me.CCCVV = Nothing
Me.CCExp = Nothing
Me.CCNumber = Nothing
Me.CCRejectioncd = Nothing
Me.CCResponsecd = Nothing
Me.CCType = Nothing
Me.CCVerificationcd = Nothing
Me.CCZip = Nothing
Me.CheckAmount = Nothing
Me.CheckNumber = Nothing
Me.CustomerCD = Nothing
Me.EnterUserCd = Nothing
Me.InvoiceNum = Nothing 'Common.getAutonumber("INVOICE")
Me.InvoiceNumReUsed = Nothing
Me.ItemCollection = New CartItems(Of iInvoiceItem)
Me.MaxID = Nothing
Me.PayeeCd = Nothing
Me.PayeeTypeCd = Nothing
Me.PaymentType = Nothing
Me.PONumber = Nothing
End Sub
Public Sub ClearItems()
Me.CashAmount = Nothing
Me.CCAmount = Nothing
Me.CCCVV = Nothing
Me.CCExp = Nothing
Me.CCNumber = Nothing
Me.CCRejectioncd = Nothing
Me.CCResponsecd = Nothing
Me.CCType = Nothing
Me.CCVerificationcd = Nothing
Me.CCZip = Nothing
Me.CheckAmount = Nothing
Me.CheckNumber = Nothing
Me.InvoiceNumReUsed = Nothing
Me.ItemCollection = New CartItems(Of iInvoiceItem)
Me.MaxID = Nothing
Me.PaymentType = Nothing
Me.PONumber = Nothing
End Sub
Public Function getCartContents() As ArrayList
Dim arrCartItems As New ArrayList
For Each item As iInvoiceItem In Me.ItemCollection
arrCartItems.Add(item)
Next
Return arrCartItems
End Function
Public Function getSingleUserCartAssignedsessioncd() As String
Dim retval As String = ""
For Each item As iInvoiceItem In Me.ItemCollection
If item.Type = "Session" Then
retval = CType(item, dB.IndSession).Assignedsessioncd
End If
Next
Return retval
End Function
Public Function getParentItems() As DataTable
Dim dt As New DataTable
For Each item As iInvoiceItem In Me.ItemCollection
If item.Type <> "Function" Then
If Not CType(item, dB.IndFunction).Compcd Is Nothing Then
dt.Rows.Add(CType(item, dB.IndFunction).Compcd)
End If
End If
Next
Return dt
End Function
End Class

In Framework 2.0, I think you'll have to do a loop manually. In 3.5, you can use Linq...still does a loop, but easily:
If s.ItemCd.Contains("CNBG") Then
If (From i In cartitems.ItemCollection Where i.ItemCd.Contains("CN-") Select i).Any() Then
'Error message
Return
End If
ElseIf s.ItemCd.Contains("CN-") Then
If (From i In cartitems.ItemCollection Where i.ItemCd.Contains("CNBG") Select i).Any() Then
'Error message
Return
End If
End If
'Ok if we got here
cartitems.ItemCollection.Add(s)
You can also use StartsWith instead of Contains if the codes are always at the beginning.

Related

List.Add(var) overwrites previous items in list

Every time when you press the button, you should get a customer added to your list. But it just overrides my previous value and doesn't update the List.
This is exactly what they did in my book, but I don't know why the next variable doesn't get added to the list
Private Sub btnOpslaan_Click(sender As Object, e As EventArgs) Handles btnOpslaan.Click
Dim klantenlijst As New List(Of Klant)
Dim nieuwe_klant As New Klant
Dim path As String = IO.Path.GetTempFileName()
nieuwe_klant.Naam = txtNaam.Text
nieuwe_klant.Straat = txtStraat.Text
nieuwe_klant.Postcode = txtPostcode.Text
nieuwe_klant.Gemeente = txtGemeente.Text
nieuwe_klant.Telefoon = txtTelefoon.Text
nieuwe_klant.Email = txtEmail.Text
If chkHardware.Checked = True Then
nieuwe_klant.Hardware = True
End If
If chkInternet.Checked = True Then
nieuwe_klant.Internet = True
End If
If chkMultimedia.Checked = True Then
nieuwe_klant.Multimedia = True
End If
If chkSoftware.Checked = True Then
nieuwe_klant.Software = True
End If
klantenlijst.Add(nieuwe_klant)
MsgBox(klantenlijst.Count)
End Sub
My class "Klant"
Public Class Klant
Private mNaam As String
Private mStraat As String
Private mPostcode As String
Private mGemeente As String
Private mTelefoon As String
Private mEmail As String
Private mHardware As Boolean
Private mSoftware As Boolean
Private mInternet As Boolean
Private mMultimedia As Boolean
Public Sub New()
mHardware = False
mInternet = False
mSoftware = False
mMultimedia = False
mNaam = "Niet ingevuld"
mStraat = "Niet ingevuld"
mPostcode = "Niet ingevuld"
mGemeente = "Niet ingevuld"
mTelefoon = "Niet ingevuld"
mEmail = "Niet ingevuld"
End Sub
Public Property Hardware() As Boolean
Get
Return mHardware
End Get
Set(ByVal value As Boolean)
mHardware = value
End Set
End Property
Public Property Software() As Boolean
Get
Return mSoftware
End Get
Set(ByVal value As Boolean)
mSoftware = value
End Set
End Property
Public Property Internet() As Boolean
Get
Return mInternet
End Get
Set(ByVal value As Boolean)
mInternet = value
End Set
End Property
Public Property Multimedia() As Boolean
Get
Return mMultimedia
End Get
Set(ByVal value As Boolean)
mMultimedia = value
End Set
End Property
Public Property Naam() As String
Get
Return mNaam
End Get
Set(ByVal value As String)
mNaam = value
End Set
End Property
Public Property Straat() As String
Get
Return mStraat
End Get
Set(ByVal value As String)
mStraat = value
End Set
End Property
Public Property Postcode() As String
Get
Return mPostcode
End Get
Set(ByVal value As String)
mPostcode = value
End Set
End Property
Public Property Gemeente() As String
Get
Return mGemeente
End Get
Set(ByVal value As String)
mGemeente = value
End Set
End Property
Public Property Telefoon() As String
Get
Return mTelefoon
End Get
Set(ByVal value As String)
mTelefoon = value
End Set
End Property
Public Property Email() As String
Get
Return mEmail
End Get
Set(ByVal value As String)
mEmail = value
End Set
End Property
End Class
The issue here is that on every click, you are declaring a new 'klantenlijst' and making it private. Just declare it outside of the click and you'll get the desired result:
Dim klantenlijst As New List(Of Klant)
Private Sub btnOpslaan_Click(sender As Object, e As EventArgs) Handles btnOpslaan.Click
Dim nieuwe_klant As New Klant
Dim path As String = IO.Path.GetTempFileName()
nieuwe_klant.Naam = txtNaam.Text
//continue your code...
klantenlijst.Add(nieuwe_klant)
MsgBox(klantenlijst.Count)
Every time the button is clicked, you create a new list:
Dim klantenlijst As New List(Of Klant)
And then you add exactly one item to that list:
klantenlijst.Add(nieuwe_klant)
So that list will only ever contain one item.
Instead, create a class-level list and add to that. So put this line at the class level:
Dim klantenlijst As New List(Of Klant)
Then the same list is available throughout the instance of the class. A few things to note:
Without more context, it's possible that you may even be looking for a larger scope than the class. There are a variety of places you can store information, a class-level variable is simply the next higher scope from your method-level variable.
If you're using ASP.NET then the lifespan of the class is very short (per request) and not persisted between requests. In that case you'd want to store your data somewhere else, possibly in session state or a database.

How to add datas from one class to another

I have a problem and i don't know how to solve it.
I have 2 different classs, and i need to get a datas that are in fist class to another class.
My first class look like :
Public Class ZnrEk1Ospos
Private _sif_tvrtka As Integer
Private _sif_radnika As Integer
Private _red_broj As Integer
Private _sif_ovl_osobe As Integer
Private _datum_teorija As Date
Private _datum_praksa As Date
Private _prezime_ime As String
Private _strucna_sprema As String
Private _funkcija As String
Private _status_obrasca As Integer
Private _glavni_instruktor As Integer
Private _instruktor_prezime As String
Private _instruktor_sprema As String
Private _instruktor_funkcija As String
Private _evidencijski_broj As String
Private _potvrda As String
Public Sub New()
'Do nothing as all private variables has been initiated
End Sub
Public Sub New(ByVal DataRow As DataRow)
_sif_tvrtka = CInt(DataRow.Item("sif_tvrtka"))
_sif_radnika = CInt(DataRow.Item("sif_radnika"))
_red_broj = CInt(DataRow.Item("red_broj"))
_sif_ovl_osobe = CInt(DataRow.Item("sif_ovl_osobe"))
_datum_teorija = IIf(IsDBNull(DataRow.Item("datum_teorija")), Nothing, DataRow.Item("datum_teorija"))
_datum_praksa = IIf(IsDBNull(DataRow.Item("datum_praksa")), Nothing, DataRow.Item("datum_praksa"))
_prezime_ime = IIf(IsDBNull(DataRow.Item("prezime_ime")), "", Trim(DataRow.Item("prezime_ime")))
_strucna_sprema = IIf(IsDBNull(DataRow.Item("strucna_sprema")), "", Trim(DataRow.Item("strucna_sprema")))
_funkcija = IIf(IsDBNull(DataRow.Item("funkcija")), "", Trim(DataRow.Item("funkcija")))
_status_obrasca = CInt(DataRow.Item("status_obrasca"))
_glavni_instruktor = CInt(DataRow.Item("glavni_instruktor"))
_instruktor_prezime = IIf(IsDBNull(DataRow.Item("instruktor_prezime")), "", Trim(DataRow.Item("instruktor_prezime")))
_instruktor_sprema = IIf(IsDBNull(DataRow.Item("instruktor_sprema")), "", Trim(DataRow.Item("instruktor_sprema")))
_instruktor_funkcija = IIf(IsDBNull(DataRow.Item("instruktor_funkcija")), "", Trim(DataRow.Item("instruktor_funkcija")))
_evidencijski_broj = IIf(IsDBNull(DataRow.Item("evidencijski_broj")), "", Trim(DataRow.Item("evidencijski_broj")))
_potvrda = IIf(IsDBNull(DataRow.Item("potvrda")), "", Trim(DataRow.Item("potvrda").ToString))
End Sub
Public Property sif_tvrtka() As Integer
Get
Return _sif_tvrtka
End Get
Set(ByVal value As Integer)
_sif_tvrtka = value
End Set
End Property
Public Property sif_radnika() As Integer
Get
Return _sif_radnika
End Get
Set(ByVal value As Integer)
_sif_radnika = value
End Set
End Property
Public Property red_broj() As Integer
Get
Return _red_broj
End Get
Set(ByVal value As Integer)
_red_broj = value
End Set
End Property
Public Property sif_ovl_osobe() As Integer
Get
Return _sif_ovl_osobe
End Get
Set(ByVal value As Integer)
_sif_ovl_osobe = value
End Set
End Property
Public Property datum_teorija() As Date
Get
Return _datum_teorija
End Get
Set(ByVal value As Date)
_datum_teorija = value
End Set
End Property
Public Property datum_praksa() As Date
Get
Return _datum_praksa
End Get
Set(ByVal value As Date)
_datum_praksa = value
End Set
End Property
Public Property prezime_ime() As String
Get
Return _prezime_ime
End Get
Set(ByVal value As String)
_prezime_ime = value
End Set
End Property
Public Property strucna_sprema() As String
Get
Return _strucna_sprema
End Get
Set(ByVal value As String)
_strucna_sprema = value
End Set
End Property
Public Property funkcija() As String
Get
Return _funkcija
End Get
Set(ByVal value As String)
_funkcija = value
End Set
End Property
Public Property status_obrasca() As Integer
Get
Return _status_obrasca
End Get
Set(ByVal value As Integer)
_status_obrasca = value
End Set
End Property
Public Property glavni_instruktor() As Integer
Get
Return _glavni_instruktor
End Get
Set(ByVal value As Integer)
_glavni_instruktor = value
End Set
End Property
Public Property instruktor_prezime() As String
Get
Return _instruktor_prezime
End Get
Set(ByVal value As String)
_instruktor_prezime = value
End Set
End Property
Public Property instruktor_sprema() As String
Get
Return _instruktor_sprema
End Get
Set(ByVal value As String)
_instruktor_sprema = value
End Set
End Property
Public Property instruktor_funkcija() As String
Get
Return _instruktor_funkcija
End Get
Set(ByVal value As String)
_instruktor_funkcija = value
End Set
End Property
Public Property evidencijski_broj() As String
Get
Return _evidencijski_broj
End Get
Set(ByVal value As String)
_evidencijski_broj = value
End Set
End Property
Public Property potvrda() As String
Get
Return _potvrda
End Get
Set(ByVal value As String)
_potvrda = value
End Set
End Property
And my second class in wich i want go get data from my first class look like:
Public Class TempEK1OsposTeorija
Private _sif_ovl_osobe As Integer
Private _datum_teorija As Date
Private _datum_praksa As Date
Private _prezime_ime As String
Private _strucna_sprema As String
Now i need to get data in Public Class TempEK1OsposTeorija form class Public Class ZnrEk1Ospos.
Does anybody know how to do that?
You need to create a new instance of that class
Public Class TempEK1OsposTeorija
Private _sif_ovl_osobe As Integer
Private _datum_teorija As Date
Private _datum_praksa As Date
Private _prezime_ime As String
Private _strucna_sprema As String
Public sub PozoviKlasuIvratiPodatke()
' To use the word using you must implement the IDisposable Interface into first class
Using cl as new ZnrEk1Ospos
'get data from first class
_sif_ovl_osobe = cl._sif_ovl_osobe
_datum_teorija = cl._datum_teorija
_datum_praksa = cl._datum_praksa
_prezime_ime = cl._prezime_ime
_strucna_sprema = cl._strucna_sprema
End using
End sub
End class

vb.net arraylist of objects

I am trying to create an arraylist of objects, and everything is working fine except that the value of all 11 objects are the same. I've have tried multiple ways of writing the code, but I get the same outcome everytime.
arrFullProdList collects the name of all the products in the database. This is working properly. arrProducts is where I am having the issue with all the objects being the same.
What am I doing wrong?
Declared
Private objReader As SqlDataReader
Private objProducts As New CProducts
Private arrFullProdList As ArrayList = New ArrayList
Public arrProdcuts As ArrayList = New ArrayList
class CProduct
Public Class CProduct
Private _pstrProdId As String
Private _pstrProdDesc As String
Private _psngWhCost As Single
Private _psngRetPrice As Single
Private _pblnTaxable As Boolean
Private _isNewProd As Boolean
Public Sub New()
'_pstrProdId = ""
'_pstrProdDesc = ""
'_psngWhCost = 0
'_psngRetPrice = 0
'_pblnTaxable = False
'_isNewProd = False
End Sub
Public Property strProdId() As String
Get
Return _pstrProdId
End Get
Set(strVal As String)
_pstrProdId = strVal
End Set
End Property
Public Property strProdDesc() As String
Get
Return _pstrProdDesc
End Get
Set(strVal As String)
_pstrProdDesc = strVal
End Set
End Property
Public Property sngWhCost() As Single
Get
Return _psngWhCost
End Get
Set(sngVal As Single)
_psngWhCost = sngVal
End Set
End Property
Public Property sngRetPrice() As Single
Get
Return _psngRetPrice
End Get
Set(sngVal As Single)
_psngRetPrice = sngVal
End Set
End Property
Public Property blnTaxable() As Boolean
Get
Return _pblnTaxable
End Get
Set(blnVal As Boolean)
_pblnTaxable = blnVal
End Set
End Property
Public Property IsNewProd() As Boolean
Get
Return _isNewProd
End Get
Set(blnVal As Boolean)
_isNewProd = blnVal
End Set
End Property
Public ReadOnly Property GetSaveParameters() As ArrayList
Get
Dim paramList As New ArrayList
paramList.Add(New SqlClient.SqlParameter("ProdId", _pstrProdId))
paramList.Add(New SqlClient.SqlParameter("ProdDesc", _pstrProdDesc))
paramList.Add(New SqlClient.SqlParameter("WhCost", _psngWhCost))
paramList.Add(New SqlClient.SqlParameter("RetPrice", _psngRetPrice))
paramList.Add(New SqlClient.SqlParameter("Taxable", _pblnTaxable))
Return paramList
End Get
End Property
Public Function Save() As Integer
'return -1 if the ID already exists and we can't create a new record
If _isNewProd Then
Dim strRes As String = myDB.GetSingleValueFromSP("sp_CheckProdIDExists", _
New SqlClient.SqlParameter("ProdId", _pstrProdId))
If Not strRes = 0 Then
Return -1 'ID NOT unique!!
End If
End If
'if not a new member or it is new and is unique, then do the save (update or insert)
Return myDB.ExecSP("sp_SaveProduct", GetSaveParameters)
End Function
End Class
class CProducts
Imports System.Data.SqlClient
Public Class CProducts
'This class represents the Members table and the associated business rules
Private _Product As CProduct
'constructor
Public Sub New()
'instantiate the CMember object
_Product = New CProduct
End Sub
Public ReadOnly Property CurrentObject() As CProduct
Get
Return _Product
End Get
End Property
Public Sub Clear()
_Product = New CProduct
End Sub
Public Sub CreateNewProduct() 'call me when you are clearing the screen to create a new member
Clear()
_Product.IsNewProd = True
End Sub
Public Function Save() As Integer
Return _Product.Save
End Function
Public Function GetProductList() As SqlDataReader
Return myDB.GetDataReaderBySP("dbo.sp_GetProductList")
End Function
Public Function GetProducIdList() As SqlDataReader
Return myDB.GetDataReaderBySP("dbo.sp_GetProductIdList")
End Function
Public Function GetProductByName(strProdDesc As String) As CProduct
Dim params As New ArrayList
Dim param1 As New SqlParameter("proddesc", strProdDesc)
params.Add(param1)
FillObject(myDB.GetDataReaderBySP("dbo.sp_GetProductByName", params))
Return _Product
End Function
Public Function GetProductById(strProdId As String) As CProduct
Dim aParam As New SqlParameter("ProdId", strProdId)
FillObject(myDB.GetDataReaderBySP("dbo.sp_GetProductByID", aParam))
Return _Product
End Function
Public Function FillObject(sqlDR As SqlDataReader) As CProduct
Using sqlDR
If sqlDR.Read Then
With _Product
.strProdId = sqlDR.Item("ProdId") & ""
.strProdDesc = sqlDR.Item("ProdDesc") & ""
.sngWhCost = sqlDR.Item("WhCost") & ""
.sngRetPrice = sqlDR.Item("RetPrice") & ""
.blnTaxable = sqlDR.Item("Taxable") & ""
End With
Else
'failed for some reason
End If
End Using
Return _Product
End Function
'----------Start Alex's Code---------
Public Function GetProductByDesc(strProdDesc As String) As SqlDataReader
Dim aParam As New SqlParameter("ProdDesc", strProdDesc)
Return myDB.GetDataReaderBySP("dbo.sp_GetProductByDesc", aParam)
End Function
End Class
main
Private Sub LoadProducts()
arrProdcuts.Clear()
objReader = objProducts.GetProductByDesc(txtSearch.Text)
While objReader.Read
arrFullProdList.Add(objReader.Item("prodDesc"))
End While
objReader.Close()
For i = 0 To arrFullProdList.Count - 1
Dim aNewProd As CProduct
aNewProd = objProducts.GetProductByName(arrFullProdList.Item(i).ToString)
arrProdcuts.Add(aNewProd)
Next
End Sub

Why does the combobox throws error when button associated with its event is clicked

Basic rundown of program: connected to a database. Combo box is populated with a terms list, after you select a term a get term button is pressed which populates a listview and then returns total balance due in a text box at the bottom of the form.
The Combobox populates, but when the btn is pressed catch ex throws an error along the lines of string cannot be converted to integer(occurs on the form design code). I'm not quite sure where I've gone wrong. It doesn't seem to catch anything else anywhere.
I'll include the code below
Imports Payables
Public Class Form1
Dim invoiceList As List(Of Invoices)
Dim termList As List(Of Terms)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
LoadComboBoxes()
End Sub
Private Sub LoadComboBoxes()
termList = TermsDB.GetTermsList
cboTerms.DataSource = termList
cboTerms.ValueMember = "TermsID"
cboTerms.DisplayMember = "Description"
End Sub
Private Sub btnGetInvoice_Click(sender As Object, e As EventArgs) Handles btnGetInvoice.Click
Dim invoiceList As List(Of Invoices)
Dim TermsID = CInt(cboTerms.SelectedValue)
Try
invoiceList = InvoicesDB.FindInvoiceByID(TermsID)
txtTotalBalanceDue.Text = FormatCurrency(InvoicesDB.GetBalanceDue())
If invoiceList.Count > 0 Then
Dim invoice As Invoices
For i = 0 To invoiceList.Count - 1
invoice = invoiceList(i)
lvInvoices.Items.Add(invoice.InvoiceID)
lvInvoices.Items(i).SubItems.Add(invoice.VendorID)
lvInvoices.Items(i).SubItems.Add(invoice.InvoiceNumber)
lvInvoices.Items(i).SubItems.Add(invoice.InvoiceDate)
lvInvoices.Items(i).SubItems.Add(invoice.InvoiceTotal)
lvInvoices.Items(i).SubItems.Add(invoice.PaymentTotal)
lvInvoices.Items(i).SubItems.Add(invoice.CreditTotal)
lvInvoices.Items(i).SubItems.Add(invoice.TermsID)
lvInvoices.Items(i).SubItems.Add(invoice.DueDate)
lvInvoices.Items(i).SubItems.Add(invoice.PaymentDate)
Next
Else
MessageBox.Show("There is no info on this account")
Me.Close()
End If
Catch ex As Exception
Throw ex
Me.Close()
End Try
End Sub
Private Sub btnExit_Click(sender As Object, e As EventArgs) Handles btnExit.Click
Me.Close()
End Sub
End Class
Public Class Invoices
Dim m_InvoiceID As Integer
Dim m_VendorID As Integer
Dim m_InvoiceNumber As String
Dim m_InvoiceDate As Date
Dim m_InvoiceTotal As Decimal
Dim m_PaymentTotal As Decimal
Dim m_CreditTotal As Decimal
Dim m_TermsID As Integer
Dim m_DueDate As Date
Dim m_PaymentDate As Date
Public Sub New()
End Sub
Public Property InvoiceID() As Integer
Get
Return m_InvoiceID
End Get
Set(value As Integer)
m_InvoiceID = value
End Set
End Property
Public Property VendorID() As Integer
Get
Return m_VendorID
End Get
Set(value As Integer)
m_VendorID = value
End Set
End Property
Public Property InvoiceNumber() As String
Get
Return m_InvoiceNumber
End Get
Set(value As String)
m_InvoiceNumber = value
End Set
End Property
Public Property InvoiceDate() As Date
Get
Return m_InvoiceDate
End Get
Set(value As Date)
m_InvoiceDate = value
End Set
End Property
Public Property InvoiceTotal() As Decimal
Get
Return m_InvoiceTotal
End Get
Set(value As Decimal)
m_InvoiceTotal = value
End Set
End Property
Public Property PaymentTotal() As Integer
Get
Return m_PaymentTotal
End Get
Set(value As Integer)
m_PaymentTotal = value
End Set
End Property
Public Property CreditTotal() As Integer
Get
Return m_CreditTotal
End Get
Set(value As Integer)
m_CreditTotal = value
End Set
End Property
Public Property TermsID() As Integer
Get
Return m_TermsID
End Get
Set(value As Integer)
m_TermsID = value
End Set
End Property
Public Property DueDate() As Date
Get
Return m_DueDate
End Get
Set(value As Date)
m_DueDate = value
End Set
End Property
Public Property PaymentDate() As Date
Get
Return m_PaymentDate
End Get
Set(value As Date)
m_PaymentDate = value
End Set
End Property
'Create a function BalanceDue to return the BalanceDue
Public Function GetBalanceDue() As Decimal
Return m_InvoiceTotal - m_PaymentTotal - m_CreditTotal
End Function
End Class
Imports System.Data.SqlClient
Public Class InvoicesDB
Public Shared Function FindInvoiceByID(ByVal TermsID) As List(Of Invoices)
Dim invoice As New Invoices
Dim connection As SqlConnection = PayablesDB.GetConnection
Dim invoiceList As New List(Of Invoices)
Dim selectStatement As String = "SELECT InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal,PaymentTotal,CreditTotal,TermsID,DueDate,PaymentDate FROM Invoices WHERE TermsID=#TermsID"
Dim selectCommand As New SqlCommand(selectStatement, connection)
'add the parameter to the parameter collection of the command object
selectCommand.Parameters.AddWithValue("#TermsID", TermsID)
Try
connection.Open()
Dim reader As SqlDataReader = selectCommand.ExecuteReader
If reader.Read Then
invoice.InvoiceID = CInt(reader("InvoiceID"))
invoice.VendorID = CInt(reader("VendorID"))
invoice.InvoiceNumber = CInt(reader("InvoiceNumber"))
invoice.InvoiceDate = CDate(reader("InvoiceDate"))
invoice.InvoiceTotal = CDec(reader("InvoiceTotal"))
invoice.PaymentTotal = CDec(reader("PaymentTotal"))
invoice.CreditTotal = CDec(reader("CreditTotal"))
invoice.TermsID = CInt(reader("TermsID"))
invoice.DueDate = CDate(reader("DueDate"))
invoice.PaymentDate = CDate(reader("PaymentDate"))
Else
'that means the invoice is not found
invoice = Nothing 'this means the vendor object no longer exists
End If
reader.Close()
connection.Close()
Catch ex As Exception
Throw ex
End Try
Return invoiceList
End Function
Public Shared Function GetBalanceDue() As Decimal 'aggregate
Dim connection As SqlConnection = PayablesDB.GetConnection
Dim selectCommand As New SqlCommand()
selectCommand.Connection = connection
selectCommand.CommandText =
"SELECT SUM(InvoiceTotal - PaymentTotal - CreditTotal) " &
"AS BalanceDue FROM Invoices" &
"WHERE TermsID=#TermsID"
connection.Open()
Dim balanceDue As Decimal = CDec(selectCommand.ExecuteScalar)
connection.Close()
Return balanceDue
End Function
End Class
Public Class Terms
Dim m_TermsID As Integer
Dim m_Description As String
Dim m_DueDays As Integer
Public Sub New()
End Sub
Public Property TermsID() As Integer
Get
Return m_TermsID
End Get
Set(ByVal value As Integer)
m_TermsID = value
End Set
End Property
Public Property Description() As String
Get
Return m_Description
End Get
Set(ByVal value As String)
m_Description = value
End Set
End Property
Public Property DueDays() As Integer
Get
Return m_DueDays
End Get
Set(ByVal value As Integer)
m_DueDays = value
End Set
End Property
End Class
Imports System.Data.SqlClient
Public Class TermsDB
Public Shared Function GetTermsList() As List(Of Terms)
Dim termList As New List(Of Terms)
Dim connection As SqlConnection = PayablesDB.GetConnection
Dim selectStatement As String =
"SELECT TermsID,Description,DueDays " &
"FROM Terms " &
"ORDER BY Description"
Dim selectCommand As New SqlCommand(selectStatement, connection)
Try
connection.Open()
Dim reader As SqlDataReader = selectCommand.ExecuteReader()
Dim term As Terms
Do While reader.Read
term = New Terms
term.TermsID = CInt(reader("TermsID"))
term.Description = reader("Description").ToString
term.DueDays = CInt(reader("DueDays"))
termList.Add(term)
Loop
reader.Close()
Catch ex As SqlException
Throw ex
Finally
connection.Close()
End Try
Return termList
End Function
End Class
I think your button is triggering the page load event, and you are losing the selected combobox value.
Do you have a text value as the first option in the combobox? That would cause the conversion error you're seeing.
Avoid binding the combobox on postback with something like
If ispostback = false Then
LoadComboBoxes()
End If

VB.NET Databinding Label not listening to PropertyChanged

I have a label which is databound to a Property in a Class which returns the highest number from another class. The numbers are filled into the other class from 6 text fields.
The 6 properties for the numbers all raise the PropertyChanged event when modified with the Parameter "BestThrow.Distance" as can be seen below:
Public Property Distance() As String
Get
If Status = ThrowStatus.Valid Then
If (m_Distance > 0) Then
Return m_Distance
Else
Return Nothing
End If
ElseIf Status = ThrowStatus.Pass Then
Return "PASS"
ElseIf Status = ThrowStatus.Foul Then
Return "FOUL"
Else
Return Nothing
End If
End Get
Set(value As String)
If (value.Length > 0) Then
If (IsNumeric(value)) Then
m_Distance = value
Status = ThrowStatus.Valid
ElseIf (value = "FOUL") Then
Status = ThrowStatus.Foul
ElseIf (value = "PASS") Then
Status = ThrowStatus.Pass
Else
Status = ThrowStatus.Valid
m_Distance = Nothing
End If
Else
m_Distance = Nothing
Status = ThrowStatus.Valid
End If
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("BestThrow.Distance"))
End Set
End Property
The Property which the label is bound to is as follows:
Public ReadOnly Property BestThrow() As Object
Get
Dim bt = Throws.Where(Function(t) t.Status = ThrowStatus.Valid).OrderByDescending(Function(t) t.Distance).First()
If (IsNothing(bt.Distance)) Then
bt.Distance = "0"
End If
Return bt
End Get
End Property
For the sake of providing all the information the Databinding for the label is as follows
best.DataBindings.Add(New Binding("text", athlete, "BestThrow.Distance", False, DataSourceUpdateMode.OnPropertyChanged))
When I add in the first Distance the label updates fine and displays Distance(0).Distance as expected, however when I change the other 5 values the label will not update. If, however, I then modify the first value again it will recalculate the BestThrow and display the correct distance.
I have also tried manually raising the event using a button on the form which also did not work.
From using watch values I can see that when requested the BestThrow Property is spitting out the correct values, it just seems the label only is interested in an event from the first Throw.
Thank you in advance for any assistance.
Current Code:
Imports System.ComponentModel
Imports System.Runtime.CompilerServices
Public Class Competition
Public Sub New()
Competitors = New List(Of Competitor)()
End Sub
Public Property Competitors() As List(Of Competitor)
Get
Return m_Competitors
End Get
Set(value As List(Of Competitor))
m_Competitors = value
End Set
End Property
Private m_Competitors As List(Of Competitor)
Public ReadOnly Property CurrentPlacings() As List(Of Competitor)
Get
Return Competitors.OrderByDescending(Function(c) c.BestThrow).ToList()
End Get
End Property
End Class
Public Class Competitor
Public Sub New()
Throws = New List(Of [Throw])()
End Sub
Public Property athletenum() As Integer
Get
Return m_athnum
End Get
Set(value As Integer)
m_athnum = value
End Set
End Property
Private m_Athnum As Integer
Public Property FirstName() As String
Get
Return m_FirstName
End Get
Set(value As String)
m_FirstName = value
End Set
End Property
Private m_FirstName As String
Public Property LastName() As String
Get
Return m_LastName
End Get
Set(value As String)
m_LastName = value
End Set
End Property
Private m_LastName As String
Public Property compNumber() As String
Get
Return m_compNumb
End Get
Set(value As String)
m_compNumb = value
End Set
End Property
Private m_compNumb As String
Public Property club() As String
Get
Return m_club
End Get
Set(value As String)
m_club = value
End Set
End Property
Private m_club As String
Public Property Throws() As List(Of [Throw])
Get
Return m_Throws
End Get
Set(value As List(Of [Throw]))
m_Throws = value
End Set
End Property
Private m_Throws As List(Of [Throw])
Public ReadOnly Property BestThrow() As String
Get
Dim list As IList(Of [Throw]) = (From t As [Throw] In Throws Select t Where t.Status = ThrowStatus.Valid Order By t.Distance Descending).ToList()
If (list.Count > 0) Then
If (IsNothing(list(0).Distance)) Then
Return "0"
Else
Return list(0).Distance
End If
End If
Return "0"
End Get
End Property
Public ReadOnly Property getLabel()
Get
Return compNumber & " " & LastName & ", " & FirstName & vbCrLf & club
End Get
End Property
Public Property currentPlace
Get
Return m_curplace
End Get
Set(value)
m_curplace = value
End Set
End Property
Private m_curplace As Integer
End Class
Public Enum ThrowStatus
Valid
Pass
Foul
End Enum
Public Class [Throw]
Implements INotifyPropertyChanged
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
'Throw Status
Public Property Status() As ThrowStatus
Get
Return m_Status
End Get
Set(value As ThrowStatus)
m_Status = value
End Set
End Property
Private m_Status As ThrowStatus
'Throw Distance
Public Property Distance() As String
Get
Dim value As String = Me.m_Distance
If Status = ThrowStatus.Valid Then
If (m_Distance > 0) Then
value = m_Distance
Else
value = Nothing
End If
ElseIf Status = ThrowStatus.Pass Then
value = "PASS"
ElseIf Status = ThrowStatus.Foul Then
value = "FOUL"
Else
value = Nothing
End If
If (value Me.m_Distance) Then
Me.Distance = value
End If
Return value
End Get
Set(value As String)
If (value.Length > 0) Then
If (IsNumeric(value)) Then
m_Distance = value
Status = ThrowStatus.Valid
ElseIf (value = "FOUL") Then
Status = ThrowStatus.Foul
ElseIf (value = "PASS") Then
Status = ThrowStatus.Pass
Else
Status = ThrowStatus.Valid
m_Distance = Nothing
End If
Else
m_Distance = Nothing
Status = ThrowStatus.Valid
End If
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("BestThrow"))
End Set
End Property
Private m_Distance As Decimal
Public Property attempt() As Integer
Get
Return m_attempt
End Get
Set(value As Integer)
m_attempt = value
End Set
End Property
Private m_attempt As Integer
End Class
Current binding:
best.DataBindings.Add(New Binding("text", athlete, "BestThrow", False, DataSourceUpdateMode.OnPropertyChanged))
First things first, I don't like seeing properties calculating the return value. I think this should be done in a method. (It might be okay in a read only property.) Just my opinion. What I find strange is that the getter for Distance depends on Status, and the setter acts more like a setter for Status.
Your binding expects a PropertyDescriptor named Distance. You return a String, and as you know the string class doesn't have a property named Distance.
best.DataBindings.Add(New Binding("text", athlete, "BestThrow.Distance", False, DataSourceUpdateMode.OnPropertyChanged))
Option 1
For this to work you'll need to do it like this:
Public ReadOnly Property BestThrow() As TYPE_OF_YOUR_CLASS
Get
'IMPORTANT:
'This approach requires at least ONE matching object and
'ONE item returned. If not, the binding will fail.
Return (From t As TYPE_OF_YOUR_CLASS In throws Select t Where t.Status = ThrowStatus.Valid Order By t.Distance Ascending).First()
End Get
End Property
Option 2
Another option is to just bind to the BestThrow property:
best.DataBindings.Add(New Binding("text", athlete, "BestThrow", False, DataSourceUpdateMode.OnPropertyChanged))
And change your property to this:
Public ReadOnly Property BestThrow() As String
Get
'NOTE:
'Do not use First() as this will fail if no matching items are found.
'We use ToList() and check the count property.
Dim list As IList(Of TYPE_OF_YOUR_CLASS) = (From t As TYPE_OF_YOUR_CLASS In throws Select t Where t.Status = ThrowStatus.Valid Order By t.Distance Ascending).ToList()
If (list.Count > 0) Then
Return list(0).Distance
End If
Return "0"
End Get
End Property
EDIT
To be honest I think this is bad designed. Please look in detail at this approach:
Public Class Athlete
'TODO: Implements INotifyPropertyChanged
Public Sub New(athleteNumber As Integer, Optional firstName As String = Nothing, Optional ByVal lastName As String = Nothing, Optional ByVal club As String = Nothing)
Me.m_athleteNumber = athleteNumber
Me.m_firstName = If((firstName Is Nothing), String.Empty, firstName)
Me.m_lastName = If((lastName Is Nothing), String.Empty, lastName)
Me.m_club = If((club Is Nothing), String.Empty, club)
End Sub
Public ReadOnly Property AthleteNumber() As Integer
Get
Return Me.m_athleteNumber
End Get
End Property
Public Property Club() As String
Get
Return Me.m_club
End Get
Set(value As String)
Me.m_club = value
'TODO: If changed raise property changed.
End Set
End Property
Public Property FirstName() As String
Get
Return Me.m_firstName
End Get
Set(value As String)
Me.m_firstName = value
'TODO: If changed raise property changed.
End Set
End Property
Public Property LastName() As String
Get
Return Me.m_lastName
End Get
Set(value As String)
Me.m_lastName = value
'TODO: If changed raise property changed.
End Set
End Property
Public Overrides Function ToString() As String
Return String.Concat(Me.m_firstName, " ", Me.m_lastName).Trim()
End Function
Private m_athleteNumber As Integer
Private m_club As String
Private m_firstName As String
Private m_lastName As String
End Class
Public Class Competitor
Implements INotifyPropertyChanged
Public Sub New(athlete As Athlete, Optional competitorNumber As String = Nothing)
If (athlete Is Nothing) Then
Throw New ArgumentNullException("athlete")
End If
Me.m_athlete = athlete
Me.m_bestThrow = 0D
Me.m_competitorNumber = If((competitorNumber Is Nothing), String.Empty, competitorNumber)
Me.m_curplace = 0
Me.m_throws = New ObjectCollection(Of [Throw])
AddHandler Me.m_throws.CollectionChanged, New CollectionChangeEventHandler(AddressOf Me.OnThrowCollectionChanged)
End Sub
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Public ReadOnly Property Athlete() As Athlete
Get
Return Me.m_athlete
End Get
End Property
Public ReadOnly Property BestThrow() As Decimal
Get
Return Me.m_bestThrow
End Get
End Property
Public Property CompetitorNumber() As String
Get
Return Me.m_competitorNumber
End Get
Set(value As String)
If (value <> Me.m_competitorNumber) Then
Me.m_competitorNumber = value
Me.RaisePropertyChanged("CompetitorNumber")
End If
End Set
End Property
Public Property CurrentPlace() As Integer
Get
Return Me.m_curplace
End Get
Set(value As Integer)
If (value <> Me.m_curplace) Then
Me.m_curplace = value
Me.RaisePropertyChanged("CurrentPlace")
End If
End Set
End Property
Public ReadOnly Property Throws() As ObjectCollection(Of [Throw])
Get
Return Me.m_throws
End Get
End Property
Protected Sub OnThrowCollectionChanged(sender As Object, e As CollectionChangeEventArgs)
Dim list As IList(Of [Throw]) = (From t As [Throw] In Me.m_throws Select t Where t.Status = ThrowStatus.Valid Order By t.Distance Descending).ToList()
Dim bestThrow As Decimal = If((list.Count > 0), list(0).Distance, 0D)
If (Me.m_bestThrow <> bestThrow) Then
Me.m_bestThrow = bestThrow
Me.RaisePropertyChanged("BestThrow")
End If
End Sub
Private Sub RaisePropertyChanged(propertyName As String)
If (Not Me.PropertyChangedEvent Is Nothing) Then
Me.PropertyChangedEvent.Invoke(Me, New PropertyChangedEventArgs(propertyName))
End If
End Sub
Private m_athlete As Athlete
Private m_bestThrow As Decimal
Private m_competitorNumber As String
Private m_curplace As Integer
Private m_throws As ObjectCollection(Of [Throw])
End Class
Public Class [Throw]
Public Sub New(Optional ByVal status As ThrowStatus = ThrowStatus.Valid, Optional distance As Decimal = 0D)
Me.m_status = status
Me.m_distance = Math.Max(distance, 0D)
End Sub
Public ReadOnly Property Status() As ThrowStatus
Get
Return Me.m_status
End Get
End Property
Public ReadOnly Property Distance() As Decimal
Get
Return Me.m_distance
End Get
End Property
Public Overrides Function ToString() As String
Select Case Me.m_status
Case ThrowStatus.Valid
Return Me.m_distance.ToString("N2")
Case ThrowStatus.Pass
Return "PASS"
Case ThrowStatus.Foul
Return "FOUL"
Case Else
Return 0D.ToString("N2")
End Select
End Function
Private m_attempt As Integer
Private m_distance As Decimal
Private m_status As ThrowStatus
End Class
Public Class ObjectCollection(Of T)
Inherits Collections.ObjectModel.Collection(Of T)
Public Event CollectionChanged As CollectionChangeEventHandler
Protected Overrides Sub ClearItems()
MyBase.ClearItems()
Me.RaiseCollectionChanged(CollectionChangeAction.Refresh, Nothing)
End Sub
Protected Overrides Sub InsertItem(index As Integer, item As T)
If (item Is Nothing) Then
Throw New ArgumentNullException("item")
ElseIf (Me.Contains(item)) Then
Throw New ArgumentException("Item duplicate.", "item")
End If
MyBase.InsertItem(index, item)
Me.RaiseCollectionChanged(CollectionChangeAction.Add, item)
End Sub
Protected Overridable Sub OnCollectionChanged(e As CollectionChangeEventArgs)
If (Not Me.CollectionChangedEvent Is Nothing) Then
Me.CollectionChangedEvent.Invoke(Me, e)
End If
End Sub
Private Sub RaiseCollectionChanged(action As CollectionChangeAction, item As T)
Me.OnCollectionChanged(New CollectionChangeEventArgs(action, item))
End Sub
Protected Overrides Sub RemoveItem(index As Integer)
Dim item As T = Me.Item(index)
MyBase.RemoveItem(index)
Me.RaiseCollectionChanged(CollectionChangeAction.Remove, item)
End Sub
Protected Overrides Sub SetItem(index As Integer, item As T)
Throw New NotSupportedException()
End Sub
End Class
Public Enum ThrowStatus As Integer
Valid = 0 '<- This is the default value.
Pass = 1
Foul = 2
End Enum
The following code are tested and works. Drop a Button and a TextBox onto a Form and append:
Public Class Form1
Public Sub New()
Me.InitializeComponent()
Me.competitor = New Competitor(New Athlete(1, "John", "Smith", "Team JS"), "CP_1")
Me.competitor.Throws.Add(New [Throw](distance:=123.3472D))
Me.competitor.Throws.Add(New [Throw](distance:=424.1234D))
Me.competitor.Throws.Add(New [Throw](distance:=242.1234D))
Dim b As New Binding("Text", Me.competitor, "BestThrow", True, DataSourceUpdateMode.Never)
AddHandler b.Format, New ConvertEventHandler(AddressOf Me._FormatBinding)
Me.TextBox1.DataBindings.Add(b)
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Me.competitor.Throws.Add(New [Throw](distance:=845.4365D))
End Sub
Private Sub _FormatBinding(sender As Object, e As ConvertEventArgs)
If ((TypeOf e.Value Is Decimal) AndAlso (e.DesiredType Is GetType(String))) Then
e.Value = CDec(e.Value).ToString("N2")
End If
End Sub
Private competitor As Competitor
End Class