C# 动态添加的属性与 datagridview 顺序混淆

Posted

技术标签:

【中文标题】C# 动态添加的属性与 datagridview 顺序混淆【英文标题】:C# dynamically added property messes with datagridview order 【发布时间】:2017-11-30 06:47:47 【问题描述】:

所以我需要动态地将数据添加到将填充数据网格视图的类中。下面是测试代码。我创建了一个带有 datagridview 的表单,并按照我想要的顺序手动添加了与数据集中每个属性对应的 datapropertynames 列。但是 datagridview 对它们重新排序,我不知道为什么。我将 datagridview 设置为 data2、data1、CustomerName 的顺序,但 customername 一直在 data2 和 data1 之间移动。我知道这可能看起来很奇怪,但这只是对这个概念的测试。实现是我的列是根据其他列中的数据计算的,但这些列不可排序,因为它们没有绑定到数据。所以我需要这个工作或一种方法来绑定计算列中的数据,以便它可以排序。谢谢

public partial class Form1 : Form

    public Form1()
    
        InitializeComponent();
    
    public static Type BuildDynamicTypeWithProperties()
    
        AppDomain myDomain = Thread.GetDomain();
        AssemblyName myAsmName = new AssemblyName();
        myAsmName.Name = "MyDynamicAssembly";

        // To generate a persistable assembly, specify AssemblyBuilderAccess.RunAndSave.
        AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly(myAsmName,
                                                        AssemblyBuilderAccess.RunAndSave);
        // Generate a persistable single-module assembly.
        ModuleBuilder myModBuilder =
            myAsmBuilder.DefineDynamicModule(myAsmName.Name, myAsmName.Name + ".dll");



        TypeBuilder myTypeBuilder = myModBuilder.DefineType("CustomerData",
                                                        TypeAttributes.Public);
        myTypeBuilder.SetParent(typeof(TestData));

        FieldBuilder customerNameBldr = myTypeBuilder.DefineField("customerName",
                                                        typeof(string),
                                                        FieldAttributes.Private);

        // The last argument of DefineProperty is null, because the
        // property has no parameters. (If you don't specify null, you must
        // specify an array of Type objects. For a parameterless property,
        // use an array with no elements: new Type[] )
        PropertyBuilder custNamePropBldr = myTypeBuilder.DefineProperty("CustomerName",
                                                         System.Reflection.PropertyAttributes.HasDefault,
                                                         typeof(string),
                                                         null);

        // The property set and property get methods require a special
        // set of attributes.
        MethodAttributes getSetAttr =
            MethodAttributes.Public | MethodAttributes.SpecialName |
                MethodAttributes.HideBySig;

        // Define the "get" accessor method for CustomerName.
        MethodBuilder custNameGetPropMthdBldr =
            myTypeBuilder.DefineMethod("get_CustomerName",
                                       getSetAttr,
                                       typeof(string),
                                       Type.EmptyTypes);

        ILGenerator custNameGetIL = custNameGetPropMthdBldr.GetILGenerator();

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

        // Define the "set" accessor method for CustomerName.
        MethodBuilder custNameSetPropMthdBldr =
            myTypeBuilder.DefineMethod("set_CustomerName",
                                       getSetAttr,
                                       null,
                                       new Type[]  typeof(string) );

        ILGenerator custNameSetIL = custNameSetPropMthdBldr.GetILGenerator();

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

        // Last, we must map the two methods created above to our PropertyBuilder to 
        // their corresponding behaviors, "get" and "set" respectively. 
        custNamePropBldr.SetGetMethod(custNameGetPropMthdBldr);
        custNamePropBldr.SetSetMethod(custNameSetPropMthdBldr);


        Type retval = myTypeBuilder.CreateType();

        // Save the assembly so it can be examined with Ildasm.exe,
        // or referenced by a test program.
        myAsmBuilder.Save(myAsmName.Name + ".dll");
        return retval;
    
    private void Form1_Load(object sender, EventArgs e)
    
        Type custDataType = BuildDynamicTypeWithProperties();

        PropertyInfo[] custDataPropInfo = custDataType.GetProperties();
        foreach (PropertyInfo pInfo in custDataPropInfo)
        
            Console.WriteLine("Property '0' created!", pInfo.ToString());
        

        Console.WriteLine("---");
        // Note that when invoking a property, you need to use the proper BindingFlags -
        // BindingFlags.SetProperty when you invoke the "set" behavior, and 
        // BindingFlags.GetProperty when you invoke the "get" behavior. Also note that
        // we invoke them based on the name we gave the property, as expected, and not
        // the name of the methods we bound to the specific property behaviors.

        object custData = Activator.CreateInstance(custDataType);

        ((TestData)custData).data1 = "This Works";
        ((TestData)custData).data2 = "This Works 2";
        custDataType.InvokeMember("CustomerName", BindingFlags.SetProperty,
                                      null, custData, new object[]  "Joe User" );
        var list = new List<object>();

        /* var1.data1 = "Hello";
         var1.data2 = "World";
         list.Add(var1);*/
        list.Add(custData);
        dataGridView1.DataSource = list;

    

    private void button1_Click(object sender, EventArgs e)
    
        var test = dataGridView1.Rows[0].DataBoundItem;
    


public class TestData

    public string data1  get; set; 
    public string data2  get; set; 
 

【问题讨论】:

不能用dynamic吗?见***.com/questions/5573856/… 这在某些情况下可能有效,但是数据在很大程度上依赖于该对象中的对象和方法,因此我无法在没有重大代码更改的情况下将其转换为数据表(几千行)所以我需要派生基类并以编程方式添加属性。 【参考方案1】:

结果是通过禁用 autogeneratecolumns 修复了它。似乎 datagridview 正在清除我创建的列并从数据源生成新列。

【讨论】:

以上是关于C# 动态添加的属性与 datagridview 顺序混淆的主要内容,如果未能解决你的问题,请参考以下文章

C# DataGridView控件动态添加新行

求用c#在dataGridView中动态添加列的方法

C# winfrom datagridview 怎样实现 如图效果 程序动态添加数据呢?

C# 如何动态更新DataGridView

C# datagridview 如何显示动态图片

C# 怎么把数组中的数据添加到datagridview中