ASP. NET FormView - 동적 모드 및 데이터 연결 DynamicObject

수요: 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 를 Expando Object (Dynamic Object) 로 바 꾸 는 방법 http://stackoverflow.com/questions/7595416/convert-dictionarystring-object-to-anonymous-object
Expando Object 에서 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 데이터 바 인 딩 에 사용 할 대상 으로 변환 합 니 다. (DynamicTypeDescriptor Wrapper 는 상기 참조 에서 실 현 됩 니 다)
 public class DynamicDataBindHelper
    {
        public static dynamic ConvertToBindableDynamicObject(Dictionary<stringobject> dictionary)
        {
            var expando = new ExpandoObject();
            var collection = (ICollectionstring, object>>)expando;
            foreach (var pair in dictionary)
            {
                collection.Add(pair);
            }
            dynamic dynamaicObject = new DynamicTypeDescriptorWrapper(expando);
            return dynamaicObject;
        }
    }

좋은 웹페이지 즐겨찾기