ASP.NET FormView - 动态模版以及数据绑定到DynamicObject

本文详细介绍了如何使用自定义模版类实现FormView的动态ItemTemplate、EditItemTemplate和InsertItemTemplate,包括数据绑定、字段处理和模板初始化过程,并提供了关键步骤的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

需求:通过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([Sessionstring id)
        {
            if (id == null)
            {
                return null;
            }
            Dictionary<stringobject> fields = SelectRaw(id);//entity values as a Dictionary
 
            var names = fields.Keys.ToList();
            var item = DynamicDataBindHelper.ConvertToBindableDynamicObject(fields);
            return item;
        }


将ExpandoObject转换为可用于FormView数据绑定的对象, (DynamicTypeDescriptorWrapper实现来自于前述引用)

 public class DynamicDataBindHelper
    {
        public static dynamic ConvertToBindableDynamicObject(Dictionary<stringobject> dictionary)
        {
            var expando = new ExpandoObject();
            var collection = (ICollection<KeyValuePair<stringobject>>)expando;
            foreach (var pair in dictionary)
            {
                collection.Add(pair);
            }
            dynamic dynamaicObject = new DynamicTypeDescriptorWrapper(expando);
            return dynamaicObject;
        }
    }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值