Loop through IEnumeration

I want to loop through the "source" here which is a DataSource of IEnumerable that has been populated but I am having trouble iterating through the properties from the existing code that I am trying to mimic.

Here is my call

ColumnHelper.PrepareColumns(DataSource, gvGeneric.Columns)

Open in new window


And here is the for each loop that is not bringing back the correct properties for me? Im confused now

Public Shared Sub PrepareColumns(source As Object, ByVal columns As DataControlFieldCollection)

        ' if ViewState is enabled, the columns info will be persisted between requests and we only want to add the column 
        ' the first time the grid is requested. 
        If columns.Count = 0 Then
            ' at this point, the datasource must have been prepared and it must be a list
            Dim properties = source(0).GetType.GetProperties

            For Each [property] In properties

                Dim name = [property].Name

                Dim field = New BoundField()
                With field
                    .DataField = name
                    .HeaderText = SeperateNamesWithSpace(name) 'If(headerNameFormatter Is Nothing, SeperateNamesWithSpace(name), headerNameFormatter(name))
                    .SortExpression = name
                    .HtmlEncode = False
                End With

                If [property].PropertyType.Name = "DateTime" Then
                    field.DataFormatString = "{0:dd-MMM-yyyy}"
                End If

                columns.Add(field)
            Next


        End If
    End Sub

Open in new window


Its giving me proprties for another type of object or something....Please help me out here!!!
jknj72Asked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jknj72Author Commented:
I guess I should mention that Im trying to iterate through the source and set the column names and properties....
it_saigeDeveloperCommented:
What does your Enumerable comprise of, in other words, how do you populate your enumerable?

-saige-
jknj72Author Commented:
Ok in the c# program it is using the first parameter source as Dynamic and then columns as DataFieldCollection so in my VB program I am passing in source as object(cause i dont have dynamic in VB)and DataFieldCollection for the columns param. When I do the for each property loop its looking at a different object then mine. I looked at the watch window and see that the C# programs dynamic source is now a Systems.Reflection.PropertyInfo(see 1st image attached) and my program is different.....

Any clue on what Im doing wrong here??? Im passing in a dataview while the c# program is passing in a List LinQ query of hard coded results. I want to be able to pass in a data set or table or view and get this to work
pic1.png
pic2.bmp
CompTIA Security+

Learn the essential functions of CompTIA Security+, which establishes the core knowledge required of any cybersecurity role and leads professionals into intermediate-level cybersecurity jobs.

jknj72Author Commented:
I forgot to add that Im passing these values on a call to Prepare my columns

ColumnHelper.PrepareColumns(DataSource, gvGeneric.Columns)
it_saigeDeveloperCommented:
What type is 'DataSource' and how do you populate 'DataSource'?

-saige-
jknj72Author Commented:
I set it to a stored proc(pic4) and it has return records and the C# version is a List(pic 3) so when I try to  pass it to the PrepareColumns as an Object and then do the Cast I want it to be of the same type as the list ends up being? I essentially have a NameObject that I am trying to use in place of the C# Product List but its obviously not working. Any thoughts?
pic3.png
jknj72Author Commented:
oops forgot to add my pic of my datasource...here it is
pic4-VB.NET.png
jknj72Author Commented:
fyi,

the DataSource both starts out being of type IEnumerable with mine being set to a DataSet and his being set to a List in C#. When they are passed into the PrepareColumns routine his source is dynamic and mine is of Object. Well when they do the for each loop it is a different type then the C# version and Id love to get it to be the same. Am I making sense at all? haha

Thanks for your help with this!!

    Public Shared Sub PrepareColumns(source As Object, ByVal columns As DataControlFieldCollection) 

        ' if ViewState is enabled, the columns info will be persisted between requests and we only want to add the column 
        ' the first time the grid is requested. 
        If columns.Count = 0 Then
[b]            ' at this point, the datasource must have been prepared and it must be a list[/b]
            Dim properties = source(0).GetType().GetProperties()

            For Each [property] In properties

                Dim name = [property].PropertyType.Name

                Dim field = New BoundField()
                With field
                    .DataField = name
                    .HeaderText = SeperateNamesWithSpace(name) 'If(headerNameFormatter Is Nothing, SeperateNamesWithSpace(name), headerNameFormatter(name))
                    .SortExpression = name
                    .HtmlEncode = False
                End With

                If [property].PropertyType.Name = "DateTime" Then
                    field.DataFormatString = "{0:dd-MMM-yyyy}"
                End If

                columns.Add(field)
            Next


        End If
    End Sub

Open in new window

it_saigeDeveloperCommented:
Now that I can see your intentions a little clearer.  Try this on for size:

WebForm1.aspx -
<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="WebForm1.aspx.vb" Inherits="EE_Q28837439.WebForm1" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    
    	<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
	    </asp:GridView>
    
    </div>
    </form>
</body>
</html>

Open in new window

WebForm1.aspx.vb -
Imports System.Runtime.CompilerServices
Imports System.ComponentModel

Public Class WebForm1
	Inherits System.Web.UI.Page

	Private products As List(Of Product)

	Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
		If Not Page.IsPostBack Then
			If products Is Nothing Then
				products = New List(Of Product) From _
					{ _
						New Product() With {.Name = "IPhone2", .Description = "Apple Product 1", .Price = 499.99D, .Rating = "High", .ReleaseDate = GetDateTime("31 March 2010")}, _
						New Product() With {.Name = "IPhone6", .Description = "Apple Product 2", .Price = 399.99D, .Rating = "Medium", .ReleaseDate = GetDateTime("31 March 2011")}, _
						New Product() With {.Name = "IPhone3", .Description = "Apple Product 3", .Price = 599.99D, .Rating = "Medium", .ReleaseDate = GetDateTime("31 March 2010")}, _
						New Product() With {.Name = "IPhone3G", .Description = "Apple Product 4", .Price = 299.99D, .Rating = "High", .ReleaseDate = GetDateTime("31 March 2015")}, _
						New Product() With {.Name = "IPhone4", .Description = "Apple Product5", .Price = 199.99D, .Rating = "Medium", .ReleaseDate = GetDateTime("31 Dec 2010")}, _
						New Product() With {.Name = "IPhone5", .Description = "Apple Product6", .Price = 399.99D, .Rating = "Low", .ReleaseDate = GetDateTime("31 March 2010")}, _
						New Product() With {.Name = "IPhone2", .Description = "Apple Product7", .Price = 459.99D, .Rating = "High", .ReleaseDate = GetDateTime("31 March 2010")}, _
						New Product() With {.Name = "IPhone3", .Description = "Apple Product8", .Price = 469.99D, .Rating = "High", .ReleaseDate = GetDateTime("31 March 2010")}, _
						New Product() With {.Name = "IPhone3G", .Description = "Apple Product9", .Price = 479.99D, .Rating = "Low", .ReleaseDate = GetDateTime("31 Jan 2010")}, _
						New Product() With {.Name = "IPhone4", .Description = "Apple Product", .Price = 489.99D, .Rating = "Medium", .ReleaseDate = GetDateTime("1 Feb 2010")}, _
						New Product() With {.Name = "IPhone1", .Description = "Apple Product", .Price = 499.99D, .Rating = "High", .ReleaseDate = GetDateTime("31 March 2010")}, _
						New Product() With {.Name = "IPhone5", .Description = "Apple Product", .Price = 439.99D, .Rating = "Medium", .ReleaseDate = GetDateTime("3 Feb 2010")}, _
						New Product() With {.Name = "IPhone5", .Description = "Apple Product9", .Price = 299.99D, .Rating = "Medium", .ReleaseDate = GetDateTime("3 Jun 2010")}, _
						New Product() With {.Name = "IPhone3G", .Description = "Apple Product", .Price = 199.99D, .Rating = "Low", .ReleaseDate = GetDateTime("31 March 2010")}, _
						New Product() With {.Name = "IPhone4", .Description = "Apple Product4", .Price = 449.99D, .Rating = "High", .ReleaseDate = GetDateTime("31 March 2011")}, _
						New Product() With {.Name = "IPhone1", .Description = "Apple Product", .Price = 495.99D, .Rating = "Medium", .ReleaseDate = GetDateTime("31 March 2010")}, _
						New Product() With {.Name = "IPhone2", .Description = "Apple Product4", .Price = 497.99D, .Rating = "Medium", .ReleaseDate = GetDateTime("31 March 2010")}, _
						New Product() With {.Name = "IPhone3", .Description = "Apple Product", .Price = 495.99D, .Rating = "High", .ReleaseDate = GetDateTime("3 Aug 2011")}, _
						New Product() With {.Name = "IPhone3G", .Description = "Apple Product6", .Price = 491.99D, .Rating = "Low", .ReleaseDate = GetDateTime("31 March 2010")}, _
						New Product() With {.Name = "IPhone4", .Description = "Apple Product", .Price = 499.92D, .Rating = "Medium", .ReleaseDate = GetDateTime("11 Sep 2011")}, _
						New Product() With {.Name = "IPhone1", .Description = "Apple Product7", .Price = 499.93D, .Rating = "High", .ReleaseDate = GetDateTime("3 Nov 2012")}, _
						New Product() With {.Name = "IPhone6", .Description = "Apple Product8", .Price = 499.93D, .Rating = "High", .ReleaseDate = GetDateTime("31 March 2010")}, _
						New Product() With {.Name = "IPhone3", .Description = "Apple Product", .Price = 499.94D, .Rating = "High", .ReleaseDate = GetDateTime("31 March 2010")}, _
						New Product() With {.Name = "IPhone3G", .Description = "Apple Product", .Price = 499.95D, .Rating = "Medium", .ReleaseDate = GetDateTime("31 Jan 2010")}, _
						New Product() With {.Name = "IPhone4", .Description = "Apple Product4", .Price = 499.96D, .Rating = "High", .ReleaseDate = GetDateTime("31 March 2010")}, _
						New Product() With {.Name = "IPhone1c", .Description = "Apple Product5", .Price = 499.97D, .Rating = "Medium", .ReleaseDate = GetDateTime("31 May 2010")}, _
						New Product() With {.Name = "IPhone2b", .Description = "Apple Product6", .Price = 499.98D, .Rating = "Medium", .ReleaseDate = GetDateTime("31 March 2010")}, _
						New Product() With {.Name = "IPhone3a", .Description = "Apple Product7", .Price = 499.92D, .Rating = "High", .ReleaseDate = GetDateTime("31 April 2010")}, _
						New Product() With {.Name = "IPhone3G", .Description = "Apple Product8", .Price = 499.93D, .Rating = "Low", .ReleaseDate = GetDateTime("31 March 2010")}, _
						New Product() With {.Name = "IPhone4", .Description = "Apple Product5", .Price = 499.94D, .Rating = "Low", .ReleaseDate = GetDateTime("1 Nov 2010")}, _
						New Product() With {.Name = "IPhone5", .Description = "Apple Product5", .Price = 499.95D, .Rating = "Low", .ReleaseDate = GetDateTime("31 March 2010")}, _
						New Product() With {.Name = "IPhone5", .Description = "Apple Product5", .Price = 499.95D, .Rating = "Low", .ReleaseDate = GetDateTime("31 March 2010")} _
					}
			End If

			Dim table = products.ConvertToDataTable()
			Dim view = New DataView(table)
			PrepareColumns(view.Table, GridView1.Columns)
			GridView1.DataSource = view
			GridView1.DataBind()
		End If
	End Sub

	Private Sub PrepareColumns(source As DataTable, ByVal columns As DataControlFieldCollection)
		' if ViewState is enabled, the columns info will be persisted between requests and we only want to add the column 
		' the first time the grid is requested. 
		If columns.Count = 0 Then
			For Each [column] As DataColumn In source.Columns

				Dim name = [column].ColumnName

				'If(headerNameFormatter Is Nothing, SeperateNamesWithSpace(name), headerNameFormatter(name))
				Dim field = New BoundField() With _
						  { _
							  .DataField = name, _
							  .HeaderText = name, _
							  .SortExpression = name, _
							  .HtmlEncode = False _
						  }

				If [column].DataType().Equals(GetType(DateTime)) Then
					field.DataFormatString = "{0:dd-MMM-yyyy}"
				End If

				columns.Add(field)
			Next
		End If
	End Sub

	Private Function GetDateTime(ByVal value As String) As DateTime
		Dim result As DateTime = DateTime.MinValue
		Try
			DateTime.TryParse(value, result)
		Catch ex As Exception
			result = DateTime.MinValue
		End Try
		Return result
	End Function
End Class

Module Extensions
	<Extension()> _
	Public Function ConvertToDataTable(Of T)(ByVal source As IEnumerable(Of T)) As DataTable
		Dim properties As PropertyDescriptorCollection = TypeDescriptor.GetProperties(GetType(T))
		Dim table As DataTable = New DataTable()

		For i As Integer = 0 To properties.Count - 1
			Dim [property] As PropertyDescriptor = properties(i)
			If [property].PropertyType.IsGenericType AndAlso [property].PropertyType.GetGenericTypeDefinition().Equals(GetType(Nullable)) Then
				table.Columns.Add([property].Name, [property].PropertyType.GetGenericArguments()(0))
			Else
				table.Columns.Add([property].Name, [property].PropertyType)
			End If
		Next

		Dim values(properties.Count - 1) As Object
		For Each item As T In source
			For i As Integer = 0 To properties.Count - 1
				values(i) = properties(i).GetValue(item)
			Next
			table.Rows.Add(values)
		Next
		Return table
	End Function
End Module

Class Product
	Public Property Name() As String
	Public Property Description() As String
	Public Property Price() As Decimal
	Public Property Rating() As String
	Public Property ReleaseDate() As DateTime
End Class

Open in new window

Produces the following output -Capture.JPG-saige-

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
jknj72Author Commented:
The datasource starts off as IEnumerable. The C# program generates the Product Object to a List and is able to pass this but when I try to call the PrepareDataSource right before I call the PrepareColumns I am getting a type error which may be the root cause of all my issues?
What do you think?
Here is my call to the DataSource which is right before the PrepareColumns, which youve showed me already and it looks good to me...

 DataSourceHelper.PrepareDataSource(gvGeneric, ViewState, DataSource, _totalRowCount)

Code for PrepareDataSource
    Public Shared Sub PrepareDataSource(gvGeneric As GridView, viewState As StateBag, ByRef DataSource As IEnumerable, ByRef _totalRowCount As Integer) ', sorting As GridViewSortEventArgs)

        Dim column = TryCast(viewState(Constants.SortExpression), String)
        Dim sortDirection As SortDirection = sortDirection.Ascending

        If viewState(Constants.SortDirection) IsNot Nothing Then
            sortDirection = DirectCast(viewState(Constants.SortDirection), SortDirection)
        End If

        Dim temp = DataSource.Cast(Of Object)()
        _totalRowCount = temp.Count

        If column IsNot Nothing Then
            Dim source = SortingHelper.GetSortedObjects(New GridViewSortEventArgs(column, sortDirection), temp) ',  sorting)
            DataSource = source
        ElseIf DataSource.[GetType]().Name <> Constants.ListTypeName Then
            DataSource = temp.ToList
        End If

        gvGeneric.DataSource = DataSource

    End Sub

Open in new window


I know the gridview gets set in the Page_Load of my Default form but then it gets set in the Load of the user control too? Im not sure Im doing this correctly but I think Im close.  When I tried to pass in the IEnumerable to the PrepareColumns call it says it gives me a cpnversion error

Unable to cast object of type 'System.Collections.Generic.List`1[System.Object]' to type 'System.Data.DataTable'.

Any thoughts on this?
Thanks for your help
jknj72Author Commented:
Also, even though I set the DataSource in the Default.aspx.vb it never shows the data I have generated? Ive tried the DataBind after the DataSource but it still doesnt show me any data in the grid?
jknj72Author Commented:
I have found the solution for this. When looping through the following code I didnt have the correct references set so it wasnt looping through the correct object so I added the System.Reflection and that fixed the problem.
jknj72Author Commented:
thanks for your help
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
ASP.NET

From novice to tech pro — start learning today.