This is a migrated thread and some comments may be shown as answers.

Grouping with dynamically generated types

3 Answers 122 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Greg
Top achievements
Rank 1
Greg asked on 30 Jul 2009, 05:35 PM

In my application I need to bind RadGridViews to tabular data exposed via web services where the columns may not be known at compile time. In ASP.NET the solution was to return a DataSet and bind to a DataTable, and this worked very well. In Silverlight, there is no DataSet (DataSets are proxied as instances of ArrayOfXElement which contains a couple of XML fields), so to compensate, I parse the ArrayOfXElement object and extract the columns and type data from the XML contained therein. I take this data and build a dynamic type using System.Emit namespace. The result is a type which contains a public get/set property corresponding to each column in the source datatable, with a matching type. I then populate a collection of these types using the xml data. I end up with IEnumerable<object> which I then set to the RadGridView.ItemSource, and everything works fine. The problem is, the GroupDescriptor.Version field cannot seem to be used to point to one of these dynamic properties, whereas the GridViewDataColumn.DataMemberPath has no issues in this regard. When the name of a dynamic property is specified in the GroupDescriptor.Version field, it results in an exception being thrown when ItemSource is set. See below error (note that Version is the name of the dynamic property I'm trying to group on). The source code used to generate the dynamic type is included below for interest, although the code works perfectly. The key question is why does binding the actual data to the grid columns work fine with dynamic types, but grouping does not? They should both use reflection, right?

Thanks
Greg

Webpage error details

User Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; WOW64; Trident/4.0; SLCC1; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.5.21022; .NET CLR 3.0.30618; .NET CLR 3.5.30729; MS-RTC LM 8; MS-RTC EA 2)
Timestamp: Thu, 30 Jul 2009 17:31:20 UTC

Message: Unhandled Error in Silverlight 2 Application Invalid property or field - 'Version' for type: Object   at Telerik.Windows.Data.Expressions.MemberAccessTokenExtensions.CreateMemberAccessExpression(IMemberAccessToken token, Expression instance)
   at Telerik.Windows.Data.Expressions.ExpressionFactory.MakeMemberAccess(Expression instance, String memberName)
   at Telerik.Windows.Data.Expressions.ExpressionFactory.MakeMemberAccess(Expression instance, String memberName, Boolean liftMemberAccessToNull)
   at Telerik.Windows.Data.Expressions.PropertyAccessExpressionBuilder.CreateMemberAccessExpression()
   at Telerik.Windows.Data.Expressions.MemberAccessExpressionBuilderBase.CreateLambdaExpression()
   at Telerik.Windows.Data.Expressions.GroupDescriptorExpressionBuilder.CreateGroupByExpression()
   at Telerik.Windows.Data.Expressions.GroupDescriptorExpressionBuilderBase.CreateQuery()
   at Telerik.Windows.Data.Expressions.GroupDescriptorCollectionExpressionBuilder.CreateQuery()
   at Telerik.Windows.Data.QueryableExtensions.GroupBy(IQueryable source, GroupDescriptorCollection groupDescriptors)
   at Telerik.Windows.Data.QueryableCollectionView.CreateView()
   at Telerik.Windows.Data.QueryableCollectionView.get_QueryableView()
   at Telerik.Windows.Data.QueryableCollectionView.CreateInternalList()
   at Telerik.Windows.Data.QueryableCollectionView.get_InternalList()
   at Telerik.Windows.Data.QueryableCollectionView.GetEnumerator()
   at Telerik.Windows.Data.RecordFactory.<CreateRecordsForGroupRecord>d__0.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at Telerik.Windows.Controls.GridView.GridViewDataControl.PopulateRecords()
   at Telerik.Windows.Controls.GridView.GridViewDataControl.LoadData()
   at Telerik.Windows.Controls.GridView.GridViewDataControl.<>c__DisplayClass3c.<Bind>b__3b()
   at Telerik.Windows.Controls.CursorManager.PerformTimeConsumingOperation(FrameworkElement frameworkElement, Action action)
   at Telerik.Windows.Controls.GridView.GridViewDataControl.Bind(Object newValue)
   at Telerik.Windows.Controls.GridView.GridViewDataControl.OnItemsSourceChanged(Object oldValue, Object newValue)
   at Telerik.Windows.Controls.DataControl.OnItemsSourcePropertyChanged(DependencyObject origin, DependencyPropertyChangedEventArgs args)
   at Telerik.Windows.PropertyMetadata.<>c__DisplayClass1.<Create>b__0(DependencyObject d, DependencyPropertyChangedEventArgs e)
   at System.Windows.DependencyObject.RaisePropertyChangeNotifications(DependencyProperty dp, Object newValue, Object oldValue)
   at System.Windows.DependencyObject.SetValueInternal(DependencyProperty dp, Object value, Boolean allowReadOnlySet, Boolean isSetByStyle, Boolean isSetByBuiltInStyle, PropertyInvalidationReason reason)
   at System.Windows.DependencyObject.SetValueInternal(DependencyProperty dp, Object value)
   at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value)
   at Telerik.Windows.Controls.DataControl.set_ItemsSource(Object value)
   at GFSChangeSilverlight.ChangeUI.reportSvc_ExecuteQueryCompleted(Object sender, ExecuteQueryCompletedEventArgs e)
   at GFSChangeSilverlight.ReportService.ReportServiceSoapClient.OnExecuteQueryCompleted(Object state)
Line: 1
Char: 1
Code: 0
URI: http://localhost/gfschange/Change2.aspx?mode=rfc&id=24436



private

 

static Type CreateType(IEnumerable<XElement> columnDefinitions)

 

{

 

AppDomain myDomain = AppDomain.CurrentDomain;

 

 

AssemblyName myAsmName = new AssemblyName("MyAssembly");

 

System.Reflection.Emit.

AssemblyBuilder myAssembly = myDomain.DefineDynamicAssembly(myAsmName, AssemblyBuilderAccess.Run);

 

 

ModuleBuilder myModule = myAssembly.DefineDynamicModule(myAsmName.Name);

 

 

TypeBuilder myType = myModule.DefineType("DataSource", TypeAttributes.Public);

 

 

foreach (XElement col in columnDefinitions)

 

{

 

XAttribute typeAttribute = col.Attributes().First<XAttribute>(a => a.Name.LocalName == "type");

 

 

Type propertyType;

 

 

switch (typeAttribute.Value)

 

{

 

case "xs:dateTime":

 

propertyType =

typeof(Nullable<DateTime>);

 

 

break;

 

 

case "xs:string":

 

propertyType =

typeof(String);

 

 

break;

 

 

case "xs:int":

 

propertyType =

typeof(Nullable<int>);

 

 

break;

 

 

default:

 

 

throw new Exception("Unexpected type attribute value: " + typeAttribute.Value);

 

}

 

XAttribute nameAttribute = col.Attributes().First<XAttribute>(a => a.Name.LocalName == "name");

 

 

string propertyName = nameAttribute.Value;

 

 

FieldBuilder exField = myType.DefineField("_" + propertyName, propertyType, FieldAttributes.Public);

 

 

PropertyBuilder exProperty = myType.DefineProperty(propertyName, PropertyAttributes.None, propertyType, Type.EmptyTypes);

 

 

MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;

 

 

MethodBuilder exGetMethod = myType.DefineMethod("get_" + propertyName,

 

getSetAttr,

propertyType,

 

Type.EmptyTypes);

 

 

ILGenerator getIlgen = exGetMethod.GetILGenerator();

 

getIlgen.Emit(

OpCodes.Ldarg_0);

 

getIlgen.Emit(

OpCodes.Ldfld, exField);

 

getIlgen.Emit(

OpCodes.Ret);

 

exProperty.SetGetMethod(exGetMethod);

 

MethodBuilder exSetMethod = myType.DefineMethod("set_" + propertyName,

 

getSetAttr,

 

null,

 

 

new Type[] { propertyType });

 

 

ILGenerator setIlgen = exSetMethod.GetILGenerator();

 

setIlgen.Emit(

OpCodes.Ldarg_0);

 

setIlgen.Emit(

OpCodes.Ldarg_1);

 

setIlgen.Emit(

OpCodes.Stfld, exField);

 

setIlgen.Emit(

OpCodes.Ret);

 

exProperty.SetSetMethod(exSetMethod);

}

 

return myType.CreateType();

 

}

 

 

3 Answers, 1 is accepted

Sort by
0
Accepted
Vlad
Telerik team
answered on 31 Jul 2009, 05:11 AM
Hello Greg,

You can use my DataTable and everything will work as expected :)

Kind regards,
Vlad
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
0
E
Top achievements
Rank 1
answered on 29 Sep 2010, 12:06 AM
Hello Greg. Currently I'm having the same problem . Do you have a sample project with the solution you applied?
Thank you very much,

Regards,
0
jfkrueger
Top achievements
Rank 1
answered on 26 Nov 2011, 07:44 PM
That's great but I would still like to hear an answer to the original question without having to completely restructure my data.
Tags
GridView
Asked by
Greg
Top achievements
Rank 1
Answers by
Vlad
Telerik team
E
Top achievements
Rank 1
jfkrueger
Top achievements
Rank 1
Share this question
or