Silverlight 动态创建类并绑定DataGrid Column及ItemSource

阅读更多

        使用Silverlight开发前台页面,需要将后台查询回的集合绑定到前台的DataGrid上。

        一般情况下,我们都有定义好的实体类Po,然后可以.xaml文件中固定绑定Po的成员变量到DataGrid的列上,当取到实体集合时直接将 dataGrid.itemsource = List 即可。

        但有些时候,我们并不知道返回的集合中的实体是什么类型,无法预先定义PO,那么该如何动态绑定列和集合呢?

         想到一个方法就是在拿到集合后通过反射动态的创建PO类,动态添加public属性,并动态绑定到DataGrid Column。然后再绑定实体集合就可实现需求。

         首先在工程中添加动态类型工厂类 DynamicTypeBuilder:

 public class DynamicTypeBuilder
    {
        TypeBuilder tb;
        /// 
        /// 构造函数
        /// 
        /// 动态类型的名称
        public DynamicTypeBuilder(string typeNm)
        {
            // 在 Silverlight 中 AssemblyBuilderAccess 没有 RunAndSave
            AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(
                new AssemblyName("TempAssembly"), AssemblyBuilderAccess.Run);

            ModuleBuilder mb = ab.DefineDynamicModule("TempModule");
            this.tb = mb.DefineType(typeNm, TypeAttributes.Public);
        }
        /// 
        /// 添加一个public的可读写属性,并且会创建对应的名为 propertyNm + "Field" 的私有字段
        /// 
        /// 
        /// 
        public void AppendPublicProperty(string propertyNm, Type type)
        {
            this.AppendPublicProperty(propertyNm, type, true, true);
        }
        /// 
        /// 添加一个public属性,并且会创建对应的名为 propertyNm + "Field" 的私有字段
        /// 
        /// 
        /// 
        /// 是否实现getter
        /// 是否实现setter
        public void AppendPublicProperty(string propertyNm, Type type, bool canGet, bool canSet)
        {
            FieldBuilder field = this.tb.DefineField(string.Format("{0}Field", propertyNm), type, FieldAttributes.Private);

            PropertyBuilder property = tb.DefineProperty(propertyNm, PropertyAttributes.HasDefault, type, null);

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

            if (canGet)
            {
                MethodBuilder getAccessor = tb.DefineMethod(string.Format("get_{0}", propertyNm), getSetAttr, type, Type.EmptyTypes);
                ILGenerator getIL = getAccessor.GetILGenerator();
                // For an instance property, argument default is the instance. Load the
                // instance, then load the private field and return, leaving the
                // field value on the stack.
                getIL.Emit(OpCodes.Ldarg_0);
                getIL.Emit(OpCodes.Ldfld, field);
                getIL.Emit(OpCodes.Ret);
                property.SetGetMethod(getAccessor);
            }

            if (canSet)
            {
                MethodBuilder setAccessor = tb.DefineMethod(string.Format("set_{0}", propertyNm), getSetAttr, null, new Type[] { type });
                setAccessor.DefineParameter(1, ParameterAttributes.None, "value");
                ILGenerator setIL = setAccessor.GetILGenerator();
                // Load the instance and then the numeric argument, then store the
                // argument in the field.
                setIL.Emit(OpCodes.Ldarg_0);
                setIL.Emit(OpCodes.Ldarg_1);
                setIL.Emit(OpCodes.Stfld, field);
                setIL.Emit(OpCodes.Ret);
                property.SetSetMethod(setAccessor);
            }
        }
        /// 
        /// 在添加完各个 public 属性之后,调用此方法以完成对动态类型的定义并加载之,
        /// 此后通过 Activator.CreateInstance() 便可实例化动态类型
        /// 
        /// 
        public Type CreateDynamicType()
        {
            return this.tb.CreateType();
        }
    }

 

    有了它我们就可以动态创建类了。

      

DynamicTypeBuilder dyClass = new DynamicTypeBuilder("dy");//创建动态类,dy可以随便替换
                    datagrid.Columns.Clear();//清空datagrid的已有列
                    .......
                    //ColInfos为已经取到的列信息集合
                        foreach (ColInfo colInfo in colInfos)
                        {
                            String name = colInfo.name;//列绑定名
                            String title = colInfo.title;//列显示名
                            DataGridTextColumn dtc = new DataGridTextColumn();//动态创建列,完成绑定
                            dtc.Header = name;
                            dtc.Binding = new Binding("_" + name);
                            this.datagrid.Columns.Add(dtc);//添加列
                            dyClass.AppendPublicProperty("_" + name, typeof(string));//同时动态添加公共属性到自定义类
                        }
                        Type dyType = dyClass.CreateDynamicType();//创建自定义类
                ........
             //构造绑定DataGrid ItemSource的集合
              List datas = new List();
                        var po = Activator.CreateInstance(dyType);//创建自定义类实例
                            
                           
                       PropertyInfo property = dyType.GetProperty("_" + colInfos[i].name);
                               
                        property.SetValue(po, [value], null);
                       datas.add(po);
 
                     dataGrid.itemsource = datas   

                        } 
  

 

你可能感兴趣的:(silverlight,ice,java)