首页 新闻 会员 周边

关于telerik asp.net mvc grid组件的问题

0
悬赏园豆:100 [已解决问题] 解决于 2012-01-09 15:05

各位好:

如下代码所示:Order类无法事先定义好其属性或字段,因为其字段是根据客户需要动态配置的,代码期间无法确定,所以我采用了dictionary 来存储订单的相关数据, 并添加了一个this索引器,但是我未找到方法绑定到Telerik Grid控件,错误提示为: Invalid property or field - 'id' for type: Order。

另外我发现telerik可以绑定到DataTable的Datarow,而datarow也是动态构造的,内部采用了一个public object[] ItemArray { get; set; }来存储行的数据,也有一个this索引器,我感觉绑定是this索引器起了作用,我觉得应该可以找到类似的解决办法。

谁知道如何解决这个问题?

代码如下:

 

Model:

 1 public class Order
2
3 {
4
5 public Dictionary<string, object> Data = new Dictionary<string, object>();
6
7 public object this[string columnName]
8
9 {
10
11 get
12
13 {
14
15 object temp;
16
17 if (Data.TryGetValue(columnName, out temp) == true)
18
19 {
20
21 return temp;
22
23 }
24
25 return null;
26
27 }
28
29 set
30
31 {
32
33 if (Data.ContainsKey(columnName) == true)
34
35 Data.Remove(columnName);
36
37 Data.Add(columnName, value);
38
39 }
40
41 }
42
43 }

 ViewModel:

1 public class OrdersViewModel   
 {        
public List<Order> Data = new List<Order>();   
public IEnumerable<GridColumnSettings> Columns { get; set; }    
}

 

Controller:

 1 public class HomeController : Controller
2
3 {
4
5 public ActionResult Index()
6
7 {
8
9 ViewBag.Message = "Welcome to ASP.NET MVC!";
10
11
12
13 OrdersViewModel model = new OrdersViewModel();
14
15
16
17 Order order1 = new Order();
18
19 order1.Data.Add("id", "1");
20
21 order1.Data.Add("customer", "customer1");
22
23 order1.Data.Add("qty", "100");
24
25 model.Data.Add(order1);
26
27
28
29 Order order2 = new Order();
30
31 order2.Data.Add("id", "2");
32
33 order2.Data.Add("customer", "customer2");
34
35 order2.Data.Add("qty", "200");
36
37 model.Data.Add(order2);
38
39
40
41 model.Columns = this.columns();
42
43
44
45 return View(model);
46
47 }
48
49
50
51 public ActionResult About()
52
53 {
54
55 return View();
56
57 }
58
59
60
61
62
63 public List<GridColumnSettings> columns()
64
65 {
66
67 List<GridColumnSettings> columns = new List<GridColumnSettings>();
68
69
70
71 GridColumnSettings columnSettings;
72
73
74
75 columnSettings = new GridColumnSettings();
76
77 columnSettings.Member = "id";
78
79 columnSettings.Title = "id";
80
81 columnSettings.MemberType = typeof(String);
82
83 columns.Add(columnSettings);
84
85
86
87 columnSettings = new GridColumnSettings();
88
89 columnSettings.Member = "customer";
90
91 columnSettings.Title = "customer";
92
93 columnSettings.MemberType = typeof(String);
94
95 columns.Add(columnSettings);
96
97
98
99 columnSettings = new GridColumnSettings();
100
101 columnSettings.Member = "qty";
102
103 columnSettings.Title = "qty";
104
105 columnSettings.MemberType = typeof(int);
106
107 columns.Add(columnSettings);
108
109
110
111 return columns;
112
113 }
114
115 }

 

View:

 1 @model TelerikMvcApplication1.ViewModels.OrdersViewModel
2
3 @{
4
5 ViewBag.Title = "Home Page";
6
7 }
8
9
10
11 <h2>@ViewBag.Message</h2>
12
13 <p>
14
15 To learn more about ASP.NET MVC visit <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>.
16
17 </p>
18
19
20
21 @(
22
23 Html.Telerik().Grid(Model.Data.AsEnumerable())
24
25 .Name("Grid")
26
27 .Columns(columns =>
28
29 {
30
31 columns.LoadSettings(Model.Columns as IEnumerable<GridColumnSettings>);
32
33 })
34
35 .Reorderable(resizing => resizing.Columns(true))
36
37 .Resizable(resizing => resizing.Columns(true))
38
39 .Groupable(grouping => grouping.Enabled((bool)true))
40
41 .Sortable()
42
43 .Groupable()
44
45 .Footer(true)
46
47 )

 代码可以在http://www.telerik.com/community/forums/aspnet-mvc/grid/can-grid-bind-to-dictionary.aspx下载。

冰绿茶——的主页 冰绿茶—— | 初学一级 | 园豆:6
提问于:2011-12-25 22:03
< >
分享
最佳答案
0

呃,我想你的问题大致是这样的,你的Order类中的属性是用户自己配置的,所以属性不确定,然后你在这个Order类中用了一个Dcitionary来存储了用户的配置,然后你希望Grid控件自动生成用户配置的那些属性。

关键问题就是,怎样动态创建这个Order类!所以

View Code
  1  public static List<object> ToDataSource(DataTable t4Dt)  
2 {
3 if (t4Dt.Rows.Count == 0)
4 {
5 throw new ArgumentException("DataTable cannot be null");
6 }
7
8 Type objectType = null;
9 TypeBuilder tb = GetTypeBuilder(t4Dt.GetHashCode());
10
11 ConstructorBuilder constructor = tb.DefineDefaultConstructor(
12
13 MethodAttributes.Public |
14
15 MethodAttributes.SpecialName |
16
17 MethodAttributes.RTSpecialName);
18
19 foreach (DataColumn pair in t4Dt.Columns)
20 {
21 CreateProperty(
22 tb,
23 Convert.ToString(pair.ColumnName),
24 pair.ColumnName == null ? typeof(object) : pair.DataType);
25 }
26 objectType = tb.CreateType();
27 return GenerateArray(objectType,t4Dt);
28 }
29
30 private static List<object> GenerateArray(Type objectType,DataTable t4Dt)
31 {
32 var itemsSource = new List<object>();
33
34 foreach (DataRow currentDict in t4Dt.Rows)
35 {
36 if (currentDict == null)
37 {
38 throw new ArgumentException("IDictionary entry cannot be null");
39 }
40
41 object row = Activator.CreateInstance(objectType);
42
43 foreach (DataColumn pair in t4Dt.Columns)
44 {
45 if (currentDict.OwnerTable.Columns.Contains(pair.ColumnName))
46 {
47 PropertyInfo property = objectType.GetProperty(Convert.ToString(pair.ColumnName));
48 if (currentDict[pair.ColumnName] != null)
49 {
50 Type typeInfo = property.PropertyType;
51 CheckTypeInfo(property.PropertyType, out typeInfo);
52 property.SetValue
53 (
54 row,
55 Convert.ChangeType(currentDict[pair.ColumnName], typeInfo, null),
56 null
57 );
58 }
59 }
60 }
61
62 itemsSource.Add(row);
63 }
64 return itemsSource;
65 }
66
67 private static TypeBuilder GetTypeBuilder(int code)
68 {
69 AssemblyName an = new AssemblyName("TempAssembly" + code);
70
71 AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
72
73 ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
74
75 TypeBuilder tb = moduleBuilder.DefineType(
76
77 "TempType" + code,
78
79 TypeAttributes.Public |
80
81 TypeAttributes.Class |
82
83 TypeAttributes.AutoClass |
84
85 TypeAttributes.AnsiClass |
86
87 TypeAttributes.BeforeFieldInit | TypeAttributes.AutoLayout,
88
89 typeof(object));
90
91 return tb;
92 }
93
94 private static void CreateProperty(TypeBuilder tb, string propertyName, Type propertyType)
95 {
96 FieldBuilder fieldBuilder = tb.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);
97
98 PropertyBuilder propertyBuilder = tb.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);
99
100 MethodBuilder getPropMthdBldr = tb.DefineMethod(
101
102 "get_" + propertyName,
103
104 MethodAttributes.Public |
105
106 MethodAttributes.SpecialName |
107
108 MethodAttributes.HideBySig,
109
110 propertyType, Type.EmptyTypes);
111
112 ILGenerator getIL = getPropMthdBldr.GetILGenerator();
113
114 getIL.Emit(OpCodes.Ldarg_0);
115
116 getIL.Emit(OpCodes.Ldfld, fieldBuilder);
117
118 getIL.Emit(OpCodes.Ret);
119
120 MethodBuilder setPropMthdBldr = tb.DefineMethod(
121
122 "set_" + propertyName,
123
124 MethodAttributes.Public |
125
126 MethodAttributes.SpecialName |
127
128 MethodAttributes.HideBySig,
129
130 null, new Type[] { propertyType });
131
132 ILGenerator setIL = setPropMthdBldr.GetILGenerator();
133
134 setIL.Emit(OpCodes.Ldarg_0);
135
136 setIL.Emit(OpCodes.Ldarg_1);
137
138 setIL.Emit(OpCodes.Stfld, fieldBuilder);
139
140 setIL.Emit(OpCodes.Ret);
141
142 propertyBuilder.SetGetMethod(getPropMthdBldr);
143
144 propertyBuilder.SetSetMethod(setPropMthdBldr);
145 }

只要动态的把Order类生成就能解决你那个问题了。

收获园豆:100
Sharp_Knife | 初学一级 |园豆:24 | 2011-12-26 17:24

非常感谢南京——耗子的回复,此方法应该属于不得已的办法。打算放弃telerik asp.net mvc 感觉还不成熟。

冰绿茶—— | 园豆:6 (初学一级) | 2012-01-09 15:05
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册