Silverlight日记:动态生成DataGrid、行列装换、动态加载控件
本文主要针对使用DataGrid动态绑定数据对象,并实现行列转换效果。
一,前台绑定
<sdk:DataGrid x:Name="dataGrid2" Style="{StaticResource ResourceKey=safeDataGrid2}" />
using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Net; using System.Reflection; using System.Reflection.Emit; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Markup; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Windows.Threading; using Test.Util; namespace Test { public partial class MainPage : UserControl { public Md Model = null; private DispatcherTimer timer; int index = 0; /// <summary> /// /// </summary> public ObservableCollection<Obj> objs = new ObservableCollection<Obj>(); public MainPage() { InitializeComponent(); init(); timer = new DispatcherTimer(); timer.Interval = new TimeSpan(0, 0, 8); timer.Tick += timer_Tick; timer.Start(); } /// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void timer_Tick(object sender, EventArgs e) { var ramd = new Random(); foreach (var tag in Model.Tags) { foreach (var para in Consts.Params) { var rv = index % 2 == 0 ? ramd.Next(2, 10) : ramd.Next(1, 5); var o = new Obj { IsAlarm = false, Value = (0.5 + rv).ToString(), State = index % 2 == 0 ? 1 : 0, MeterId = tag.F_METER_ID, MeterName = tag.F_METER_NAME, ParaId = para.Id }; if (para.Id == "10") { o.IsAlarm = false; o.ParaId = string.Empty; o.State = 0; o.Value = string.Empty; } var temp = objs.FirstOrDefault(i => i.MeterName.Equals(o.MeterName) && i.ParaId == o.ParaId); if (temp != null) { temp.IsAlarm = o.IsAlarm; temp.State = o.State; temp.Value = o.Value; } else objs.Add(o); } } //CommHelper.GetSource(Model.Tags, objs, ref this.dataGrid2); CommHelper.BindData(Model.Tags, objs, ref this.dataGrid2); index++; } /// <summary> /// /// </summary> void init() { Model = new Md(); Model.Tags = new List<T_METER>(); Model.Eles = new List<Param>(); for (int i = 0; i < 1; i++) { var temp = new T_METER { F_BUILD_ID = "440300B059", F_METER_ID = string.Format("TAG_{0}", i), F_METER_NAME = string.Format("CM-{0}", i) }; if (i == 0) temp.F_EQT_TYPE = "D"; else if (i == 1) temp.F_EQT_TYPE = "C"; else if (i == 2) temp.F_EQT_TYPE = "E"; else temp.F_EQT_TYPE = "A"; Model.Tags.Add(temp); } this.dataGrid1.ItemsSource = Consts.Params; CommHelper.CreateDataGrid(Model.Tags, ref this.dataGrid2); } } /// <summary> /// /// </summary> public class Md { /// <summary> /// 参数集合 /// </summary> public List<Param> Eles { get; set; } /// <summary> /// 电表集合 /// </summary> public List<T_METER> Tags { get; set; } } /// <summary> /// /// </summary> public class T_METER { public string F_BUILD_ID { get; set; } public string F_METER_ID { get; set; } public string F_METER_NAME { get; set; } public string F_EQT_TYPE { get; set; } public string F_VALUE { get; set; } } /// <summary> /// 参数 /// </summary> public class Param { public string Id { get; set; } public string Name { get; set; } } /// <summary> /// 绑定数据对象 /// </summary> public class Obj { /// <summary> /// 对应参数编号 /// </summary> public string ParaId { get; set; } public string MeterId { get; set; } /// <summary> /// 电表名称 /// </summary> public string MeterName { get; set; } /// <summary> /// 开关状态0-关,1-开 /// </summary> public int State { get; set; } /// <summary> /// OPC读取值 /// </summary> public string Value { get; set; } /// <summary> /// 是否报警 /// </summary> public bool IsAlarm { get; set; } } }
二,动态列对象
1 using System.Collections.Generic; 2 3 namespace Test.Util 4 { 5 /* ============================== 6 * Desc:DynamicColumn 7 * Author:hezp 8 * Date:2014/8/14 15:49:17 9 * ==============================*/ 10 public class DynamicColumn 11 { 12 /// <summary> 13 /// 列名 14 /// </summary> 15 public string ColumnName { get; set; } 16 /// <summary> 17 /// 列对应集合 18 /// </summary> 19 public List<string> Values { get; set; } 20 } 21 }
三,DataGrid动态生成类
1 using System; 2 using System.Linq; 3 using System.Collections; 4 using System.Collections.Generic; 5 using System.Net; 6 using System.Text; 7 using System.Windows; 8 using System.Windows.Controls; 9 using System.Windows.Documents; 10 using System.Windows.Ink; 11 using System.Windows.Input; 12 using System.Windows.Markup; 13 using System.Windows.Media; 14 using System.Windows.Media.Animation; 15 using System.Windows.Shapes; 16 using System.Text.RegularExpressions; 17 using System.Collections.ObjectModel; 18 19 namespace Test.Util 20 { 21 /* ============================== 22 * Desc:CommHelper 23 * Author:hezp 24 * Date:2014/8/14 15:58:26 25 * ==============================*/ 26 public class CommHelper 27 { 28 /// <summary> 29 /// 30 /// </summary> 31 /// <param name="columnBindName"></param> 32 /// <param name="columnHeaderName"></param> 33 /// <param name="width"></param> 34 /// <param name="index"></param> 35 /// <returns></returns> 36 private static DataGridTemplateColumn CreateDataGridTextColumn(string columnBindName, string columnHeaderName, T_METER tag) 37 { 38 DataGridTemplateColumn dgColumn = new DataGridTemplateColumn(); 39 dgColumn.Header = columnHeaderName; 40 dgColumn.IsReadOnly = true; 41 var w = 70; 42 if (tag != null) 43 { 44 if (tag.F_EQT_TYPE.Equals("D")) 45 { 46 dgColumn.HeaderStyle = ResourcesWrapper.GetStyle<Style>("safeByqStyle"); 47 w = 120; 48 } 49 else if (tag.F_EQT_TYPE.Equals("B")) 50 { 51 dgColumn.HeaderStyle = ResourcesWrapper.GetStyle<Style>("safeSingleDrStyle"); 52 w = 90; 53 } 54 else if (tag.F_EQT_TYPE.Equals("C")) 55 { 56 dgColumn.HeaderStyle = ResourcesWrapper.GetStyle<Style>("safeDoubleDrStyle"); 57 w = 150; 58 } 59 else if (tag.F_EQT_TYPE.Equals("E")) 60 { 61 dgColumn.HeaderStyle = ResourcesWrapper.GetStyle<Style>("safeHookStyle"); 62 w = 98; 63 } 64 else 65 dgColumn.HeaderStyle = ResourcesWrapper.GetStyle<Style>("safeMeterStyle"); 66 } 67 else 68 dgColumn.HeaderStyle = ResourcesWrapper.GetStyle<Style>("safeMeterStyle"); 69 70 dgColumn.CellStyle = ResourcesWrapper.GetStyle<Style>("safeCellStyle"); 71 72 StringBuilder cellTemplate = new StringBuilder(); 73 cellTemplate.Append("<DataTemplate "); 74 cellTemplate.Append(" xmlns='http://schemas.microsoft.com/client/2007' "); 75 cellTemplate.Append(" xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' "); 76 cellTemplate.Append(" xmlns:c='clr-namespace:Test.Controls;assembly=Test.Controls' "); 77 cellTemplate.Append(" xmlns:local = 'Test"); 78 cellTemplate.Append(";assembly=Test'>"); 79 cellTemplate.Append(string.Format("<c:CustomCell Width='{1}' Text='{{Binding {0}}}'/>", columnBindName, w)); 80 cellTemplate.Append("</DataTemplate>"); 81 dgColumn.CellTemplate = (DataTemplate)XamlReader.Load(cellTemplate.ToString()); 82 dgColumn.CellTemplate.LoadContent(); 83 84 return dgColumn; 85 } 86 87 /// <summary> 88 /// 89 /// </summary> 90 /// <param name="SourceList"></param> 91 /// <returns></returns> 92 private static IEnumerable<IDictionary> GetEnumerable(List<Dictionary<string, string>> SourceList) 93 { 94 for (int i = 0; i < SourceList.Count; i++) 95 { 96 var dict = new Dictionary<string, string>(); 97 dict = SourceList[i]; 98 yield return dict; 99 } 100 } 101 /// <summary> 102 /// 103 /// </summary> 104 /// <param name="list"></param> 105 /// <param name="objs"></param> 106 /// <returns></returns> 107 private static List<DynamicColumn> Grenartor(List<T_METER> list, ObservableCollection<Obj> objs) 108 { 109 var columns = new List<DynamicColumn>(); 110 if (null == list) return null; 111 var ms = from p in list 112 group p by new { p.F_BUILD_ID, p.F_METER_ID, p.F_METER_NAME } into gg 113 select gg.Key; 114 var ramd = new System.Random(); 115 foreach (var m in ms) 116 { 117 var column = new DynamicColumn 118 { 119 ColumnName = string.Format("{0}____{1}", m.F_METER_NAME, 0)//格式:支路名称|开关状态值 120 }; 121 if (objs != null) 122 { 123 var obj = objs.FirstOrDefault(i => i.MeterName.Equals(m.F_METER_NAME)); 124 if (obj != null) 125 column.ColumnName = string.Format("{0}____{1}", obj.MeterName, obj.State); 126 } 127 column.Values = new List<string>(); 128 var count = Consts.Params.Count; 129 for (int i = 0; i < count; i++) 130 { 131 var v = false;//是否显示按钮 132 if (i == count - 1) 133 v = true; 134 if (objs != null) 135 { 136 var temp = objs.FirstOrDefault(j => j.MeterName.Equals(m.F_METER_NAME) && !string.IsNullOrEmpty(j.ParaId) && j.ParaId.Equals(Consts.Params[i].Id)); 137 if (temp != null) 138 column.Values.Add(string.Format("{0}____{1}____{2}____{3}____{4}____{5}____{6}", m.F_BUILD_ID, m.F_METER_ID, m.F_METER_NAME, temp.Value, v, temp.IsAlarm, Consts.Params[i].Id)); 139 else 140 column.Values.Add(string.Format("{0}____{1}____{2}____{3}____{4}____{5}____{6}", m.F_BUILD_ID, m.F_METER_ID, m.F_METER_NAME, "-", v, false, Consts.Params[i].Id));//格式:建筑编号____支路编号____支路名称____数值____是否是按钮____是否报警 141 } 142 else 143 column.Values.Add(string.Format("{0}____{1}____{2}____{3}____{4}____{5}____{6}", m.F_BUILD_ID, m.F_METER_ID, m.F_METER_NAME, "-", v, false, Consts.Params[i].Id)); 144 } 145 columns.Add(column); 146 } 147 return columns; 148 } 149 /// <summary> 150 /// 绑定数据 151 /// </summary> 152 /// <param name="tags"></param> 153 /// <param name="objs"></param> 154 /// <param name="datagrid"></param> 155 public static void BindData(List<T_METER> tags, ObservableCollection<Obj> objs, ref DataGrid datagrid) 156 { 157 var list = Grenartor(tags, objs); 158 var dataSources = new List<Dictionary<string, string>>(); 159 for (int j = 0; j < 10; j++) 160 { 161 var dict = new Dictionary<string, string>();//数据行(Key:列名,Value:列值) 162 list.ForEach(item => 163 { 164 dict.Add(item.ColumnName.Replace(" ", "_").Replace("-", "_"), item.Values[j]); 165 }); 166 dataSources.Add(dict); 167 } 168 foreach (var item in list) 169 { 170 var index = list.IndexOf(item); 171 var arr = Regex.Split(item.ColumnName, "____", RegexOptions.IgnoreCase); 172 var tag = tags.FirstOrDefault(i => i.F_METER_NAME.ToUpper().Equals(arr[0].ToUpper())); 173 var column = CreateDataGridTextColumn(item.ColumnName.Replace(" ", "_").Replace("-", "_"), item.ColumnName, tag); 174 var cl = datagrid.Columns.FirstOrDefault(i => i.Header.ToString().StartsWith(tag.F_METER_NAME)); 175 if (cl != null) 176 cl = column; 177 else 178 datagrid.Columns.Add(column); 179 } 180 datagrid.ItemsSource = GetEnumerable(dataSources).ToDataSource(); 181 } 182 183 public static void GetSource(List<T_METER> tags, ObservableCollection<Obj> objs, ref DataGrid datagrid) 184 { 185 var list = Grenartor(tags, objs); 186 var dataSources = new List<Dictionary<string, string>>(); 187 for (int j = 0; j < 10; j++) 188 { 189 var dict = new Dictionary<string, string>();//数据行(Key:列名,Value:列值) 190 list.ForEach(item => 191 { 192 dict.Add(item.ColumnName.Replace(" ", "_").Replace("-", "_"), item.Values[j]); 193 }); 194 dataSources.Add(dict); 195 } 196 datagrid.ItemsSource = GetEnumerable(dataSources).ToDataSource(); 197 } 198 199 public static void CreateDataGrid(List<T_METER> tags, ref DataGrid datagrid) 200 { 201 var list = Grenartor(tags, null); 202 var dataSources = new List<Dictionary<string, string>>(); 203 for (int j = 0; j < 10; j++) 204 { 205 var dict = new Dictionary<string, string>();//数据行(Key:列名,Value:列值) 206 list.ForEach(item => 207 { 208 dict.Add(item.ColumnName.Replace(" ", "_").Replace("-", "_"), item.Values[j]); 209 }); 210 dataSources.Add(dict); 211 } 212 foreach (var item in list) 213 { 214 var index = list.IndexOf(item); 215 var arr = Regex.Split(item.ColumnName, "____", RegexOptions.IgnoreCase); 216 var tag = tags.FirstOrDefault(i => i.F_METER_ID.ToUpper().Equals(arr[0].ToUpper())); 217 var column = CreateDataGridTextColumn(item.ColumnName.Replace(" ", "_").Replace("-", "_"), item.ColumnName, tag); 218 var cl = datagrid.Columns.FirstOrDefault(i => i.Header.ToString().StartsWith(tag.F_METER_NAME)); 219 if (cl != null) 220 cl = column; 221 else 222 datagrid.Columns.Add(column); 223 } 224 datagrid.ItemsSource = GetEnumerable(dataSources).ToDataSource(); 225 } 226 } 227 }
四,数据源构造(实现行列转换)类
1 using System; 2 using System.Collections; 3 using System.Collections.Generic; 4 using System.Collections.ObjectModel; 5 using System.Reflection; 6 using System.Reflection.Emit; 7 8 namespace Test.Util 9 { 10 /* ============================== 11 * Desc:DataSourceCreator 12 * Author:hezp 13 * Date:2014/8/14 15:51:04 14 * ==============================*/ 15 public static class DataSourceCreator 16 { 17 public static ObservableCollection<object> ToDataSource(this IEnumerable<IDictionary> list) 18 { 19 IDictionary firstDict = null; 20 bool hasData = false; 21 foreach (IDictionary currentDict in list) 22 { 23 hasData = true; 24 firstDict = currentDict; 25 break; 26 } 27 if (!hasData) 28 { 29 return new ObservableCollection<object> { }; 30 } 31 if (firstDict == null) 32 { 33 throw new ArgumentException("IDictionary entry cannot be null"); 34 } 35 Type objectType = null; 36 TypeBuilder tb = GetTypeBuilder(list.GetHashCode()); 37 ConstructorBuilder constructor = 38 tb.DefineDefaultConstructor( 39 MethodAttributes.Public | 40 MethodAttributes.SpecialName | 41 MethodAttributes.RTSpecialName); 42 foreach (DictionaryEntry pair in firstDict) 43 { 44 45 CreateProperty(tb, 46 Convert.ToString(pair.Key), 47 pair.Value == null ? 48 typeof(object) : 49 pair.Value.GetType()); 50 51 } 52 objectType = tb.CreateType(); 53 return GenerateArray(objectType, list, firstDict); 54 } 55 private static ObservableCollection<object> GenerateArray(Type objectType, IEnumerable<IDictionary> list, IDictionary firstDict) 56 { 57 var itemsSource = new ObservableCollection<object>(); 58 foreach (var currentDict in list) 59 { 60 object row = Activator.CreateInstance(objectType); 61 foreach (DictionaryEntry pair in firstDict) 62 { 63 if (currentDict.Contains(pair.Key)) 64 { 65 PropertyInfo property = 66 objectType.GetProperty(Convert.ToString(pair.Key)); 67 property.SetValue( 68 row, 69 Convert.ChangeType( 70 currentDict[pair.Key], 71 property.PropertyType, 72 null), 73 null); 74 } 75 } 76 itemsSource.Add(row); 77 } 78 return itemsSource; 79 } 80 private static TypeBuilder GetTypeBuilder(int code) 81 { 82 AssemblyName an = new AssemblyName("TempAssembly" + code); 83 AssemblyBuilder assemblyBuilder = 84 AppDomain.CurrentDomain.DefineDynamicAssembly( 85 an, AssemblyBuilderAccess.Run); 86 ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule"); 87 TypeBuilder tb = moduleBuilder.DefineType("TempType" + code 88 , TypeAttributes.Public | 89 TypeAttributes.Class | 90 TypeAttributes.AutoClass | 91 TypeAttributes.AnsiClass | 92 TypeAttributes.BeforeFieldInit | 93 TypeAttributes.AutoLayout 94 , typeof(object)); 95 return tb; 96 } 97 private static void CreateProperty(TypeBuilder tb, string propertyName, Type propertyType) 98 { 99 FieldBuilder fieldBuilder = tb.DefineField("_" + propertyName, 100 propertyType, 101 FieldAttributes.Private); 102 103 PropertyBuilder propertyBuilder = 104 tb.DefineProperty( 105 propertyName, PropertyAttributes.HasDefault, propertyType, null); 106 MethodBuilder getPropMthdBldr = 107 tb.DefineMethod("get_" + propertyName, 108 MethodAttributes.Public | 109 MethodAttributes.SpecialName | 110 MethodAttributes.HideBySig, 111 propertyType, Type.EmptyTypes); 112 ILGenerator getIL = getPropMthdBldr.GetILGenerator(); 113 getIL.Emit(OpCodes.Ldarg_0); 114 getIL.Emit(OpCodes.Ldfld, fieldBuilder); 115 getIL.Emit(OpCodes.Ret); 116 MethodBuilder setPropMthdBldr = 117 tb.DefineMethod("set_" + propertyName, 118 MethodAttributes.Public | 119 MethodAttributes.SpecialName | 120 MethodAttributes.HideBySig, 121 null, new Type[] { propertyType }); 122 ILGenerator setIL = setPropMthdBldr.GetILGenerator(); 123 setIL.Emit(OpCodes.Ldarg_0); 124 setIL.Emit(OpCodes.Ldarg_1); 125 setIL.Emit(OpCodes.Stfld, fieldBuilder); 126 setIL.Emit(OpCodes.Ret); 127 propertyBuilder.SetGetMethod(getPropMthdBldr); 128 propertyBuilder.SetSetMethod(setPropMthdBldr); 129 } 130 } 131 }
五,显示效果