2017-11-30 3 views
1

DataGridviewにデータを追加するクラスにデータを動的に追加する必要があります。以下はテストコードです。私はdatagridviewでフォームを作成し、データセットの各プロパティに対応するdatapropertynamesを使用して、必要な順番で列を手動で追加しました。しかし、datagridviewはそれらを並べ替え、私は理由を理解できません。私はdata2、data1、CustomerNameの順序を持​​つようにdatagridviewを設定しますが、customernameはdata2とdata1の間を移動し続けます。私はこれが奇妙に見えるかもしれないことを知っていますが、これは単なる概念のテストに過ぎません。実装では、他の列のデータに基づいて計算される列がありますが、それらの列はデータにバインドされていないためソート可能ではありません。ですから、私はこれを動作させるために、またはソート可能なように計算された列のデータをバインドする方法が必要です。ありがとうC#動的にデータグリッドビューの順序でプロパティを追加する

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; } 
} 
+0

「動的」を使用できませんか? https://stackoverflow.com/questions/5573856/binding-a-gridview-to-a-dynamic-or-expandoobject-object/6298704#6298704 –

+0

を参照してください。ただし、データがオブジェクトに大きく依存する場合があります。そのオブジェクトのメソッドは、私はそれを私は基本的なコードの変更(数千行)せずにデータテーブルに変換する方法がないので、私は基本クラスを派生し、プロパティをプログラムで追加する必要があります。 – lesyriad

答えて

0

この問題を解決するには、自動生成列を無効にしてください。 datagridviewが作成したカラムをクリアして、データソースから新しいカラムを生成していたようです。

関連する問題