123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433 |
- 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<T>
- {
- private static readonly Type Type = typeof(T);
- private static readonly FormField<T>[] AllField;
- private static readonly FormField<T> PkField;
- static DymWebForm()
- {
- AllField = FormFieldFactory<T>.GetFormFields();
- PkField = AllField.FirstOrDefault(p => p.IsPK);
- if (PkField == null)
- throw new ArgumentException("Must define PK");
- }
- private static void ProcTdFK(Func<Type, object[], object[]> fkQuery, List<FieldFK<T>> 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<Type, object[], object[]> 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<FieldFK<T>> lstFKs = new List<FieldFK<T>>();
- //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<T> { Field = field, Td = td, FKVal = objVal });
- }
- }
- if (fkQuery != null)
- {
- ProcTdFK(fkQuery, lstFKs);
- }
- return tbl;
- }
-
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="container">容器, 要求已经添加到Page</param>
- /// <param name="dataSource">数据源</param>
- /// <param name="arrSkipFields">跳过的字段(如密码)</param>
- /// <param name="fkQuery">外键查询回调</param>
- /// <param name="urlEdit">{0}=ID 默认 ?op=edit&arg={0}</param>
- /// <param name="urlDelete">{0}=ID 默认 ?op=delete&arg={0}</param>
- public static void RenderGrid(Control container, IEnumerable<T> dataSource, string[] arrSkipFields
- , Func<Type, object[], object[]> 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<FieldFK<T>> lstFKs = new List<FieldFK<T>>();
- 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<T> { 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 = "<br>*留空保持不变" });
- 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 = "必填字段:<b>" + field.DisplayName + "</b>";
- 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 = "无效输入:<b>" + field.DisplayName + "</b>";
- 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<Type, object[], object[]> fkQuery = null, string[] arrSkipFields = null)
- {
- RenderDetailsInternal(container, entity, fkQuery, arrSkipFields);
- }
- public static void RenderDelete(WebControl container, T entity, Action actOnDeleteSubmit, Func<Type, object[], object[]> 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<string, string> 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();
- }
- }
- }
|