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 顺序混淆的主要内容,如果未能解决你的问题,请参考以下文章