0

I have created several Datagrids dynamically. In the mode of dynamic Datagrid creation the number and name of columns are not known in advance.

So, I created a DataGrid like below :

DataGrid grid = new DataGrid();
grid.Columns.Add(new DataGridTextColumn() { Header = randomHeader1 });
grid.Columns.Add(new DataGridTextColumn() { Header = randomHeader2 });
grid.Columns.Add(new DataGridTextColumn() { Header = randomHeader3 });
// The number of columns for each datagrid is variable

How can I add rows to my Datagrid? For instance, I want to add those 3 rows to Dtatagrid that I have defined in the top:

  1. a, b, c
  2. d, e, f
  3. g, h, i

I tried to solve my problem like below but it is not working:

grid.Items.Add(new Object[] { "a", "b", "c" });
grid.Items.Add(new Object[] { "d", "e", "f" });
grid.Items.Add(new Object[] { "g", "h", "i" });

Please review the code and provide me solution.

Gul Ershad
  • 1,743
  • 2
  • 25
  • 32
steacker
  • 127
  • 1
  • 10

1 Answers1

0

Using reflection, you could create a collection of dynamic objects, then bind your DataGrid to it.

There is a great answer here about creating dynamic classes:

How to dynamically create a class in C#?

Using this, you can create the list of properties (which will be columns in your datagrid) at runtime like this

List<TypeBuilderNamespace.Field> myFields = new List<TypeBuilderNamespace.Field>();
myFields.Add( new TypeBuilderNamespace.Field("FirstName", Type.GetType("System.String")));
myFields.Add( new TypeBuilderNamespace.Field("Surname", Type.GetType("System.String")));
myFields.Add( new TypeBuilderNamespace.Field("Age", Type.GetType("System.Int32")));

Then dynamically create your class

Type myDynamicType = TypeBuilderNamespace.MyTypeBuilder.CompileResultType(myFields);

Create some sample data

List<dynamic> people = new List<dynamic>();
dynamic person1 = Activator.CreateInstance(myDynamicType);
person1.FirstName = "John";
person1.Surname = "Smith";
person1.Age = 45;
people.Add(person1);

dynamic person2 = Activator.CreateInstance(myDynamicType);
person2.FirstName = "Emma";
person2.Surname = "Jones";
person2.Age = 18;
people.Add(person2);

Then bind your data to the grid

DataGrid grid = new DataGrid();
grid.AutoGenerateColumns = true;
grid.ItemsSource = people;

This gives the following DataGrid

enter image description here

I modified the code in the answer quoted above slightly, so here is my listing of that for completeness:

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;

namespace TypeBuilderNamespace {
    public class Field {
        public String FieldName { get; set; }
        public Type FieldType { get; set; }

        public Field(String name, Type type) {
            FieldName = name;
            FieldType = type;
        }
    }

    public static class MyTypeBuilder {                
        public static Type CompileResultType(List<Field> fields) {
            TypeBuilder tb = GetTypeBuilder();
            ConstructorBuilder constructor = tb.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);

            FieldName(string) and FieldType(Type)
            foreach (var field in fields)
                CreateProperty(tb, field.FieldName, field.FieldType);

            Type objectType = tb.CreateType();
            return objectType;
        }

        private static TypeBuilder GetTypeBuilder() {
            var typeSignature = "MyDynamicType";
            var an = new AssemblyName(typeSignature);
            AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
            TypeBuilder tb = moduleBuilder.DefineType(typeSignature
                            , TypeAttributes.Public |
                            TypeAttributes.Class |
                            TypeAttributes.AutoClass |
                            TypeAttributes.AnsiClass |
                            TypeAttributes.BeforeFieldInit |
                            TypeAttributes.AutoLayout
                            , null);
            return tb;
        }

        private static void CreateProperty(TypeBuilder tb, string propertyName, Type propertyType) {
            FieldBuilder fieldBuilder = tb.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);

            PropertyBuilder propertyBuilder = tb.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);
            MethodBuilder getPropMthdBldr = tb.DefineMethod("get_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, propertyType, Type.EmptyTypes);
            ILGenerator getIl = getPropMthdBldr.GetILGenerator();

            getIl.Emit(OpCodes.Ldarg_0);
            getIl.Emit(OpCodes.Ldfld, fieldBuilder);
            getIl.Emit(OpCodes.Ret);

            MethodBuilder setPropMthdBldr =
            tb.DefineMethod("set_" + propertyName,
              MethodAttributes.Public |
              MethodAttributes.SpecialName |
              MethodAttributes.HideBySig,
              null, new[] { propertyType });

            ILGenerator setIl = setPropMthdBldr.GetILGenerator();
            Label modifyProperty = setIl.DefineLabel();
            Label exitSet = setIl.DefineLabel();

            setIl.MarkLabel(modifyProperty);
            setIl.Emit(OpCodes.Ldarg_0);
            setIl.Emit(OpCodes.Ldarg_1);
            setIl.Emit(OpCodes.Stfld, fieldBuilder);

            setIl.Emit(OpCodes.Nop);
            setIl.MarkLabel(exitSet);
            setIl.Emit(OpCodes.Ret);

            propertyBuilder.SetGetMethod(getPropMthdBldr);
            propertyBuilder.SetSetMethod(setPropMthdBldr);
        }
    }
}
Community
  • 1
  • 1
Gary Wright
  • 2,441
  • 1
  • 20
  • 32