I did find some information, but that was on other forums.
Now we have DynamicObject (or ExpandoObject, that's an implementation of DynamicObject as I understood) we, of course, want it to bind to a RadGrid. There is no thread or blog I can find on this issue. It's also a bit of a Sunday afternoon thing for now.
I was wondering what Telerik thinks of this usage, what would be your approach..
And also this tread can grow to be of use to others, that's the main gaol..
We have a dynamic class:
Imports
System.IO
Imports
System.Dynamic
Public
Class
DynamicDictionary
Inherits
DynamicObject
' The inner dictionary.
Dim
mdic_PropertyHolder
As
New
Dictionary(Of
String
,
Object
)
' This property returns the number of elements in the inner dictionary.
ReadOnly
Property
Count
As
Integer
Get
Return
mdic_PropertyHolder.Count
End
Get
End
Property
ReadOnly
Property
Items
As
Dictionary(Of
String
,
Object
)
Get
Return
mdic_PropertyHolder
End
Get
End
Property
Public
Function
GetMembers()
As
String
()
Return
mdic_PropertyHolder.Keys.ToArray
End
Function
Public
Property
Item(
ByVal
PropertyName
As
String
)
As
String
Get
Return
mdic_PropertyHolder(PropertyName)
End
Get
Set
(
ByVal
value
As
String
)
mdic_PropertyHolder(PropertyName) = value
End
Set
End
Property
' If you try to get a value of a property that is not defined in the class, this method is called.
Public
Overrides
Function
TryGetMember(
ByVal
binder
As
System.Dynamic.GetMemberBinder,
ByRef
result
As
Object
)
As
Boolean
' Converting the property name to lowercase
' so that property names become case-insensitive.
Dim
name
As
String
= binder.Name.ToLower()
' If the property name is found in a dictionary, set the result parameter to the property value and return true. Otherwise, return false.
Return
mdic_PropertyHolder.TryGetValue(name, result)
End
Function
Public
Overrides
Function
TrySetMember(
ByVal
binder
As
System.Dynamic.SetMemberBinder,
ByVal
value
As
Object
)
As
Boolean
' Converting the property name to lowercase so that property names become case-insensitive.
mdic_PropertyHolder(binder.Name.ToLower()) = value
' You can always add a value to a dictionary, so this method always returns true.
Return
True
End
Function
End
Class
In a asp.net page we have:
<
telerik:RadGrid
ID
=
"RadGrid1"
runat
=
"server"
AllowPaging
=
"True"
GridLines
=
"None"
Width
=
"100%"
ShowGroupPanel
=
"True"
AllowSorting
=
"True"
ShowStatusBar
=
"true"
>
<
MasterTableView
RetrieveAllDataFields
=
"true"
AutoGenerateColumns
=
"false"
>
<
Columns
>
<
telerik:GridTemplateColumn
HeaderText
=
"Hopa"
>
<
ItemTemplate
>
<
span
style
=
"white-space:nowrap"
><%# Container.DataItem.firstname%></
span
>
</
ItemTemplate
>
</
telerik:GridTemplateColumn
>
<
telerik:GridBoundColumn
HeaderText
=
"FirstName"
DataField
=
"FirstName"
>
</
telerik:GridBoundColumn
>
<
telerik:GridBoundColumn
HeaderText
=
"MiddleName"
DataField
=
"MiddleName"
>
</
telerik:GridBoundColumn
>
<
telerik:GridBoundColumn
DataField
=
"LastName"
HeaderText
=
"LastName"
>
</
telerik:GridBoundColumn
>
</
Columns
>
</
MasterTableView
>
</
telerik:RadGrid
>
In a asp.net page code we have:
Protected
Sub
Page_Load(
ByVal
sender
As
Object
,
ByVal
e
As
System.EventArgs)
Handles
Me
.Load
Dim
person
As
Object
Dim
List
As
New
ArrayList
' Adding new dynamic properties.
' The TrySetMember method is called.
person =
New
DynamicDictionary()
person.FirstName =
"Ellen"
person.LastName =
"Adams"
List.Add(person)
person =
New
DynamicDictionary()
person.FirstName =
"Piet"
person.LastName =
"Pietersen"
List.Add(person)
person =
New
DynamicDictionary()
person.FirstName =
"Erik"
person.MiddleName =
"van der"
person.LastName =
"Heide"
List.Add(person)
person =
New
DynamicDictionary()
person.FirstName =
"Jan"
person.LastName =
"Janssen"
List.Add(person)
RadGrid1.DataSource = List
RadGrid1.DataBind()
End
Sub
Private
Sub
RadGrid1_ItemDataBound(sender
As
Object
, e
As
Telerik.Web.UI.GridItemEventArgs)
Handles
RadGrid1.ItemDataBound
If
TypeOf
e.Item
Is
GridDataItem
Then
Dim
dataBoundItem
As
GridDataItem = e.Item
For
Each
Member
As
String
In
dataBoundItem.DataItem.GetMembers
Try
dataBoundItem(Member).Text = dataBoundItem.DataItem.Item(Member)
Catch
ex
As
Exception
' Oops
End
Try
Next
End
If
End
Sub
This is of course not verry fast, but verry flexible it is. Editing is an issue I think, but displaying is not.
Regards,
Erik
15 Answers, 1 is accepted
This approach can be very useful. Thank you for sharing it with the whole community.
It is a nice way of using the dynamic object that is supported in .Net 4.0
Here is C# version of the code that also supports editing.
ASPX:
<
telerik:RadGrid
ID
=
"RadGrid1"
runat
=
"server"
OnNeedDataSource
=
"RadGrid1_NeedDataSource"
AutoGenerateEditColumn
=
"true"
AutoGenerateColumns
=
"false"
AllowAutomaticUpdates
=
"false"
OnUpdateCommand
=
"RadGrid1_UpdateCommand"
>
<
MasterTableView
>
<
Columns
>
<
telerik:GridTemplateColumn
HeaderText
=
"First name"
>
<
ItemTemplate
>
<%# (Container.DataItem as dynamic).FirstName%>
</
ItemTemplate
>
<
EditItemTemplate
>
<
asp:TextBox
runat
=
"server"
ID
=
"FirstNameTextbox"
Text=" <%# (Container.DataItem as dynamic).FirstName%> "> </
asp:TextBox
>
</
EditItemTemplate
>
</
telerik:GridTemplateColumn
>
</
Columns
>
</
MasterTableView
>
</
telerik:RadGrid
>
C#:
using
System.Dynamic;
using
Telerik.Web.UI;
public
partial
class
RadGridBindingToListOfDynamicDict : System.Web.UI.Page
{
public
class
DynamicDictionary : DynamicObject
{
Dictionary<
string
,
object
> dictionary =
new
Dictionary<
string
,
object
>();
public
int
Count
{
get
{
return
dictionary.Count;
}
}
public
override
bool
TryGetMember(GetMemberBinder binder,
out
object
result)
{
string
name = binder.Name.ToLower();
return
dictionary.TryGetValue(name,
out
result);
}
public
override
bool
TrySetMember(SetMemberBinder binder,
object
value)
{
dictionary[binder.Name.ToLower()] = value;
return
true
;
}
}
protected
List<dynamic> LoadData()
{
List<dynamic> data =
new
List<dynamic>();
dynamic person;
person =
new
DynamicDictionary();
person.FirstName =
"Ellen"
;
person.LastName =
"Adams"
;
data.Add(person);
person =
new
DynamicDictionary();
person.FirstName =
"Piet"
;
person.LastName =
"Pietersen"
;
data.Add(person);
person =
new
DynamicDictionary();
person.FirstName =
"Erik"
;
person.MiddleName =
"van der"
;
person.LastName =
"Heide"
;
data.Add(person);
person =
new
DynamicDictionary();
person.FirstName =
"Jan"
;
person.LastName =
"Janssen"
;
data.Add(person);
return
data;
}
protected
void
Page_Load(
object
sender, EventArgs e)
{
if
(Session[
"data"
] ==
null
)
{
Session[
"data"
] = LoadData();
}
}
protected
void
RadGrid1_NeedDataSource(
object
sender, Telerik.Web.UI.GridNeedDataSourceEventArgs e)
{
(sender
as
RadGrid).DataSource = (List<dynamic>)Session[
"data"
];
}
protected
void
RadGrid1_UpdateCommand(
object
source, GridCommandEventArgs e)
{
string
newFirstName = (e.Item.FindControl(
"FirstNameTextbox"
)
as
TextBox).Text;
((List<dynamic>)Session[
"data"
])[e.Item.DataSetIndex].FirstName = newFirstName;
}
}
Kind regards,
Vasil
the Telerik team
Browse the vast support resources we have to jump start your development with RadControls for ASP.NET AJAX. See how to integrate our AJAX controls seamlessly in SharePoint 2007/2010 visiting our common SharePoint portal.

I used the above example which works fine but I have problems grouping.
When I try to group by one of the columns I get the following Server exception:
at Telerik.Web.UI.GridDataSetHelper.CreateGroupByTable(DataTable SourceTable, GridTableView view)
at Telerik.Web.UI.GridDataSetHelper.CalcGroupByTables(GridTableView gridTableView, DataTable SourceTable, String RowFilter, Int32 FirstIndex, Int32 LastIndex, Boolean applyPaging, Boolean isCustomPaging)
at Telerik.Web.UI.GridEnumerableFromDataView.PerformTransformation()
at Telerik.Web.UI.GridEnumerableFromDataView.TransformEnumerable()
at Telerik.Web.UI.GridTableView.GetEnumerator(Boolean useDataSource, GridEnumerableBase resolvedDataSource, ArrayList dataKeysArray)
at Telerik.Web.UI.GridTableView.CreateControlHierarchy(Boolean useDataSource)
at Telerik.Web.UI.GridTableView.CreateChildControls(IEnumerable dataSource, Boolean useDataSource)
at System.Web.UI.WebControls.CompositeDataBoundControl.PerformDataBinding(IEnumerable data)
at System.Web.UI.WebControls.DataBoundControl.OnDataSourceViewSelectCallback(IEnumerable data)
at System.Web.UI.DataSourceView.Select(DataSourceSelectArguments arguments, DataSourceViewSelectCallback callback)
at System.Web.UI.WebControls.DataBoundControl.PerformSelect()
at Telerik.Web.UI.GridTableView.PerformSelect()
at System.Web.UI.WebControls.BaseDataBoundControl.DataBind()
at Telerik.Web.UI.GridTableView.DataBind()
at Telerik.Web.UI.GridTableView.BindAllInHierarchyLevel()
at Telerik.Web.UI.RadGrid.RaisePostBackEvent(String eventArgument)
at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
at System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
or on Client side:
Microsoft JScript runtime error: Sys.WebForms.PageRequestManagerServerErrorException: Field FirstName not found in the source table. Please check the expression syntax.
<telerik:RadGrid ID="RadGrid2" runat="server" PageSize="10" AllowSorting="True" AllowMultiRowSelection="True" AllowPaging="True" AllowCustomPaging="false" ShowGroupPanel="True" AutoGenerateColumns="false" GridLines="none"> <PagerStyle Mode="NextPrevNumericAndAdvanced"></PagerStyle> <ClientSettings ReorderColumnsOnClient="True" AllowDragToGroup="True" AllowColumnsReorder="True"> <Selecting AllowRowSelect="True"></Selecting> <Resizing AllowRowResize="false" AllowColumnResize="True" EnableRealTimeResize="True" ResizeGridOnColumnResize="False"></Resizing> </ClientSettings> <GroupingSettings ShowUnGroupButton="true" /> <MasterTableView Width="100%"> <Columns> <telerik:GridTemplateColumn HeaderText="First name" DataField="LastName" SortExpression="LastName" GroupByExpression="FirstName group by FirstName"> <ItemTemplate> <%# (Container.DataItem as dynamic).FirstName%> </ItemTemplate> <EditItemTemplate> <asp:TextBox runat="server" ID="FirstNameTextbox" Text=" <%# (Container.DataItem as dynamic).FirstName%> "> </asp:TextBox> </EditItemTemplate> </telerik:GridTemplateColumn> <telerik:GridTemplateColumn HeaderText="Last name" DataField="LastName" SortExpression="LastName" GroupByExpression="LastName group by LastName"> <ItemTemplate> <%# (Container.DataItem as dynamic).LastName%> </ItemTemplate> <EditItemTemplate> <asp:TextBox runat="server" ID="LastNameTextbox" Text=" <%# (Container.DataItem as dynamic).LastName%> "> </asp:TextBox> </EditItemTemplate> </telerik:GridTemplateColumn> </Columns> </MasterTableView> </telerik:RadGrid>
Unfortunately the RadGrid does not support filtering/sorting/paging when it is bound to collection of . DynamicObjects. RadGrid supports binding to generic collection of .NET 4.0 dynamic type objects. For more information please check out the following online example:
http://demos.telerik.com/aspnet-ajax/grid/examples/programming/dynamictypes/defaultcs.aspx
Regards,
Radoslav
the Telerik team

[=Fields.FirstName]
and
this.textBox.Value = "=(Container.DataItem as dynamic).FirstName";
don't seem to work.
thanks
If you want to bind a control property to the value of object's property boxed into dynamic object by using binding expressions you could try using Eval and bind directly to the property. For example:
<
telerik:RadGrid
ID
=
"RadGrid1"
AllowFilteringByColumn
=
"true"
runat
=
"server"
AllowPaging
=
"true"
PageSize
=
"4"
AutoGenerateColumns
=
"true"
ShowStatusBar
=
"true"
AllowSorting
=
"true"
OnNeedDataSource
=
"RadGrid1_NeedDataSource"
>
<
MasterTableView
PagerStyle-AlwaysVisible
=
"true"
>
<
Columns
>
<
telerik:GridTemplateColumn
DataField
=
"Name"
>
<
ItemTemplate
>
<
asp:TextBox
runat
=
"server"
ID
=
"TextBox1"
Text='<%# DataBinder.Eval(Container.DataItem, "Name") %>'></
asp:TextBox
>
</
ItemTemplate
>
</
telerik:GridTemplateColumn
>
</
Columns
>
</
MasterTableView
>
<
ClientSettings
EnablePostBackOnRowClick
=
"true"
>
<
Selecting
AllowRowSelect
=
"true"
/>
</
ClientSettings
>
</
telerik:RadGrid
>
protected
void
RadGrid1_NeedDataSource(
object
sender, GridNeedDataSourceEventArgs e)
{
dynamic data =
new
[] {
new
{ ID = 1, Name =
"Name1"
},
new
{ ID = 2, Name =
"Name2"
},
new
{ ID = 3, Name =
"Name3"
},
new
{ ID = 4, Name =
"Name4"
},
new
{ ID = 5, Name =
"Name5"
},
new
{ ID = 6, Name =
"Name6"
},
new
{ ID = 7, Name =
"Name7"
},
new
{ ID = 8, Name =
"Name8"
},
new
{ ID = 9, Name =
"Name9"
},
new
{ ID = 10, Name =
"Name10"
},
new
{ ID = 11, Name =
"Name11"
},
new
{ ID = 12, Name =
"Name12"
},
new
{ ID = 13, Name =
"Name13"
},
new
{ ID = 14, Name =
"Name14"
},
new
{ ID = 15, Name =
"Name15"
}
};
RadGrid1.DataSource = data;
}
I hope this helps.
Kind regards,
Radoslav
the Telerik team

I am using Normal Telerik grid control not Rad one. But can this above dynamic list bind with my telerik normal grid control as well?
Could you please elaborate a bit more on your scenario? What do you mean by “I am using Normal Telerik grid control not Rad one”?
Looking forward for your reply.
Kind regards,
Radoslav
the Telerik team


From last 2 weeks i am running into a problem. I am working with MVC applicaiton where i have to implement Telerik grid with dynamic columns. I have done this by Data Table. This table containing column name as DateTime like "2/3/2013 Sunday" or "7:30 AM" and this is the issue. Telerik grid is not binding data with date and time column name. Though if i change the column name to any string value like "Sunday" or any "Text" value then it is working fine.
Index.cshtml
@
using
System.Data;
@model DataTable
@{
ViewBag.Title =
"Home Page"
;
}
<h2>@ViewBag.Message</h2>
@(Html.Telerik().Grid<System.Data.DataRow>(Model.Rows.Cast<System.Data.DataRow>())
.Name(
"Grid"
)
.Columns(columns =>
{
foreach
(System.Data.DataColumn column
in
Model.Columns)
{
if
(column.ColumnName !=
"ShopName"
)
columns.Bound(column.DataType, column.ColumnName).Width(50).Sortable(
false
).Filterable(
false
);
else
columns.Bound(column.DataType, column.ColumnName).Width(50).Sortable(
true
).Filterable(
true
);
}
})
.DataBinding(dataBinding => dataBinding.Ajax().Select(
"_CustomBinding"
,
"Home"
))
.Pageable()
.Sortable()
.Filterable()
)
HomeController.cs
public
class
HomeController : Controller
{
private
static
int
count;
ShopLoadGridModel model =
new
ShopLoadGridModel();
public
ActionResult Index()
{
ViewBag.Message =
"Welcome to ASP.NET MVC!"
;
ViewData[
"total"
] = 100;
DataTable table =
new
DataTable();
table = model.DataTableColumnSettings;
return
View(table);
}
[GridAction(EnableCustomBinding =
true
)]
public
ActionResult _CustomBinding(GridCommand command)
{
model.ShopLoadGridCommand = command;
model.Load();
IEnumerable data = model.ShopLoadGridSummaryIEnumerable;
count = 3;
GridModel model1 =
new
GridModel();
return
View(
new
GridModel { Data = data, Total=count });
}
}
Model Class
Creating column settings with column name
DataTable table =
new
DataTable();
table.Columns.Add(
"ShopName"
,
typeof
(
string
));
table.Columns.Add(
"WIP"
,
typeof
(
string
));
table.Columns.Add(
"CurrentRO"
,
typeof
(
string
));
table.Columns.Add(
"Total"
,
typeof
(
string
));
bool
continueLoop =
true
;
int
limit = 0;
while
(continueLoop)
{
//I want column name like from 7:30 AM to 8:30 PM, if below Date and days column name works fine
string
columnName = DateTime.Now.AddDays(limit).ToShortDateString() +
" "
+ DateTime.Now.AddDays(limit).DayOfWeek;
table.Columns.Add(columnName,
typeof
(
string
));
if
(limit == 7)
// No of columns (5 static + 56 dynamic)
continueLoop =
false
;
limit++;
}
return
table;
Filling data which will display in grid
var serializer =
new
JavaScriptSerializer();
serializer.RegisterConverters(
new
JavaScriptConverter[] {
new
ExpandoJSONConverter() });
List<Dictionary<
string
,
string
>> data =
new
List<Dictionary<
string
,
string
>>();
bool
continueLoop =
true
;
int
limit = 0;
for
(
int
i = 1; i <= 3; i++)
{
continueLoop =
true
;
limit = 0;
dynamic diarioModel =
new
ExpandoObject();
var dictionary = (IDictionary<
string
,
string
>)diarioModel;
dictionary.Add(
"ShopName"
,
"Shop"
+ i.ToString());
dictionary.Add(
"WIP"
, i.ToString());
dictionary.Add(
"CurrentRO"
, i.ToString());
dictionary.Add(
"Total"
, i.ToString());
dictionary.Add(
"Amount"
, i.ToString());
while
(continueLoop)
{
string
columnName = DateTime.Now.AddDays(limit).ToShortDateString() +
" "
+ DateTime.Now.AddDays(limit).DayOfWeek;
dictionary.Add(columnName, Convert.ToString(limit + i));
if
(limit == 7)
// No of columns (5 static + 56 dynamic)
continueLoop =
false
;
limit++;
}
var json = serializer.Serialize(dictionary);
var d = serializer.Deserialize<dynamic>(json);
data.Add(d);
}
I have mentioned all the major code here, but if want test project i can share.
For any help will much appreciated.
Thanks,
Jitender
The column field name should be valid for JavaScript and currently the name contains invalid characters. You should remove all invalid characters from the name in order for the data to be bound correctly. If you wish to show the title in a different format then you can use the Title method e.g.
table.Columns.Add(
new
DataColumn
{
ColumnName = DateTime.Now.AddDays(limit).DayOfWeek + DateTime.Now.AddDays(limit).ToShortDateString().Replace(
" "
,
""
).Replace(
"/"
,
""
),
Caption = DateTime.Now.AddDays(limit).ToShortDateString() +
" "
+ DateTime.Now.AddDays(limit).DayOfWeek,
DataType =
typeof
(
string
)
});
columns.Bound(column.DataType, column.ColumnName).Title(column.Caption).Width(50).Sortable(
true
).Filterable(
true
);
Daniel
the Telerik team

Suggestion provided by you surely the one which i wanted. BTW i have resolved this issue by using GridColumnSettings for column setting and datatable for dynamic data using MVC kendo UI grid control.
Thanks again :)
-Jitender

There isn't a way to use DataAnnotation attributes with dynamic objects.
Regards,Daniel
Telerik

I'm trying to use Vasil's example posted 21 April, 2011 but doing it all programmatically, defining the radgrid in codebehind. My grid has 2 set columns plus an 'x' number of added GridTemplateColumns only known at run time. I'm declaring the boundColumns as such
GridBoundColumn boundColumn;
boundColumn = new GridBoundColumn();
boundColumn.UniqueName = "id";
boundColumn.DataField = "id";
boundColumn.DataType = typeof(System.Int32);
boundColumn.HeaderText = "Volunteer #".Translate();
boundColumn.HeaderStyle.Width = Unit.Pixel(70);
boundColumn.Resizable = true;
grid.MasterTableView.Columns.Add(boundColumn);
boundColumn = new GridBoundColumn();
boundColumn.UniqueName = "name";
boundColumn.DataField = "name";
boundColumn.DataType = typeof(System.String);
boundColumn.HeaderText = "Name";
boundColumn.Resizable = true;
boundColumn.HeaderStyle.Width = Unit.Pixel(200);
grid.MasterTableView.Columns.Add(boundColumn);
I populate the Datasource using the same NeedDataSource but when the grid displays the cells are empty.
I noticed that there is no DataKeyNames defined, is that because using DynamicObject? is there an example showing how to build the grid totally backend (assigning to a placeholder) where the grid structure is dynamic such that the number of columns and header info is pulled from the database.
Thanks
Tim
I recommend checking out the Creating a RadGrid Programmatically documentation article which describes several approaches you can use. It is also mentioned, when creating Template Columns programmatically, the entire grid structure must be created in the code behind: Creating Template Columns Programmatically
DataKeyNames are not populated automatically, this also needs to be set by the developer at the same time the ID and other properties are defined. (example in the following code snippet: Dynamically Defining the Structure of a Statically-declared Grid)
RadGrid1.MasterTableView.DataKeyNames =
new
string
[] {
"CustomerID"
};
I hope this will be helpful.
Kind regards,
Attila Antal
Progress Telerik