Powered by MSDN

US - English
NEW! Silverlight 5 is available Learn More

Issue Binding XML to DataGrid RSS

6 replies

Last post Jan 06, 2009 08:45 AM by avtar

(0)
  • WJamesLord

    WJamesLord

    Member

    138 Points

    121 Posts

    Issue Binding XML to DataGrid

    Mar 14, 2008 12:15 AM | LINK

    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

    138 Points

    121 Posts

    Re: Issue Binding XML to DataGrid

    Mar 14, 2008 11:17 AM | LINK

    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

    138 Points

    121 Posts

    Re: Issue Binding XML to DataGrid

    Mar 14, 2008 01:44 PM | LINK

    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

    28 Points

    19 Posts

    Re: Re: Issue Binding XML to DataGrid

    Mar 19, 2008 05:23 PM | LINK

    Hey bro,

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

    Thanx in advance

  • GunnarHoffmann

    GunnarHoffmann

    Member

    4 Points

    2 Posts

    Re: Issue Binding XML to DataGrid

    Apr 28, 2008 06:23 PM | LINK

     Can you please provide the source code for this problem?

     

    Thanks in advance

     GH
     

  • avtar

    avtar

    Participant

    777 Points

    208 Posts

    Re: Issue Binding XML to DataGrid

    Jan 06, 2009 04:35 AM | LINK

    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

    Participant

    777 Points

    208 Posts

    Re: Issue Binding XML to DataGrid

    Jan 06, 2009 08:45 AM | LINK

    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.