Skip to main content

Microsoft Silverlight

Answered Question Issue Binding XML to DataGridRSS Feed

(0)

WJamesLord
WJamesLord

Member

Member

138 points

118 Posts

Issue Binding XML to DataGrid

I have web services that return XML defining columns and rows for a result set.  Each set contains a variable number of columns and rows.  I need to bind such contents to a DataGrid.  However, the ItemSource property takes a collection data objects with each object essentially a struct or class detailing the members that should be displayed on each row of the grid.  I've tried parsing the XML into a collection of rows with each row defined by an array of objects.  For example: object[][] or List<object[]>.  However, when I assign such a list to the ItemSource, it fails to bind.  I've also tried creating a list of dynamic row objects.  Each row object is a dynamic class created by reflection via Emit that holds all the columns for a row.  Binding this list to the DataGrid.ItemSource property also fails.

How do I dynamically assign a collection of rows to a DataGrid without using a pre-defined class or struct to hold the contents of each row?

W James

 

WJamesLord
WJamesLord

Member

Member

138 points

118 Posts

Answered Question

Re: Issue Binding XML to DataGrid

Perhaps the problem is in the code that generates the class used to hold the data for each row in the generic list.  Here's the method in the data class that takes the contents of the column collection, generates the dynamic data object, and then builds a collection of such objects for each row.

public object[] CreateItemsSource()

{

if (_RowClass == null)

{

AssemblyName an = new AssemblyName("Result" + this.GetHashCode());

AssemblyBuilder assemblyBuilder =

AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);

ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");

TypeBuilder tb = moduleBuilder.DefineType("RowType" + this.GetHashCode()

, TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass

| TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.AutoLayout

, typeof(object));

ConstructorBuilder constructor = tb.DefineDefaultConstructor(

MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);

Dictionary<string, ColumnInfo>.Enumerator columns = GetColumnEnumerator();while (columns.MoveNext())

{

ColumnInfo info = columns.Current.Value;

tb.DefineField(info.ColumnName.Replace(' ', '_'), info.DataType, FieldAttributes.Public);

}

_RowClass = tb.CreateType();

}

object[] itemsSource = new object[_ResultSet.Count];for (int rowIdx = 0; rowIdx < _ResultSet.Count; rowIdx++)

{

object row = Activator.CreateInstance(_RowClass);

Dictionary<string, ColumnInfo>.Enumerator columns = GetColumnEnumerator();while (columns.MoveNext())

{

ColumnInfo info = columns.Current.Value;

FieldInfo field = _RowClass.GetField(info.ColumnName.Replace(' ', '_'));

object val = _ResultSet[rowIdx][info.Index];

field.SetValue(row, ChangeType(val, field.FieldType));

}

itemsSource[rowIdx] = row;

}

return itemsSource;

}

 

If anyone can provide insight into this issue, I'd be very grateful.

Thanks much,

W James

 

WJamesLord
WJamesLord

Member

Member

138 points

118 Posts

Answered Question

Re: Issue Binding XML to DataGrid

Woot!  Solved my own problem!  The DataGrid uses reflection on properties NOT fields.  I changed my dynamic type to provide properties and the DataGrid binding issue was resolved.

W James

 

dotnetmac
dotnetmac

Member

Member

28 points

19 Posts

Re: Re: Issue Binding XML to DataGrid

Hey bro,

i have the same issue with my project, can you please post the code.

Thanx in advance

GunnarHoffmann
GunnarHo...

Member

Member

4 points

2 Posts

Re: Issue Binding XML to DataGrid

 Can you please provide the source code for this problem?

 

Thanks in advance

 GH
 

avtar
avtar

Member

Member

63 points

69 Posts

Re: Issue Binding XML to DataGrid

Hello and a very happy new year to all.

I have the same problem and able to solve the issue using WJAMESLORD method with little changes.

I have used property instead of field.

But i put this functionality at server side (WCF) and my service method return arry of Object. I am posting my code, please feel free to comment on this.

           //method called by silverlight client... (WCF service method)  
public object[]  GetComponentData(string queryString, bool authflag) 
{

DataTable dt = ComponentHelper.GetComponentData(queryString, ref authflag);
dt.TableName = "IterationResult";
Object[] rows = CreateItemsSource(dt); // method used to convert datatable row to object.
return rows; // return Object array to silverlight client
}

private object[] CreateItemsSource(DataTable dt)
{
Type _RowClass;
AssemblyName an = new AssemblyName("Result" + this.GetHashCode());
System.Reflection.Emit.AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
TypeBuilder tb = moduleBuilder.DefineType("RowType" + this.GetHashCode(), TypeAttributes.Public |
TypeAttributes.Class |
TypeAttributes.AutoClass |
TypeAttributes.AnsiClass |
TypeAttributes.BeforeFieldInit |
TypeAttributes.AutoLayout
, typeof(object));

ConstructorBuilder constructor = tb.DefineDefaultConstructor( MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);
IEnumerator columns = dt.Columns.GetEnumerator();
while (columns.MoveNext())
{
DataColumn info = (DataColumn)columns.Current;
FieldBuilder field= tb.DefineField(info.ColumnName.Replace(' ', '_'), info.DataType, FieldAttributes.Private);
PropertyBuilder propBldr = tb.DefineProperty(info.ColumnName.Replace(' ', '_'), System.Reflection.PropertyAttributes.HasDefault,info.DataType, new Type[]{info.DataType});
// The property set and property get methods require a special
// set of attributes.

MethodAttributes getSetAttr = MethodAttributes.Public;
// Define the "get" accessor method for CustomerName.
MethodBuilder getPropMthdBldr =
tb.DefineMethod("get_"+info.ColumnName,
getSetAttr,
info.DataType,
new Type[] { });
ILGenerator custNameGetIL = getPropMthdBldr.GetILGenerator();

custNameGetIL.Emit(OpCodes.Ldarg_0);
custNameGetIL.Emit(OpCodes.Ldfld, field);
custNameGetIL.Emit(OpCodes.Ret);

// Define the "set" accessor method for CustomerName.
MethodBuilder setPropMthdBldr =
tb.DefineMethod("set_"+info.ColumnName,
getSetAttr,
null,
new Type[] { info.DataType });
ILGenerator custNameSetIL = setPropMthdBldr.GetILGenerator();

custNameSetIL.Emit(OpCodes.Ldarg_0);
custNameSetIL.Emit(OpCodes.Ldarg_1);
custNameSetIL.Emit(OpCodes.Stfld, field);
custNameSetIL.Emit(OpCodes.Ret);

// Last, we must map the two methods created above to our PropertyBuilder to
// their corresponding behaviors, "get" and "set" respectively.

propBldr.SetGetMethod(getPropMthdBldr);
propBldr.SetSetMethod(setPropMthdBldr);

}
_RowClass = tb.CreateType();
object[] itemsSource = new object[dt.Rows.Count];
for (int rowIdx = 0; rowIdx < dt.Rows.Count; rowIdx++)
{
object row = Activator.CreateInstance(_RowClass);
columns = dt.Columns.GetEnumerator();
int i = 0;
while (columns.MoveNext())
{
DataColumn info = (DataColumn)columns.Current;

PropertyInfo field = _RowClass.GetProperty(info.ColumnName.Replace(' ', '_'));
object val = dt.Rows[rowIdx][i++];
//IFormatProvider format =
// new CultureInfo("en-GB", true);

field.SetValue(row, Convert.ChangeType(val, field.PropertyType),null);
}

itemsSource[rowIdx] = row;
}
return itemsSource;
}
 

Thanks to all.

Avtar.

Please click on "Mark As Answer", if this answered your query partially or fully.

avtar
avtar

Member

Member

63 points

69 Posts

Re: Issue Binding XML to DataGrid

Hi, 

now my wcf method return array of Object..i.e (object[]) but getting Communication Exception at client side.

http://silverlight.net/forums/t/63057.aspx

 

Avtar.

Please click on "Mark As Answer", if this answered your query partially or fully.
  • Unanswered Question
  • Answered Question
  • Announcement
Microsoft Communities