ASP.NET FormView - 动态模版以及数据绑定到DynamicObject
来源:互联网 发布:奥塔哥大学 知乎 编辑:程序博客网 时间:2024/06/05 18:37
需求:通过metadata数据源构造一个实体,实体属性为动态(metadata可变),使用FormView实现实体的CRUD功能
问题1:如何实现FormView的动态ItemTemplate,EditItemTemplate,InsertItemTemplate
解决1:自定义模版类,实现IBindableTemplate接口
参考:如何实现自定义模版
http://www.intelligiblebabble.com/dynamically-create-item-templates-server-side/
http://www.developerfusion.com/code/4721/dynamically-loading-an-ibindabletemplate/
如何实现模版字段的数据绑定:
http://forums.asp.net/t/1783767.aspx/2/10
http://forums.asp.net/t/911217.aspx/2/10?Creating+GridView+at+Runtime+Columns+from+Database
问题2:如何实现前述动态模版的数据绑定
解决2:使用自.NET 4.0推出的DynamicObject,将模版字段绑定到DynamicObject上的动态属性
参考:
如何将Dictionary转换为ExpandoObject (一种DynamicObject) http://stackoverflow.com/questions/7595416/convert-dictionarystring-object-to-anonymous-object
解决ExpandoObject无法使用DataBinder.Eval的问题 http://programcsharp.com/blog/archive/2012/09/25/databinder-eval-expandoobject-custom-typedescriptor.aspx
实现自定义模版类DynamicItemTemplate,支持ReadOnly 或者Update/Insert模式
public class DynamicItemTemplate : IBindableTemplate { private List<CustomFieldMetadata> _fields; private bool _isReadOnly; public DynamicItemTemplate(List<CustomFieldMetadata> fields, bool readOnly) { _fields = fields; _isReadOnly = readOnly; } public void InstantiateIn(Control container) { var divFormWrapper = new HtmlGenericControl("div"); divFormWrapper.Attributes.Add("class", "form-wrapper"); var divWrapPanel = new HtmlGenericControl("div"); divWrapPanel.Attributes.Add("class", "wrap-panel"); divFormWrapper.Controls.Add(divWrapPanel); foreach(var f in _fields) { if (f.Name == "id") //ignore "id" field { continue; } var label = new HtmlGenericControl("span"); label.Attributes.Add("class", "label"); label.InnerText = f.Name; divWrapPanel.Controls.Add(label); if (_isReadOnly) { Label value = new Label { ID = f.Name };//control id must to be field name divWrapPanel.Controls.Add(value); value.DataBinding += Field_DataBinding; } else { var span = new HtmlGenericControl("span"); var input = CreateFiledInput(f); //control id must to be field name span.Controls.Add(input); divWrapPanel.Controls.Add(span); input.DataBinding += Field_DataBinding; } } container.Controls.Add(divFormWrapper); } void Field_DataBinding(object sender, EventArgs e) { if (sender is Label) { Label label = sender as Label; object databoundValue = DataBinder.Eval(((IDataItemContainer)((Control)sender).NamingContainer).DataItem, label.ID); //assuming input control id is the property name of the bound data item if (databoundValue != null) { label.Text = databoundValue.ToString(); } } else { Control control = sender as Control; object databoundValue = DataBinder.Eval(((IDataItemContainer)((Control)sender).NamingContainer).DataItem, control.ID); //assuming input control id is the property name of the bound data item if (databoundValue != null) { if (control is ITextControl) { ((ITextControl)control).Text = databoundValue.ToString(); } else if (control is RadDatePicker) { DateTime dt; DateTime.TryParseExact(databoundValue.ToString(), "yyyy-MM-dd", null, System.Globalization.DateTimeStyles.None, out dt); ((RadDatePicker)control).SelectedDate = dt; } } } } public System.Collections.Specialized.IOrderedDictionary ExtractValues(Control container) { if (_isReadOnly) { return null; } OrderedDictionary dict = new OrderedDictionary(); foreach (var f in _fields) { var control = container.FindControl(f.Name); if (control is ITextControl) { dict.Add(control.ID, ((ITextControl)control).Text); } else if (control is RadDatePicker) { dict.Add(control.ID, ((RadDatePicker)control).SelectedDate); } } return dict; } public Control CreateFiledInput(CustomFieldMetadata fieldMetadata) { Control control = null; switch(fieldMetadata.Type) { case CustomFieldTypeDataSourceProvider.TEXT: control = new RadTextBox(); break; case CustomFieldTypeDataSourceProvider.INTEGER: case CustomFieldTypeDataSourceProvider.DECIMAL: control = new RadNumericTextBox(); break; case CustomFieldTypeDataSourceProvider.DATE: control = new RadDatePicker(); break; } control.ID = fieldMetadata.Name;//set control id to be field name return control; } }
在 FormView 控件所在的页面Init 事件处理中,初始化FormView的模版:
var fields = GetCustomFields();
DynamicItemTemplate itemTemplate = new DynamicItemTemplate(fields, true); detailForm.ItemTemplate = itemTemplate; DynamicItemTemplate editItemTemplate = new DynamicItemTemplate(fields, false); detailForm.EditItemTemplate = editItemTemplate;
加载FormView数据的Select方法实现如下:
public dynamic Select([Session] string id) { if (id == null) { return null; } Dictionary<string, object> fields = SelectRaw(id);//entity values as a Dictionary var names = fields.Keys.ToList(); var item = DynamicDataBindHelper.ConvertToBindableDynamicObject(fields); return item; }
public class DynamicDataBindHelper { public static dynamic ConvertToBindableDynamicObject(Dictionary<string, object> dictionary) { var expando = new ExpandoObject(); var collection = (ICollection<KeyValuePair<string, object>>)expando; foreach (var pair in dictionary) { collection.Add(pair); } dynamic dynamaicObject = new DynamicTypeDescriptorWrapper(expando); return dynamaicObject; } }
- ASP.NET FormView - 动态模版以及数据绑定到DynamicObject
- ASP.NET 2.0 的数据绑定控件概述与区别(GridView、DetailsView、FormView 、Repeater、DataList)
- ASP.NET 2.0 的数据绑定控件概述与区别(GridView、DetailsView、FormView 、Repeater、DataList)
- ASP.NET 2.0 的数据绑定控件概述与区别(GridView、DetailsView、FormView 、Repeater、DataList)
- ASP.NET GirdView后台动态绑定数据
- asp.net 利用NPOI导出数据到Excel模版
- ASP.NET动态网站开发培训-12.FormView控件
- ASP.NET 数据控件:GridView,DataList,Repeater ,DetailsView,FormView。
- ASP.NET数据绑定
- asp.net数据绑定
- ASP.net 数据绑定
- asp.net数据绑定
- Asp.net数据绑定
- ASP.NET 数据绑定
- asp.net数据绑定
- asp.net数据绑定
- asp.net 数据绑定
- asp.net 数据绑定
- 黑马程序员_交通灯管理系统
- 进程与线程的一个简单解释
- (译)Objective-C的动态特性
- POJ Mayor's posters (线段树+离散化处理)
- 关于 sql中 group by 后跟主键是没有任何意义的
- ASP.NET FormView - 动态模版以及数据绑定到DynamicObject
- MFC Dll
- Linux 经典电子书共享下载
- struct 对齐
- Apache软件体系结构
- xcode联机调试最简单的方法/xcode真机调试最简单的方法
- C#定时器中调用WCF服务+自定义回调函数
- 华为机试准备--练习(JAVA实现)
- Android 颜色渲染(五) LinearGradient线性渲染