Trying to generate GridView columns programmatically

I have a program where I am trying to generate the columns dynamically from an IEnumerable datasource, which Ive never used before, and Im having trouble with. I assign the Datasource to the gridview  and then I try to create the columns but it was orignally done in C# but I am dtrying to do it in VB.NEt so I havent been able to get this done.

Here is the code in C#...I tried to convert to VB.NET using Telerix but Im passing in a DataView as the source where in this code its passing in a dynamic source, which cant be done in VB so when I try to run the GetProperties I am getting the same values? Can someone help me out here to get this done in VB.NET passing in a DataView or a DataTable?

 public static void PrepareColumns(dynamic source, DataControlFieldCollection columns, Func<string, string> headerNameFormatter)
        {
            // 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)
            {
                // at this point, the datasource must have been prepared and it must be a list
                var properties = source[0].GetType().GetProperties();
                foreach (var property in properties)
                {
                    var name = property.Name;

                    var field = new BoundField
                                    {
                                        DataField = name,
                                        HeaderText =
                                            headerNameFormatter == null
                                                ? SeperateNamesWithSpace(name)
                                                : headerNameFormatter(name),
                                        SortExpression = name,
                                        HtmlEncode = false
                                    };

                    if (property.PropertyType.Name == "DateTime")
                    {
                        field.DataFormatString = "{0:dd-MMM-yyyy}";
                    }

                    columns.Add(field);
                }
            }
        }
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:
Sorry I meant to say that I am NOT getting the same values in the GetProperties
it_saigeDeveloperCommented:
In all honesty, I believe this might be what you are after:
Module Extensions
	<System.Runtime.CompilerServices.Extension()> _
	Public Sub PrepareColumns(Of T)(ByVal source As IEnumerable(Of T), ByVal columns As DataControlFieldCollection, ByVal headerNameFormatter As Func(Of String, String))
		' 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] As PropertyInfo In properties
				Dim name = [property].Name

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

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

				columns.Add(field)
			Next
		End If
	End Sub
End Module

Open in new window

-saige-
jknj72Author Commented:
I got an error on this  
"Unable to cast object of type 'System.Data.DataRowView' to type 'System.Collections.IEnumerable'. "
on
Dim properties = source(0).[GetType]().GetProperties()

In the example I am going off of it is using a System.Linq.Enumerable.WhereSelectIsIterator as the source and I am using a database so I am passing in a different type as the original.  But I think Im in the ballpark!

In my example I am passing in a DataView, as the source,, which is causing a problem for me. I have the datasource set and can pass in a datatable or whatever if I need to?

Thanks for your help
Become a Microsoft Certified Solutions Expert

This course teaches how to install and configure Windows Server 2012 R2.  It is the first step on your path to becoming a Microsoft Certified Solutions Expert (MCSE).

jknj72Author Commented:
Just so you know I prepare the DataSource prior to the Columns so maybe I need to change anything here? Again, his is obviously in C# but Im doing it in VB

        public static void PrepareDataSource(
            GridView gvGeneric,
            StateBag viewState,
            ref IEnumerable DataSource,
            ref int _totalRowCount,
            Func<GridViewSortEventArgs, IEnumerable> sorting)
        {
            var column = viewState[Const.SortExpression] as string;
            SortDirection sortDirection = SortDirection.Ascending;
            if (viewState[Const.SortDirection] != null)
            {
                sortDirection = (SortDirection)viewState[Const.SortDirection];
            }

            var temp = DataSource.Cast<object>();
            _totalRowCount = temp.Count();

            if (column != null)
            {
                var source = SortingHelper.GetSortedObjects(new GridViewSortEventArgs(column, sortDirection), temp, sorting);
                DataSource = source;
            }
            else if (DataSource.GetType().Name != Const.ListTypeName)
            {
                DataSource = temp.ToList();
            }

            gvGeneric.DataSource = DataSource;
        }
it_saigeDeveloperCommented:
I'm not seeing where you prepare the columns.  Can provide the code associated with this?  Also it would help if you use code blocks.

1. Press the '[b]CODE[/b]' glyph in the formatting bar.

Capture.JPG

2. This will insert code blocks.

Note you can also just type [code]This is example code[/code]

3. Code is formatted like the following.

This is example code

Open in new window


-saige-
jknj72Author Commented:
Ok sorry, I just pasted it in there? Could you not see my first post with the code in it? The Sub was called PrepareColumns

 public static void PrepareColumns(dynamic source, DataControlFieldCollection columns, Func<string, string> headerNameFormatter)
        {
            // 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)
            {
                // at this point, the datasource must have been prepared and it must be a list
                var properties = source[0].GetType().GetProperties();
                foreach (var property in properties)
                {
                    var name = property.Name;

                    var field = new BoundField
                                    {
                                        DataField = name,
                                        HeaderText =
                                            headerNameFormatter == null
                                                ? SeperateNamesWithSpace(name)
                                                : headerNameFormatter(name),
                                        SortExpression = name,
                                        HtmlEncode = false
                                    };

                    if (property.PropertyType.Name == "DateTime")
                    {
                        field.DataFormatString = "{0:dd-MMM-yyyy}";
                    }

                    columns.Add(field);
                }
            }
        }

Open in new window


and then the PrepareDataSource which I call before the PrepareColumns

      public static void PrepareDataSource(
            GridView gvGeneric,
            StateBag viewState,
            ref IEnumerable DataSource,
            ref int _totalRowCount,
            Func<GridViewSortEventArgs, IEnumerable> sorting)
        {
            var column = viewState[Const.SortExpression] as string;
            SortDirection sortDirection = SortDirection.Ascending;
            if (viewState[Const.SortDirection] != null)
            {
                sortDirection = (SortDirection)viewState[Const.SortDirection];
            }

            var temp = DataSource.Cast<object>();
            _totalRowCount = temp.Count();

            if (column != null)
            {
                var source = SortingHelper.GetSortedObjects(new GridViewSortEventArgs(column, sortDirection), temp, sorting);
                DataSource = source;
            }
            else if (DataSource.GetType().Name != Const.ListTypeName)
            {
                DataSource = temp.ToList();
            }

            gvGeneric.DataSource = DataSource;
        }

Open in new window


Hope I did it correctly and thanks for your help!!!
jknj72Author Commented:
oh I see what you mean now...Thanks for the correction
it_saigeDeveloperCommented:
You did fine.

To clarify, where is the code that calls the PrepareColumns and PrepareDataSource  methods?

-saige-
jknj72Author Commented:
Ahh sorry...Here it is... In my code I had to take out the sorting in the DataSource call and the HeaderFormatter in the Column call, so  you could ignore those parameters because I couldnt figure out the C# conversion to VB.NET so I had to work around it

        
    Public DataSource As IEnumerable
    'Public Event HeaderFormatting As Func(Of String, String)
    'Public Event Sorting As Func(Of GridViewSortEventArgs, IEnumerable)

        gvGeneric.AllowPaging = AllowSorting
        gvGeneric.AllowSorting = AllowSorting

        DataSourceHelper.PrepareDataSource(gvGeneric, ViewState, DataSource, _totalRowCount) ', Sorting(e))
        ColumnHelper.PrepareColumns(DataSource, gvGeneric.Columns) ', HeaderFormatting)

Open in new window

jknj72Author Commented:
Im thinking I need to convert the DataSource to a list because thats what they had it as in the example. I just created a dataset and tried to pass it in that way(tried a dataview as well) and it didnt work.
it_saigeDeveloperCommented:
In the DataView, there is a table property, the table should be an enumerable.  And since the table contains schema, it should also contain the columns.

-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:
thanks Saige
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.