Link to home
Start Free TrialLog in
Avatar of pamsauto
pamsauto

asked on

Need help understanding how to use IEnumable in custom class

I need help understanding how to use a custom class I have so I can bind it to a datagridview and allow the user to click a header to sort the data.

The first code chuck is the existing class.

I have a windows form with a DataGridView on it that is bound to the object.  I then call this from from another form. The datagridview form code is here.

 Public Sub New(ByVal rtqRates() As RateQuoteType, ByVal frmTitle As String)

        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        DataGridView1.DataSource = rtqRates
        Me.Text = frmTitle

    End Sub

The second chunk of code is what I believe I need to incorborate into the class, but am really lost on how to structure this, where it goes in the class, and how to make the datagrid view use the functionality.  This code does have a few bugs in it I believe.

Thanks for any help in advance!


Imports Microsoft.VisualBasic
Imports System.Data
Imports System
Imports System.Collections
Imports System.ComponentModel
Imports System.Reflection

Public Class RateQuoteType



    <EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)> Protected _Rate As Decimal
    <EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)> Protected _DayInTransitMin As Integer
    <EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)> Protected _DayInTransitMax As Integer
    <EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)> Protected _Name As String
    <EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)> Protected _ServiceDescription As String
    <EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)> Protected _Surcharges As String
    <EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)> Protected _Description As String
    <EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)> Protected _RateBasedOnHistory As Boolean = False




    ''' <summary>
    ''' RateQuoteType is an object to hold a quoted rate for shipping a product(s) to a destination 
    ''' Use the rate quoting classes to fill this type
    ''' </summary>
    ''' <param name="Rate">The rate to use in calculations</param>
    ''' <param name="DaysInTransitMin">If provided by the rating engine the shortest days until the product will be delivered, do not include time spent prepping the shipment or waiting for end terminal delivery to the customer</param>
    ''' <param name="DaysInTransitMax">If provided by the rating engine the maximium days until the product will be delivered, do not include time spent prepping the shipment or waiting for end terminal delivery to the customer</param>
    ''' <param name="Name">The name of the Service - Usually like UPS, Speedee, Etc</param>
    ''' <param name="ServiceDescription">Usually the description of the service - examples ; Next Day Air ; Ground </param>
    ''' <param name="Surcharges">A text description of surcharges that the carrier may apply - examples ; COD add $10.00 ; Residential add $10.00</param>
    ''' <param name="Description">Another field to add more text for the descrion to the user - this is the lowest priority in displaying</param>
    ''' <param name="RateBasedOnShipmentHistory">If this quote was generated with some type of weight or dimension history set to true</param>
    ''' <remarks></remarks>
    Public Sub New(ByVal Rate As Decimal, ByVal DaysInTransitMin As Integer, ByVal DaysInTransitMax As Integer, ByVal Name As String, ByVal ServiceDescription As String, ByVal Surcharges As String, ByVal Description As String, ByVal RateBasedOnShipmentHistory As Boolean)
        Me._Rate = Rate
        Me._DayInTransitMin = DaysInTransitMin
        Me._DayInTransitMax = DaysInTransitMax
        Me._Name = Name
        Me._ServiceDescription = ServiceDescription
        Me._Surcharges = Surcharges
        Me._Description = Description
        Me._RateBasedOnHistory = RateBasedOnShipmentHistory
    End Sub

    ''' <summary>
    ''' This is the cost of the rate quote for the delivery method
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Property Rate As Decimal
        Get
            Return _Rate
        End Get
        Set(ByVal value As Decimal)
            _Rate = value
        End Set
    End Property
    ''' <summary>
    ''' This is the top level Name of the Delivery Method
    ''' There are three levels total
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Property Name As String
        Get
            Return _Name
        End Get
        Set(ByVal value As String)
            _Name = value
        End Set
    End Property
    ''' <summary>
    ''' This is the second level Name of th Delivery Method
    ''' There are three levels total
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Property ServiceDescription As String
        Get
            Return _ServiceDescription
        End Get
        Set(ByVal value As String)
            _ServiceDescription = value
        End Set
    End Property
    ''' <summary>
    ''' This is a string of what surcharges the user needs
    ''' to be aware of for this rate quote
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Property Surcharges As String
        Get
            Return _Surcharges
        End Get
        Set(ByVal value As String)
            _Surcharges = value
        End Set
    End Property
    ''' <summary>
    ''' This is the third level Name of th Delivery Method
    ''' There are three levels total
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Property Description As String
        Get
            Return _Description
        End Get
        Set(ByVal value As String)
            _Description = value
        End Set
    End Property
    ''' <summary>
    ''' The Mininium Full Business Days it will take to get the product to the customer after it is shipped
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Property DaysInTransitMin As Integer
        Get
            Return _DayInTransitMin
        End Get
        Set(ByVal value As Integer)
            _DayInTransitMin = value
        End Set
    End Property
    ''' <summary>
    ''' The Maximium Full Business Days it will take to get the product to the customer after it is shipped
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Property DaysInTransitMax As Integer
        Get
            Return _DayInTransitMax
        End Get
        Set(ByVal value As Integer)
            _DayInTransitMax = value
        End Set
    End Property

    ''' <summary>
    ''' If this rate quote was made with shipment size and weight history set this var to true
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Property RateBasedOnHistory As Boolean
        Get
            Return _RateBasedOnHistory
        End Get
        Set(ByVal value As Boolean)
            _RateBasedOnHistory = value
        End Set
    End Property

End Class

Public Class RateQuote

#Region "Rate Quotes"

    Implements IEnumerable

    Private _RateQuotes() As RateQuoteType



    Public Function GetEnumerator() As IEnumerator _
        Implements IEnumerable.GetEnumerator
        Return New RateQuoteEnum(_RateQuotes)
    End Function
#End Region

End Class

Public Class RateQuoteEnum

    Implements IEnumerator
    Public _RateEnum() As RateQuoteType
    Dim position As Integer = -1

    Public Sub New(ByVal list() As RateQuoteType)
        _RateEnum = list
    End Sub

    Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
        position = position + 1
        Return (position < _RateEnum.Length)
    End Function

    Public Sub Reset() Implements IEnumerator.Reset
        position = -1
    End Sub

    Public ReadOnly Property Current() As Object Implements IEnumerator.Current
        Get
            Try
                Return _RateEnum(position)
            Catch ex As IndexOutOfRangeException
                Throw New InvalidOperationException()
            End Try
        End Get
    End Property

End Class

Open in new window

Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Text
Imports System.Windows.Forms
Imports System.Reflection
Imports System.Collections

Namespace SomethingSomething
	''' <summary> 
	''' Supports sorting of list in data grid view. 
	''' </summary> 
	''' <typeparam name="T">Type of object to be displayed in data grid view.</typeparam> 
	Public Class SortableSearchableList(Of T)
		Inherits BindingList(Of T)
		#Region "Data Members"

		Private _sortDirectionValue As ListSortDirection
		Private _sortPropertyValue As PropertyDescriptor = Nothing

		''' <summary> 
		''' Dictionary from property name to custom comparison function. 
		''' </summary> 
		Private _customComparisons As New Dictionary(Of String, Comparison(Of T))()

		#End Region

		#Region "Constructors"

		''' <summary> 
		''' Default constructor. 
		''' </summary> 
		Public Sub New()
		End Sub

		#End Region

		#Region "Properties"

		''' <summary> 
		''' Indicates if sorting is supported. 
		''' </summary> 
		Protected Overrides ReadOnly Property SupportsSortingCore() As Boolean
			Get
				Return True
			End Get
		End Property

		''' <summary> 
		''' Indicates if list is sorted. 
		''' </summary> 
		Protected Overrides ReadOnly Property IsSortedCore() As Boolean
			Get
				Return _sortPropertyValue IsNot Nothing
			End Get
		End Property

		''' <summary> 
		''' Indicates which property the list is sorted. 
		''' </summary> 
		Protected Overrides ReadOnly Property SortPropertyCore() As PropertyDescriptor
			Get
				Return _sortPropertyValue
			End Get
		End Property

		''' <summary> 
		''' Indicates in which direction the list is sorted on. 
		''' </summary> 
		Protected Overrides ReadOnly Property SortDirectionCore() As ListSortDirection
			Get
				Return _sortDirectionValue
			End Get
		End Property

		#End Region

		#Region "Methods"

		''' <summary> 
		''' Add custom compare method for property. 
		''' </summary> 
		''' <param name="propertyName"></param> 
		''' <param name="compareProperty"></param> 
		Protected Sub AddCustomCompare(propertyName As String, comparison As Comparison(Of T))
			_customComparisons.Add(propertyName, comparison)
		End Sub

		''' <summary> 
		''' Apply sort. 
		''' </summary> 
		''' <param name="prop"></param> 
		''' <param name="direction"></param> 
		Protected Overrides Sub ApplySortCore(prop As PropertyDescriptor, direction As ListSortDirection)
			Dim comparison As Comparison(Of T)
			If Not _customComparisons.TryGetValue(prop.Name, comparison) Then
				' Check to see if the property type we are sorting by implements 
				' the IComparable interface. 
				Dim interfaceType As Type = prop.PropertyType.GetInterface("IComparable")
				If interfaceType IsNot Nothing Then
					comparison = Function(t1 As T, t2 As T) Do
						Dim val1 As IComparable = DirectCast(prop.GetValue(t1), IComparable)
						Dim val2 As IComparable = DirectCast(prop.GetValue(t2), IComparable)
						Return val1.CompareTo(val2)
					End Function
				Else
					' Last option: convert to string and compare. 
					comparison = Function(t1 As T, t2 As T) Do
						Dim val1 As String = prop.GetValue(t1).ToString()
						Dim val2 As String = prop.GetValue(t2).ToString()
						Return val1.CompareTo(val2)
					End Function
				End If
			End If

			If comparison IsNot Nothing Then
				' If so, set the SortPropertyValue and SortDirectionValue. 
				_sortPropertyValue = prop
				_sortDirectionValue = direction

				' Create sorted list. 
				Dim _sortedList As New List(Of T)(Me)
				_sortedList.Sort(comparison)

				' Reverse order if needed. 
				If direction = ListSortDirection.Descending Then
					_sortedList.Reverse()
				End If

				' Update list. 
				Dim count As Integer = Me.Count
				For i As Integer = 0 To count - 1
					Me(i) = _sortedList(i)
				Next

				' Raise the ListChanged event so bound controls refresh their 
				' values. 
				OnListChanged(New ListChangedEventArgs(ListChangedType.Reset, -1))
			End If
		End Sub

		' Method below was in the original implementation from MS. Don't know what it's for. 
		' -- Martijn Boeker, Jan 21, 2010 

		'protected override void RemoveSortCore() 
		'{ 
		'    //int position; 
		'    //object temp; 
		'    //// Ensure the list has been sorted. 
		'    //if (unsortedItems != null) 
		'    //{ 
		'    //    // Loop through the unsorted items and reorder the 
		'    //    // list per the unsorted list. 
		'    //    for (int i = 0; i < unsortedItems.Count; ) 
		'    //    { 
		'    //        position = this.Find(SortPropertyCore.Name, 
		'    //            unsortedItems[i].GetType(). 
		'    //            GetProperty(SortPropertyCore.Name). 
		'    //            GetValue(unsortedItems[i], null)); 
		'    //        if (position >= 0 && position != i) 
		'    //        { 
		'    //            temp = this[i]; 
		'    //            this[i] = this[position]; 
		'    //            this[position] = (T)temp; 
		'    //            i++; 
		'    //        } 
		'    //        else if (position == i) 
		'    //            i++; 
		'    //        else 
		'    //            // If an item in the unsorted list no longer exists, delete it. 
		'    //            unsortedItems.RemoveAt(i); 
		'    //    } 
		'    //    OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1)); 
		'    //} 
		'} 

		''' <summary> 
		''' Ability to search an item. 
		''' </summary> 
		Protected Overrides ReadOnly Property SupportsSearchingCore() As Boolean
			Get
				Return True
			End Get
		End Property

		''' <summary> 
		''' Finds an item in the list. 
		''' </summary> 
		''' <param name="prop"></param> 
		''' <param name="key"></param> 
		''' <returns></returns> 
		Protected Overrides Function FindCore(prop As PropertyDescriptor, key As Object) As Integer
			' Implementation not changed from MS example code. 

			' Get the property info for the specified property. 
			Dim propInfo As PropertyInfo = GetType(T).GetProperty(prop.Name)
			Dim item As T

			If key IsNot Nothing Then
				' Loop through the the items to see if the key 
				' value matches the property value. 
				For i As Integer = 0 To Count - 1
					item = DirectCast(Items(i), T)
					If propInfo.GetValue(item, Nothing).Equals(key) Then
						Return i
					End If
				Next
			End If
			Return -1
		End Function

		''' <summary> 
		''' Finds an item in the list. 
		''' </summary> 
		''' <param name="prop"></param> 
		''' <param name="key"></param> 
		''' <returns></returns> 
		Private Function Find([property] As String, key As Object) As Integer
			' Implementation not changed from MS example code. 

			' Check the properties for a property with the specified name. 
			Dim properties As PropertyDescriptorCollection = TypeDescriptor.GetProperties(GetType(T))
			Dim prop As PropertyDescriptor = properties.Find([property], True)

			' If there is not a match, return -1 otherwise pass search to 
			' FindCore method. 
			If prop Is Nothing Then
				Return -1
			Else
				Return FindCore(prop, key)
			End If
		End Function

		#End Region
	End Class
End Namespace

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Dmitry G
Dmitry G
Flag of New Zealand image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of pamsauto
pamsauto

ASKER

Yep you are right it is IComparable.  And I understand everything in the link you send.  So how does hte final binding work with the DataGridView so it sorts?   Do I have to write code to check what sort is being requested and write a function for each type?   I was hoping for something more flexable.