VB.NET Databinding Label not listening to PropertyChanged - vb.net

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

Related

DataGridView ComboBox column that will accept any text - Dropdown populated by Column

https://stackoverflow.com/a/59545459/20359642
Hi, on the article above, I grabbed the code snippet from Sidupac. This class works but it has a different drop down list for each row. I want each row to be populated with the same list. I am not very good at classes, can someone please help? My goal is to be able to add a column to a DataGridView that will act as a combobox but also accepts manual text input as well.
Public Class DataGridViewDropDownComboBoxColumn
Inherits DataGridViewColumn
Public Sub New()
MyBase.New(New DataGridViewDropDownComboBoxCell)
End Sub
Public Property DropDownStyle As ComboBoxStyle
Public Property DataSource As Object
Public Property ValueMember As Object
Public Property DisplayMember As Object
Public Overrides Property CellTemplate As DataGridViewCell
Get
Return MyBase.CellTemplate
End Get
Set
' Ensure that the cell used for the template is a DataGridViewDropDownComboBoxCell.
If ((Not (Value) Is Nothing) AndAlso Not Value.GetType.IsAssignableFrom(GetType(DataGridViewDropDownComboBoxCell))) Then
Throw New InvalidCastException("Must be a DropDownCell")
End If
MyBase.CellTemplate = Value
End Set
End Property
End Class
Public Class DataGridViewDropDownComboBoxCell
Inherits DataGridViewTextBoxCell
Public Sub New()
MyBase.New
End Sub
Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, ByVal initialFormattedValue As Object, ByVal dataGridViewCellStyle As DataGridViewCellStyle)
' Set the value of the editing control to the current cell value.
MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle)
Dim ctl As DataGridViewDropDownComboBoxEditingControl = CType(DataGridView.EditingControl, DataGridViewDropDownComboBoxEditingControl)
' Use the default row value when Value property is null.
If (Me.Value Is Nothing) Or IsDBNull(Me.Value) Then
ctl.Text = CType(Me.DefaultNewRowValue, String)
Else
ctl.Text = CType(Me.Value, String)
End If
'ctl.BringToFront()
'ctl.Focus()
'ctl.DroppedDown = True
End Sub
Public Overrides ReadOnly Property EditType As Type
Get
' Return the type of the editing control that DataGridViewDropDownComboBoxCell uses.
Return GetType(DataGridViewDropDownComboBoxEditingControl)
End Get
End Property
Public Overrides ReadOnly Property ValueType As Type
Get
' Return the type of the value that DataGridViewDropDownComboBoxCell contains.
Return GetType(String)
End Get
End Property
Public Overrides ReadOnly Property DefaultNewRowValue As Object
Get
' Use the current date and time as the default value.
Return ""
End Get
End Property
End Class
Class DataGridViewDropDownComboBoxEditingControl
Inherits ComboBox
Implements IDataGridViewEditingControl
Private dataGridView As DataGridView
Private valueChanged As Boolean = False
Private rowIndex As Integer
Public Sub New()
MyBase.New
End Sub
Public Shadows Property DropDownStyle() As ComboBoxStyle
Get
Return MyBase.DropDownStyle
End Get
Set(ByVal value As ComboBoxStyle)
If value = ComboBoxStyle.Simple Then
'Throw New NotSupportedException("ComboBoxStyle.Simple not supported")
value = ComboBoxStyle.DropDown
End If
MyBase.DropDownStyle = value
End Set
End Property
' Implements the IDataGridViewEditingControl.EditingControlFormattedValue
' property.
Public Property EditingControlFormattedValue As Object Implements IDataGridViewEditingControl.EditingControlFormattedValue
Get
Return Me.Text
End Get
Set
If (TypeOf Value Is String) Then
Me.Text = CStr(Value)
End If
End Set
End Property
' Implements the
' IDataGridViewEditingControl.GetEditingControlFormattedValue method.
Public Function GetEditingControlFormattedValue(ByVal context As DataGridViewDataErrorContexts) As Object Implements IDataGridViewEditingControl.GetEditingControlFormattedValue
Return Me.EditingControlFormattedValue
End Function
' Implements the
' IDataGridViewEditingControl.ApplyCellStyleToEditingControl method.
Public Sub ApplyCellStyleToEditingControl(ByVal dataGridViewCellStyle As DataGridViewCellStyle) Implements IDataGridViewEditingControl.ApplyCellStyleToEditingControl
Me.Font = dataGridViewCellStyle.Font
Me.ForeColor = dataGridViewCellStyle.ForeColor
Me.BackColor = dataGridViewCellStyle.BackColor
End Sub
' Implements the IDataGridViewEditingControl.EditingControlRowIndex
' property.
Public Property EditingControlRowIndex As Integer Implements IDataGridViewEditingControl.EditingControlRowIndex
Get
Return Me.rowIndex
End Get
Set
Me.rowIndex = Value
End Set
End Property
' Implements the IDataGridViewEditingControl.EditingControlWantsInputKey
' method.
Public Function EditingControlWantsInputKey(ByVal key As Keys, ByVal dataGridViewWantsInputKey As Boolean) As Boolean Implements IDataGridViewEditingControl.EditingControlWantsInputKey
' Let the DateTimePicker handle the keys listed.
Select Case ((key And Keys.KeyCode))
Case Keys.Left, Keys.Up, Keys.Down, Keys.Right, Keys.Home, Keys.End, Keys.PageDown, Keys.PageUp, Keys.F4
Return True
Case Else
Return Not dataGridViewWantsInputKey
End Select
End Function
' Implements the IDataGridViewEditingControl.PrepareEditingControlForEdit
' method.
Public Sub PrepareEditingControlForEdit(ByVal selectAll As Boolean) Implements IDataGridViewEditingControl.PrepareEditingControlForEdit
Dim col As DataGridViewDropDownComboBoxColumn = CType(dataGridView.Columns(dataGridView.CurrentCell.ColumnIndex), DataGridViewDropDownComboBoxColumn)
If (col Is Nothing) Then
Throw New InvalidCastException("Must be in a DropDownComboBoxColumn")
End If
DropDownStyle = col.DropDownStyle
Items.Clear()
If IsDBNull(dataGridView.CurrentCell.Value) Then
Text = ""
Else
Text = CType(dataGridView.CurrentCell.Value, String)
End If
Items.Add(Text)
Dim dt As DataTable = New DataTable
Dim ct As Integer = 0, cx As Integer = 0
Try
dt = DirectCast(col.DataSource, DataTable)
If Not col.DisplayMember Is Nothing Then
For Each c As DataColumn In dt.Columns
If c.ColumnName Is col.DisplayMember Then
cx = ct
End If
ct += 1
Next
End If
For Each r As DataRow In dt.Rows
If Not col.DisplayMember Is Nothing Then
If Not Items.Contains(r(cx)) Then Items.Add(r(cx))
Else
If dt.Columns.Count = 1 Then
If Not Items.Contains(r(0)) Then Items.Add(r(0))
Else
If Not Items.Contains(r(dt.Columns.Count - 1)) Then Items.Add(r(dt.Columns.Count - 1))
End If
End If
Next
Catch ex As Exception
End Try
'DropDownStyle = col.DropDownStyle
'ValueMember = col.ValueMember
'DisplayMember = col.DisplayMember
'DataSource = col.DataSource
' (If you don't explicitly set the Text then the current value is
' always replaced with one from the drop-down list when edit begins.)
'If IsDBNull(dataGridView.CurrentCell.Value) Then
' Text = ""
'Else
' Text = CType(dataGridView.CurrentCell.Value, String)
'End If
End Sub
' Implements the IDataGridViewEditingControl
' .RepositionEditingControlOnValueChange property.
Public ReadOnly Property RepositionEditingControlOnValueChange As Boolean Implements IDataGridViewEditingControl.RepositionEditingControlOnValueChange
Get
Return False
End Get
End Property
' Implements the IDataGridViewEditingControl
' .EditingControlDataGridView property.
Public Property EditingControlDataGridView As DataGridView Implements IDataGridViewEditingControl.EditingControlDataGridView
Get
Return Me.dataGridView
End Get
Set
Me.dataGridView = Value
End Set
End Property
' Implements the IDataGridViewEditingControl
' .EditingControlValueChanged property.
Public Property EditingControlValueChanged As Boolean Implements IDataGridViewEditingControl.EditingControlValueChanged
Get
Return Me.valueChanged
End Get
Set
Me.valueChanged = Value
End Set
End Property
' Implements the IDataGridViewEditingControl
' .EditingPanelCursor property.
Public ReadOnly Property EditingPanelCursor As Cursor Implements IDataGridViewEditingControl.EditingPanelCursor
Get
Return MyBase.Cursor
End Get
End Property
Protected Overrides Sub OnTextChanged(ByVal eventargs As EventArgs)
' Notify the DataGridView that the contents of the cell
' have changed.
Me.valueChanged = True
Me.EditingControlDataGridView.NotifyCurrentCellDirty(True)
MyBase.OnTextChanged(eventargs)
End Sub
Protected Overrides Sub OnSelectedIndexChanged(ByVal e As EventArgs)
' Notify the DataGridView that the contents of the cell
' have changed.
Me.valueChanged = True
Me.EditingControlDataGridView.NotifyCurrentCellDirty(True)
MyBase.OnSelectedIndexChanged(e)
End Sub
End Class
I've tried messing around with the class myself but I just cant seem to figure it out.
I actually figured it out. The DataSource was not populating the dropdowns because I was not giving it a DataTable to reference. I was giving it a string array. I just need to alter the class a bit to handle different types of inputs for the DataSource.
For example, I changed the code inside of the try statement in the PrepareEditingControlForEdit procedure to the code below:
If TypeOf col.DataSource Is String Then
Items.Add(col.DataSource)
ElseIf TypeOf col.DataSource Is String() Then
For Each obj As Object In DirectCast(col.DataSource, String())
Items.Add(obj)
Next
ElseIf TypeOf col.DataSource Is List(Of String) Then
For Each obj As String In DirectCast(col.DataSource, List(Of String))
Items.Add(obj)
Next
ElseIf TypeOf col.DataSource Is List(Of Object) Then
For Each obj As String In DirectCast(col.DataSource, List(Of Object))
Items.Add(obj)
Next
ElseIf TypeOf col.DataSource Is DataTable Then
dt = DirectCast(col.DataSource, DataTable)
If Not col.DisplayMember Is Nothing Then
For Each c As DataColumn In dt.Columns
If c.ColumnName Is col.DisplayMember Then
cx = ct
End If
ct += 1
Next
End If
For Each r As DataRow In dt.Rows
If Not col.DisplayMember Is Nothing Then
If Not Items.Contains(r(cx)) Then Items.Add(r(cx))
Else
If dt.Columns.Count = 1 Then
If Not Items.Contains(r(0)) Then Items.Add(r(0))
Else
If Not Items.Contains(r(dt.Columns.Count - 1)) Then Items.Add(r(dt.Columns.Count - 1))
End If
End If
Next
End If

How to assign typical NumericUpDown properties to custom NumericUpDown based control?

I'm trying to make a DataGridViewColumn that inherits all of the properties of a typical NumericUpDown control. I found an answer here on StackOverflow (https://stackoverflow.com/a/55788490/692250) and a MSDN article here (https://learn.microsoft.com/en-us/dotnet/desktop/winforms/controls/how-to-host-controls-in-windows-forms-datagridview-cells?view=netframeworkdesktop-4.8&redirectedfrom=MSDN#code-snippet-1).
The code from the article works well, but... I cannot assign a Maximum nor Minimum value to the control (both are stuck at the "default" Minimum of 0 and Maximum of 100).
I tried to add in code from the SO answer (by adding in a Min and Max field) but doing so locks both in to 0 and unable to change.
The question in short: how do I add the necessary properties to allow to this work.
The custom control is question:
Public Class NumericUpDownColumn
Inherits DataGridViewColumn
Public Sub New()
MyBase.New(New NumericUpDownCell())
End Sub
Public Overrides Property CellTemplate() As DataGridViewCell
Get
Return MyBase.CellTemplate
End Get
Set(ByVal value As DataGridViewCell)
' Ensure that the cell used for the template is a CalendarCell.
If Not (value Is Nothing) AndAlso Not value.GetType().IsAssignableFrom(GetType(NumericUpDownCell)) Then
Throw New InvalidCastException("Must be an Integer")
End If
MyBase.CellTemplate = value
End Set
End Property
End Class
Public Class NumericUpDownCell
Inherits DataGridViewTextBoxCell
Public Sub New()
' Number Format
Me.Style.Format = "0"
End Sub
Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, ByVal initialFormattedValue As Object, ByVal dataGridViewCellStyle As DataGridViewCellStyle)
' Set the value of the editing control to the current cell value.
MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle)
Dim ctl As NumericUpDownEditingControl = CType(DataGridView.EditingControl, NumericUpDownEditingControl)
ctl.Value = CType(Me.Value, Decimal)
End Sub
Public Overrides ReadOnly Property EditType() As Type
Get
' Return the type of the editing contol that CalendarCell uses.
Return GetType(NumericUpDownEditingControl)
End Get
End Property
Public Overrides ReadOnly Property ValueType() As Type
Get
' Return the type of the value that CalendarCell contains.
Return GetType(Decimal)
End Get
End Property
Public Overrides ReadOnly Property DefaultNewRowValue() As Object
Get
' Use the current date and time as the default value.
Return 0
End Get
End Property
End Class
Class NumericUpDownEditingControl
Inherits NumericUpDown
Implements IDataGridViewEditingControl
Private dataGridViewControl As DataGridView
Private valueIsChanged As Boolean = False
Private rowIndexNum As Integer
Public Sub New()
Me.DecimalPlaces = 0
End Sub
Public Property EditingControlFormattedValue() As Object Implements IDataGridViewEditingControl.EditingControlFormattedValue
Get
Return Me.Value.ToString("#")
End Get
Set(ByVal value As Object)
If TypeOf value Is Decimal Then
Me.Value = Decimal.Parse(value.ToString)
End If
End Set
End Property
Public Function GetEditingControlFormattedValue(ByVal context As DataGridViewDataErrorContexts) As Object Implements IDataGridViewEditingControl.GetEditingControlFormattedValue
Return Me.Value.ToString("#")
End Function
Public Sub ApplyCellStyleToEditingControl(ByVal dataGridViewCellStyle As DataGridViewCellStyle) Implements IDataGridViewEditingControl.ApplyCellStyleToEditingControl
Me.Font = dataGridViewCellStyle.Font
Me.ForeColor = dataGridViewCellStyle.ForeColor
Me.BackColor = dataGridViewCellStyle.BackColor
End Sub
Public Property EditingControlRowIndex() As Integer Implements IDataGridViewEditingControl.EditingControlRowIndex
Get
Return rowIndexNum
End Get
Set(ByVal value As Integer)
rowIndexNum = value
End Set
End Property
Public Function EditingControlWantsInputKey(ByVal key As Keys, ByVal dataGridViewWantsInputKey As Boolean) As Boolean Implements IDataGridViewEditingControl.EditingControlWantsInputKey
' Let the DateTimePicker handle the keys listed.
Select Case key And Keys.KeyCode
Case Keys.Left, Keys.Up, Keys.Down, Keys.Right, Keys.Home, Keys.End, Keys.PageDown, Keys.PageUp
Return True
Case Else
Return False
End Select
End Function
Public Sub PrepareEditingControlForEdit(ByVal selectAll As Boolean) Implements IDataGridViewEditingControl.PrepareEditingControlForEdit
' No preparation needs to be done.
End Sub
Public ReadOnly Property RepositionEditingControlOnValueChange() As Boolean Implements IDataGridViewEditingControl.RepositionEditingControlOnValueChange
Get
Return False
End Get
End Property
Public Property EditingControlDataGridView() As DataGridView Implements IDataGridViewEditingControl.EditingControlDataGridView
Get
Return dataGridViewControl
End Get
Set(ByVal value As DataGridView)
dataGridViewControl = value
End Set
End Property
Public Property EditingControlValueChanged() As Boolean Implements IDataGridViewEditingControl.EditingControlValueChanged
Get
Return valueIsChanged
End Get
Set(ByVal value As Boolean)
valueIsChanged = value
End Set
End Property
Public ReadOnly Property EditingControlCursor() As Cursor Implements IDataGridViewEditingControl.EditingPanelCursor
Get
Return MyBase.Cursor
End Get
End Property
Protected Overrides Sub OnValueChanged(ByVal eventargs As EventArgs)
' Notify the DataGridView that the contents of the cell have changed.
valueIsChanged = True
Me.EditingControlDataGridView.NotifyCurrentCellDirty(True)
MyBase.OnValueChanged(eventargs)
End Sub
End Class
Focusing on it a bit more, I found that I can assign values to the Maximum and Minimum fields as so:
' Set the value of the editing control to the current cell value.
MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle)
Dim ctl As NumericUpDownEditingControl = CType(DataGridView.EditingControl, NumericUpDownEditingControl)
ctl.Value = CType(Me.Value, Decimal)
ctl.Maximum = 180
ctl.Minimum = -1
End Sub
But I cannot seem to pass to this field via the usual means of .Maximum or .Minimum on the constructor. Any tips/advice?
This is an easy fix and very easy to overlook.
In your NumericUpDownCell class you need to override the Clone method to include the new Minimum and Maximum properties, for example:
First, add the new properties the NumericUpDownCell class and then override the Clone function
Public Class NumericUpDownCell
Inherits DataGridViewTextBoxCell
...
Public Property Minimum() As Integer
Public Property Maximum() As Integer
...
Public Overrides Function Clone() As Object
Dim retVal As NumericUpDownCell = CType(MyBase.Clone, NumericUpDownCell)
retVal.Minimum = Me.Minimum
retVal.Maximum = Me.Maximum
Return retVal
End Function
End Class
Second, inside the NumericUpDownCell classes InitializeEditingControl method, add the two lines:
ctl.Minimum = Me.Minimum
ctl.Maximum = Me.Maximum
When you setup the new column, get the CellTemplate to set the new properties, as per:
Dim upDownColumn As New NumericUpDownColumn
Dim cellTemplate As NumericUpDownCell = CType(upDownColumn .CellTemplate, NumericUpDownCell)
cellTemplate.Minimum = 10
cellTemplate.Maximum = 15
Or, following you preference to setup via the constructor, add a new constructor to the NumericUpdDownColumn class as per
Public Sub New(minValue As Integer, maxValue As Integer)
MyBase.New(New NumericUpDownCell())
Dim template As NumericUpDownCell = CType(CellTemplate, NumericUpDownCell)
template.Minimum = minValue
template.Maximum = maxValue
End Sub
and then use it like:
Dim upDownColumn As New NumericUpDownColumn(100, 150)
Dim cellTemplate As NumericUpDownCell = CType(upDownColumn.CellTemplate, NumericUpDownCell)
DataGridView1.Columns.Add(upDownColumn)

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 Databound Label not updating

I am having issues with a label with a databound text value updating. I have a Class that calculates the best throw of an athlete and this is bound to a label in my form. The class is as follows
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
Implements System.ComponentModel.INotifyPropertyChanged
Public Event PropertyChanged(sender As Object,
e As System.ComponentModel.PropertyChangedEventArgs) _
Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
Public Sub New()
Throws = New List(Of [Throw])()
End Sub
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 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
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("BestThrow"))
Return bt
End Get
End Property
Public ReadOnly Property getLabel
Get
Return compNumber & " " & LastName & ", " & FirstName & vbCrLf & club
End Get
End Property
End Class
Public Enum ThrowStatus
Valid
Pass
Foul
End Enum
Public Class [Throw]
Implements INotifyPropertyChanged
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
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
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 > 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
OnPropertyChanged("Distance")
End Set
End Property
Protected Sub OnPropertyChanged(ByVal name As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(name))
End Sub
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
The line that databinds for the Label is as follows:
best.DataBindings.Add(New Binding("text", athlete.BestThrow, "distance", False, DataSourceUpdateMode.OnPropertyChanged))
I can tell that the Property BestThrow is defintely being updated using Watch however for some reason the label seems to only reflect Throw(0).Distance and not BestThrow.Distance
I can change Throw(0) and the label will change, if I add a bigger number to any of the other 5 attempts and Watch the value I can see that the BestThrow is being updated.
Thanks in advance for your assistance.
Mark
I think you have a wrong prespective, property BestThrow is never updated because it has no setter. When you check BestThrow value using watch, it 'recalculated' because you request the value. What you need is to find a way to raise Property Changed event for BestThrow whenever item added or removed from Throws because BestThrow value depends on Throws. After event raised, UI will call BestThrow's getter again looking for updated value.
'You need to execute this code to notify UI that `BestThrow` value has changed
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("BestThrow"))
Raisng the event can be done manually after code for adding/removing item to/from Throws property, or you can make Throws an ObservableCollection of Throw then listen to Collection Changed event. Then in the event handler you can raise BestThrow property changed event.

Find an existing item in an item collection

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.