jknj72
asked on
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().GetPro perties();
foreach (var property in properties)
{
var name = property.Name;
var field = new BoundField
{
DataField = name,
HeaderText =
headerNameFormatter == null
? SeperateNamesWithSpace(nam e)
: headerNameFormatter(name),
SortExpression = name,
HtmlEncode = false
};
if (property.PropertyType.Nam e == "DateTime")
{
field.DataFormatString = "{0:dd-MMM-yyyy}";
}
columns.Add(field);
}
}
}
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
{
// 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().GetPro
foreach (var property in properties)
{
var name = property.Name;
var field = new BoundField
{
DataField = name,
HeaderText =
headerNameFormatter == null
? SeperateNamesWithSpace(nam
: headerNameFormatter(name),
SortExpression = name,
HtmlEncode = false
};
if (property.PropertyType.Nam
{
field.DataFormatString = "{0:dd-MMM-yyyy}";
}
columns.Add(field);
}
}
}
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
-saige-
ASKER
I got an error on this
"Unable to cast object of type 'System.Data.DataRowView' to type 'System.Collections.IEnume rable'. "
on
Dim properties = source(0).[GetType]().GetP roperties( )
In the example I am going off of it is using a System.Linq.Enumerable.Whe reSelectIs Iterator 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
"Unable to cast object of type 'System.Data.DataRowView' to type 'System.Collections.IEnume
on
Dim properties = source(0).[GetType]().GetP
In the example I am going off of it is using a System.Linq.Enumerable.Whe
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
ASKER
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.SortExpres sion] as string;
SortDirection sortDirection = SortDirection.Ascending;
if (viewState[Const.SortDirec tion] != null)
{
sortDirection = (SortDirection)viewState[C onst.SortD irection];
}
var temp = DataSource.Cast<object>();
_totalRowCount = temp.Count();
if (column != null)
{
var source = SortingHelper.GetSortedObj ects(new GridViewSortEventArgs(colu mn, sortDirection), temp, sorting);
DataSource = source;
}
else if (DataSource.GetType().Name != Const.ListTypeName)
{
DataSource = temp.ToList();
}
gvGeneric.DataSource = DataSource;
}
public static void PrepareDataSource(
GridView gvGeneric,
StateBag viewState,
ref IEnumerable DataSource,
ref int _totalRowCount,
Func<GridViewSortEventArgs
{
var column = viewState[Const.SortExpres
SortDirection sortDirection = SortDirection.Ascending;
if (viewState[Const.SortDirec
{
sortDirection = (SortDirection)viewState[C
}
var temp = DataSource.Cast<object>();
_totalRowCount = temp.Count();
if (column != null)
{
var source = SortingHelper.GetSortedObj
DataSource = source;
}
else if (DataSource.GetType().Name
{
DataSource = temp.ToList();
}
gvGeneric.DataSource = DataSource;
}
ASKER
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
and then the PrepareDataSource which I call before the PrepareColumns
Hope I did it correctly and thanks for your help!!!
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);
}
}
}
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;
}
Hope I did it correctly and thanks for your help!!!
ASKER
oh I see what you mean now...Thanks for the correction
You did fine.
To clarify, where is the code that calls the PrepareColumns and PrepareDataSource methods?
-saige-
To clarify, where is the code that calls the PrepareColumns and PrepareDataSource methods?
-saige-
ASKER
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)
ASKER
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.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
thanks Saige
ASKER