博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
在sliverlight 客户端实现DataTable的尝试,让自定义DataGrid能够轻松绑定DataTable
阅读量:5216 次
发布时间:2019-06-14

本文共 9277 字,大约阅读时间需要 30 分钟。

不知道微软为什么在sl中不支持DataTable,不给老程序员面子么?

好吧,既然不行那我们只能DIY一个,这就开始干活:

第一步:创建 DataRow

 既然是表格那我们必须有列,行和他们的集合,咳..什么都没,那我们先创建列:

public class DataColumn     {
#region "Properties" /// /// 列名 /// public string ColumnName { get; set; } /// /// 类型 /// public Type DataType { get; set; } /// /// 列标题 /// public string Caption { get; set; } /// /// 是否允许用户改变列的大小 /// public bool AllowResize { get; set; } /// ///是否允许用户进行排序 /// public bool AllowSort { get; set; } /// /// 是否允许用户进行重新排序 /// public bool AllowReorder { get; set; } /// /// 是否只读 /// public bool ReadOnly { get; set; } #endregion /// /// 构造并且赋初始值 /// /// 列名 public DataColumn(string columnName) {
this.ColumnName = columnName; this.Caption = columnName; this.AllowResize = true; this.AllowSort = true; this.AllowReorder = true; this.ReadOnly = false; } /// /// 重载构造 /// /// 列名 /// 列标题 /// 是否允许改变列大小 /// 是否允许排序 /// 是否允许重新排序 /// 列只读 public DataColumn(string columnName, string caption, bool allowResize, bool allowSort, bool allowReorder, bool readOnly) {
this.ColumnName = columnName; this.Caption = caption; this.AllowResize = allowResize; this.AllowSort = allowSort; this.AllowReorder = allowReorder; this.ReadOnly = readOnly; } }

光有列还不够啊,必须要拿出一捆列才行,好吧上列集合:

第二步:创建 DataColumnCollecion:

///  /// DataColumn集合,继承与list ///      public class DataColumnCollection : List
{
///
/// 隐藏List类中add方法,重新定义Add方法,判断有重复列的时候报出异常 /// ///
public new void Add(DataColumn dc) {
foreach (DataColumn curColumn in this) {
if (dc.ColumnName == curColumn.ColumnName) {
throw new Exception(String.Format("该列已经存在", dc.ColumnName)); } } base.Add(dc); } }

列都已经准备好了,接下来是伟大的行了,早在很久之前DataRow曾经一度风靡,我突然想到了一些很矜持的老程序员。。想到了久违的Ado...

第三步:创建行

public class DataRow     {
public Dictionary
items { set; get; } public DataRow() {
this.items = new Dictionary
(); } ///
/// DataRow类索引器 (DataRow[.....]) /// ///
///
public object this[string key] {
set { items[key] = value; } get { return items[key]; } } ///
/// 通过emit反射在内存中创建出一个包含属性的类 /// ///
public Assembly EmitAssembly() {
AssemblyName assemblyName = new AssemblyName("DataRowAssembly"); AssemblyBuilder assemblyBuilder=Thread.GetDomain().DefineDynamicAssembly(assemblyName,AssemblyBuilderAccess.Run); ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("DataRowModel",true); TypeBuilder typeBuilder = moduleBuilder.DefineType("DataRowObject",TypeAttributes.Public|TypeAttributes.Class); foreach(KeyValuePair
pair in items) {
BuilderFieldsAndProperty(typeBuilder, pair.Key,pair.Value.GetType()); } typeBuilder.CreateType(); return assemblyBuilder; } ///
/// 通过emit反射创建字段和属性 /// ///
TypeBuilder ///
需要创建的属性名 ///
包含该属性的类的类型 public void BuilderFieldsAndProperty(TypeBuilder myTypeBuilder, string name, Type type) {
FieldBuilder myFieldBuilder = myTypeBuilder.DefineField(name, type, FieldAttributes.Private); PropertyBuilder myPropertyBuilder = myTypeBuilder.DefineProperty(name.ToUpper(), PropertyAttributes.HasDefault, type, null); MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig; MethodBuilder getMethodBuilder = myTypeBuilder.DefineMethod("get_" + name, getSetAttr, type, Type.EmptyTypes); ILGenerator custNameGetIL = getMethodBuilder.GetILGenerator(); custNameGetIL.Emit(OpCodes.Ldarg_0); custNameGetIL.Emit(OpCodes.Ldfld, myFieldBuilder); custNameGetIL.Emit(OpCodes.Ret); MethodBuilder setMethodBuilder = myTypeBuilder.DefineMethod("set_" + name, getSetAttr, null, new Type[] { type }); ILGenerator custNameSetIL = setMethodBuilder.GetILGenerator(); custNameSetIL.Emit(OpCodes.Ldarg_0); custNameSetIL.Emit(OpCodes.Ldarg_1); custNameSetIL.Emit(OpCodes.Stfld, myFieldBuilder); custNameSetIL.Emit(OpCodes.Ret); myPropertyBuilder.SetGetMethod(getMethodBuilder); myPropertyBuilder.SetSetMethod(setMethodBuilder); } }

好吧,但是老程序员也必须面对对象才是王道的事实。。回归正题:怎么让程序自动创建实体而不需要些在.cs文件中

聪明的你一定会想到反射,的确使用Emit反射就能帮助我们在内存中创建我们需要的类类型而无需写在.cs文件中,

EmitAssembly()方法能够帮助我们将Dictionary集合中的数据在内存中

用代码直观的理解:

Assembly rowAssembly = row.EmitAssembly();                 object c=rowAssembly.CreateInstance("DataRowObject");                 Type type = rowAssembly.GetType("DataRowObject");

执行完这段代码后 "DataRowObject"类会在内存中制造完毕而且能使用,程序执行完毕后变从人间蒸发

关于怎么使用Emit,大家可以到博客园上找相关文章,这里不再细说了s

下面是行集合:

第四步:创建行集合 

public class DataRowCollection:List
{
}

行集合和list基本一致所以就靠他父亲吧。

一切准备就绪:DataTable 光荣登场:

第四步:创建DataTable

public class DataTable     {
/// /// DataTable 的名字 /// public string Name { get; set; } /// /// DataRow的集合 /// public DataRowCollection Rows { get; set; } /// /// DataColumn的集合 /// public DataColumnCollection Columns { get; set; } /// /// 构造函数并且赋初始值或创建对象 /// /// public DataTable(string name ) {
this.Name = name; this.Rows = new DataRowCollection(); this.Columns = new DataColumnCollection(); } }

OK一切准备工作完毕,只剩东风了,可惜微软给我们的DataGrid根本就不支持DataTable的绑定,怎么办?分手?不,我要改造你!

第四步:创建自己的DataGrid:

///  /// 自定义MyDataGrid 继承自DataGrid ///      public class MyDataGrid:DataGrid     {
public MyDataGrid() {
//重新定义触发AutoGeneratingColumn时的创建列的方法 this.AutoGeneratingColumn += new EventHandler
( (o, e) => {
//将dataSource赋给自定义的Datatable DataTable dt = ((DataTable)this.DataSoruce); //通过自定义DataColumn设置对dataGrid的Cloumn进行相应的修改 foreach (DataColumn dc in dt.Columns) {
if (dc.ColumnName.ToUpper() == e.Column.Header.ToString()) {
e.Column.Header = dc.Caption; e.Column.IsReadOnly = dc.ReadOnly; e.Column.CanUserResize = dc.AllowResize; e.Column.CanUserSort = dc.AllowSort; e.Column.CanUserReorder = dc.AllowReorder; break; } } } ); } public object DataSoruce { set; get; } ///
/// 将DataTable转换成list /// /// 自定义DataTable ///
public List GetDataFromDataTable(DataTable table ) {
List list = new List(); foreach (DataRow row in table.Rows) { Assembly rowAssembly = row.EmitAssembly(); object c=rowAssembly.CreateInstance("DataRowObject"); Type type = rowAssembly.GetType("DataRowObject"); foreach (string key in row.items.Keys) { PropertyInfo properInfo = type.GetProperty(key.ToUpper()); properInfo.SetValue(c, row.items[key], null); } list.Add(c); } return list; } public void DataBind() { this.ItemsSource = this.GetDataFromDataTable((DataTable)DataSoruce); } }

首先我们先继承DataGrid 创建自己的DataGrid

 第二步就是利用反射将DataTable的内容转化成List<Object>,这还不够,我们必须重定义AutoGeneratingColumn 事件的绑定方法,

 自定义DataGrid的列属性,改变DataGrid原来的生命周期

 最后一笔就是当年很流行的DataBind方法,超怀念吧。

 

最后一步:实际使用:

首先在页面上放置自定义DataGrid

 

其实到这步对于元老级程序员来说很熟悉了:

public partial class MainPage : UserControl     {
public MainPage() {
InitializeComponent(); List
firstNames = new List
() { "a","b","c"}; List
lastNames = new List
() { "Jimmy","Jimmy2","Jimmy3"}; DataTable dt = new DataTable("MyDataTable"); DataColumn dc1 = new DataColumn("col1"); dc1.Caption = "First Name"; dc1.ReadOnly = true; dc1.DataType = typeof(String); dc1.AllowResize = true; dc1.AllowSort = true; dc1.AllowReorder = true; dt.Columns.Add(dc1); DataColumn dc2 = new DataColumn("col2"); dc2.Caption = "Last Name"; dc2.ReadOnly = true; dc2.DataType = typeof(String); dc2.AllowResize = true; dc2.AllowSort = true; dc2.AllowReorder = true; dt.Columns.Add(dc2); Random r = new Random(); for (int i = 0; i < 15; i++) {
DataRow dr = new DataRow(); dr["col1"] = firstNames[r.Next(firstNames.Count)]; dr["col2"] = lastNames[r.Next(lastNames.Count)]; dt.Rows.Add(dr); } this.MyDataGrid.DataSoruce = dt; this.MyDataGrid.DataBind(); } }

好了,大功告成,Asp.net GridView和Sliverlight DataGrid  可以拥抱了。

以上方案和WCF 没有任何关系,老程序员又给我出难题了。。他希望从服务端直接通过wcf传DataTable 然后到前台还是通过DataTable绑定,没办法,让我再研究下。。。

 

 

 

 

 

转载于:https://www.cnblogs.com/JimmyZheng/archive/2012/03/11/2390233.html

你可能感兴趣的文章
java中内部类的讲解
查看>>
手机验证码执行流程
查看>>
python 基础 ----- 变量
查看>>
设计模式课程 设计模式精讲 2-2 UML类图讲解
查看>>
为块级元素添加链接
查看>>
Silverlight 的菜单控件。(不是 Toolkit的)
查看>>
:hover 鼠标同时触发两个元素变化
查看>>
go语言学习十三 - 相等性
查看>>
Idea 提交代码到码云(提交到github也大同小异)
查看>>
c#连接excel2007未安装ISAM解决
查看>>
Mono 异步加载数据更新主线程
查看>>
初识lua
查看>>
我是插件狂人,jDuang,jValidator,jModal,jGallery
查看>>
张季跃 201771010139《面向对象程序设计(java)》第四周学习总结
查看>>
如何解除循环引用
查看>>
android中fragment的使用及与activity之间的通信
查看>>
字典【Tire 模板】
查看>>
jquery的contains方法
查看>>
python3--算法基础:二分查找/折半查找
查看>>
Perl IO:随机读写文件
查看>>