using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Reflection; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace DymWebForm.Aspx { public class DymWebForm { private static readonly Type Type = typeof(T); private static readonly FormField[] AllField; private static readonly FormField PkField; static DymWebForm() { AllField = FormFieldFactory.GetFormFields(); PkField = AllField.FirstOrDefault(p => p.IsPK); if (PkField == null) throw new ArgumentException("Must define PK"); } private static void ProcTdFK(Func fkQuery, List> lstFKs) { lstFKs .GroupBy(p => p.Field.FKParentType) .ToDictionary(p => p.Key, p => p.ToArray()) .ForEach(p => { var arrFKID = p.Value .Select(q => q.FKVal) .Distinct() .ToArray(); var dicFKobj = fkQuery(p.Key, arrFKID) .ToDictionary( FormFieldFactoryProxy.GetPKValue , q => q ); p.Value.ForEach(q => { q.Td.Controls.Add(new Literal() { Text = q.FKVal.ToDisplayString() }); q.Td.Controls.Add(new Literal() { Text = ": " }); object parVal = null; var found = false; if (dicFKobj.ContainsKey(q.FKVal)) { found = true; var par = dicFKobj[q.FKVal]; parVal = FormFieldFactoryProxy.GetFKValue(par); } if (found) { q.Td.Controls.AddEx(new Label() { Text = parVal.ToDisplayString() ?? "NULL", ForeColor = Color.Blue }) .Font.Italic = (parVal == null); } else { q.Td.Controls.Add(new Label() { Text = "无对应", ForeColor = Color.Red }); } }); }); } private static Table RenderDetailsInternal(WebControl container, T entity, Func fkQuery, string[] skipFields = null) { skipFields = skipFields ?? new string[] { }; var arrFieldsToDisplay = AllField .Where(p => skipFields.Contains(p.FieldName) == false) .ToArray(); //init var tbl = new Table(); container.Controls.Add(tbl); tbl.Attributes.Add("border", "1"); tbl.Style[HtmlTextWriterStyle.BorderCollapse] = "Collapse"; tbl.CellSpacing = 1; tbl.CellPadding = 2; List> lstFKs = new List>(); //generate fields of form foreach (var field in arrFieldsToDisplay) { var tr = new TableRow(); tbl.Rows.Add(tr); var objVal = field.GetValue(entity); //field name tr.Cells.Add(new TableCell() { Text = field.DisplayName + ":" }); //field control var td = new TableCell(); tr.Cells.Add(td); td.VisualText(objVal.ToDisplayString()); //fk if (field.IsFK && objVal != null) { lstFKs.Add(new FieldFK { Field = field, Td = td, FKVal = objVal }); } } if (fkQuery != null) { ProcTdFK(fkQuery, lstFKs); } return tbl; } /// /// /// /// 容器, 要求已经添加到Page /// 数据源 /// 跳过的字段(如密码) /// 外键查询回调 /// {0}=ID 默认 ?op=edit&arg={0} /// {0}=ID 默认 ?op=delete&arg={0} public static void RenderGrid(Control container, IEnumerable dataSource, string[] arrSkipFields , Func fkQuery = null , string urlEdit = null , string urlDelete = null , int pageIndex = 0, int pageSize = 0) { //init vars urlEdit = urlEdit ?? "?op=edit&arg={0}"; urlDelete = urlDelete ?? "?op=delete&arg={0}"; //init var tbl = new Table(); container.Controls.Add(tbl); tbl.Attributes.Add("border", "1"); tbl.Style[HtmlTextWriterStyle.BorderCollapse] = "Collapse"; tbl.CellSpacing = 1; tbl.CellPadding = 2; arrSkipFields = arrSkipFields ?? new string[] { }; var arrFieldsToDisplay = AllField .Where(p => arrSkipFields.Contains(p.FieldName) == false) .ToArray(); //header var th = new TableRow(); th.Cells.Add(new TableHeaderCell { Text = "#" }); th.Cells.AddRange( arrFieldsToDisplay .SelectArray(p => new TableHeaderCell { Text = p.DisplayName }) ); th.Cells.Add(new TableHeaderCell() { Text = "操作" }); tbl.Rows.Add(th); //coll fk td for batch process List> lstFKs = new List>(); int rowNumber = pageIndex * pageSize; //rows foreach (var item in dataSource) { var tr = new TableRow(); tbl.Rows.Add(tr); tr.Cells.Add(new TableCell { Text = (++rowNumber).ToString() }); //entity data tr.Cells.AddRange( arrFieldsToDisplay .SelectArray(p => { var objVal = p.GetValue(item); var strVal = objVal.ToDisplayString(); var td = new TableCell(); td.VisualText(strVal); if (p.IsFK && objVal != null) { lstFKs.Add(new FieldFK { Field = p, Td = td, FKVal = objVal }); } return td; }) ); //opt. var tdOpt = new TableCell(); tr.Cells.Add(tdOpt); object key = PkField.GetValue(item); tdOpt.Controls.Add(new HyperLink() { Text = "修改", NavigateUrl = urlEdit.Format(key) }); tdOpt.Controls.Add(new Literal() { Text = " " }); tdOpt.Controls.Add(new HyperLink() { Text = "删除", NavigateUrl = urlDelete.Format(key) }); }//end foreach if (fkQuery != null) { ProcTdFK(fkQuery, lstFKs); } } public static void RenderInputForm(WebControl container, Action actOnSubmit, bool isAdd = true) { //init var tbl = new Table(); container.Controls.Add(tbl); tbl.Attributes.Add("border", "1"); tbl.Style[HtmlTextWriterStyle.BorderCollapse] = "Collapse"; tbl.CellSpacing = 1; tbl.CellPadding = 2; //generate fields of form foreach (var field in AllField) { if (isAdd && field.IsPK) continue; var validation = field.Validation; var tr = new TableRow(); tbl.Rows.Add(tr); //field name var tdName = tr.Cells.AddEx(new TableCell() { Text = field.DisplayName + ":" }); if (field.AllowNull == false) { tdName.Controls.Add(new Literal() { Text = "[" }); tdName.Controls.Add(new Label() { Text = "*", ForeColor = Color.Red }); tdName.Controls.Add(new Literal() { Text = "]" }); tdName.Controls.Add(new Literal() { Text = field.DisplayName + ":" }); } //field control var tdCtl = new TableCell(); tr.Cells.Add(tdCtl); Control ctl; ctl = field.CreateControl(); if (field.IsPK) { if (ctl is TextBox) { var tc = (TextBox)ctl; tc.ReadOnly = true; //tc.BorderStyle = BorderStyle.None; } } if (field.HasDefaultValueGenerator) DymWebFormControlMappnig.GetInst(field.DataType, field.ValidationType).ControlSetValue(ctl, field.GenerateDefaultValue()); tdCtl.Controls.Add(ctl); ctl.ID = field.ControlID; //hint if (!isAdd && validation is DynWebFormPasswordValidation) { tdCtl.Controls.Add(new Literal() { Text = "
*留空保持不变" }); tdName.VerticalAlign = VerticalAlign.Top; } //field validate var tdVal = new TableCell(); tr.Cells.Add(tdVal); if (field.IsPK == false && field.AllowNull == false && ctl is CheckBox == false && ( (isAdd) || (!isAdd && false == validation is DynWebFormPasswordValidation) ) ) { var rfv = new RequiredFieldValidator(); tdVal.Controls.Add(rfv); rfv.ValidationGroup = "fc" + Type.Name; rfv.ControlToValidate = ctl.ID; rfv.Display = ValidatorDisplay.Dynamic; rfv.ForeColor = Color.Red; rfv.Text = "*"; rfv.ErrorMessage = "必填字段:" + field.DisplayName + ""; rfv.ID = "rfv" + ctl.ID; } if (validation != null) { BaseValidator vc = validation.CreateValidator(container); tdVal.Controls.Add(vc); vc.ValidationGroup = "fc" + Type.Name; vc.ControlToValidate = ctl.ID; vc.Display = ValidatorDisplay.Dynamic; vc.ForeColor = Color.Red; vc.Text = "▲"; vc.ErrorMessage = "无效输入:" + field.DisplayName + ""; vc.ID = "cv" + ctl.ID; } } //the submit button var trSubmit = new TableRow(); tbl.Rows.Add(trSubmit); var tdSubmit = new TableCell(); trSubmit.Cells.Add(tdSubmit); tdSubmit.ColumnSpan = 3; tdSubmit.HorizontalAlign = HorizontalAlign.Right; tdSubmit.Controls.AddEx(new Button() { Text = "提交", ValidationGroup = "fc" + Type.Name }).Click += (ss, ee) => { if (((Page)HttpContext.Current.Handler).IsValid) actOnSubmit(); }; //the summary var trSummarny = new TableRow(); tbl.Rows.Add(trSummarny); var tdSummary = new TableCell(); trSummarny.Cells.Add(tdSummary); tdSummary.ColumnSpan = 3; tdSummary.Controls.Add(new ValidationSummary() { ValidationGroup = "fc" + Type.Name, ForeColor = Color.Red }); } public static void BindForm(WebControl container, T entity, bool isAdd = false) { AllField.ForEach(p => { var val = p.GetValue(entity); var octl = container.FindControl(p.ControlID); DymWebFormControlMappnig.GetInst(p.DataType, p.ValidationType).ControlSetValue(octl, val); }); } public static void BindEntity(WebControl container, T entity) { if (container == null) throw new ArgumentNullException("container"); AllField .Where(p => p.IsPK == false) .ForEach(p => { var octl = container.FindControl(p.ControlID); var val = DymWebFormControlMappnig.GetInst(p.DataType, p.ValidationType).ControlGetValue(octl); if (p.Validation is DynWebFormPasswordValidation && (val == null || val as string == "") ) return; p.SetValue(entity, val); }); } public static void RenderDetails(WebControl container, T entity, Func fkQuery = null, string[] arrSkipFields = null) { RenderDetailsInternal(container, entity, fkQuery, arrSkipFields); } public static void RenderDelete(WebControl container, T entity, Action actOnDeleteSubmit, Func fkQuery = null, string[] skipFields = null) { var tbl = RenderDetailsInternal(container, entity, fkQuery, skipFields); //the submit button var trSubmit = new TableRow(); tbl.Rows.Add(trSubmit); var tdSubmit = new TableCell(); trSubmit.Cells.Add(tdSubmit); tdSubmit.ColumnSpan = 3; tdSubmit.HorizontalAlign = HorizontalAlign.Right; tdSubmit.Controls.AddEx(new Button() { Text = "删除", }).Click += (ss, ee) => { if (((Page)HttpContext.Current.Handler).IsValid) actOnDeleteSubmit(); }; } public static Dictionary GetFieldNamesForGrid() { return AllField .Where(p => false == p.Validation is DynWebFormPasswordValidation) .ToDictionary(p => p.FieldName, p => p.DisplayName); } public static PropertyInfo GetFieldInfoForGrid(string name) { return AllField .Where(p => p.FieldName == name && false == p.Validation is DynWebFormPasswordValidation) .Select(p => p.PropertyInfo) .FirstOrDefault(); } } }