之前为F.Grid做了扩展,自动生成了三个按钮,并和本身的window控件联动弹出编辑窗口。编辑窗口以F.Form为主,这次我把F.Form控件增加扩展,主要用于绑定数据,拿取数据,自动验证并提交,以及简单的布局。
FineUICore本身有model和表单的对照demo,就是MVC的传统写法,通过用模型绑定控件,但是我项目里的Model是没有特性的,就是传统的类
/// <summary> /// ID /// </summary> public int Id { get; set; }
所以如果为表单控件赋值就要写成 ID.Text = ms.XXX;,如果能实现自动匹配映射是很减少工作量的。
首先要在js为F.Form扩展 setValue 和 getValue 方法,将Model的Json格式绑定到表单的各个控件,然后在取值返回Json格式,传到后台(.cs)再转为Model进行保存操作。
这种模式绑定和读取数据很像Grid的操作,Grid中有两个关键属性,DataIDField 和 DataField 属性,一个是标识字段名,一个是绑定的字段名,如果我为F.Form()(.cshtml)扩展这两个属性
F.Form().Width(900).LabelWidth(100).BodyPadding(5).EnableCollapse(true) .ID("Form1").Title("表单1") .DataIDField("Id")//数据标识字段名
表单项
F.TextBox().Label("姓名").DataField("Name")//字段名称 F.DropDownList().Label("性别").DataField("Gender")//字段名称
那么js怎么获取到我绑定的 Id,Name,Gender 呢,这里用到了F自带的为HTML标签扩展的属性 Attribute ,该属性在 ControlBaseExtension 下,所有控件继承,该方法直接为HTML标签生成一个属性,js通过 attr 很容易就拿到了,把这个属性拿到,然后直接和JSON匹配就行了。
点击F.Form(),按F12,
// // 摘要: // 表单面板控件扩展 public FormExtension Form();
FineUIEx类中扩展增加方法 DataIDField
/// <summary> /// 数据标识字段名 /// </summary> /// <param name="f">控件实例</param> /// <param name="DataIDField">主键字段</param> /// <returns></returns> public static FormExtension DataIDField(this FormExtension f, string DataIDField) { //为Form增加属性 f.Attribute("DataID", DataIDField); return f; }
字段的DataField,在Form的FormRow.Items中参数为IControlBaseExtension[]
// // 摘要: // 子控件集合 // // 参数: // extensions: public FormRowExtension Items(params IControlBaseExtension[] extensions);
如果将DataField扩展到IControlBaseExtension中,会有问题,所有控件都继承IControlBaseExtension,但是我只需要输入的控件 比如 TextBox 或 DropDownList ,又不能每个控件都单独扩展,所以找到所有文本输入控件都继承的类 FieldExtension
// // 摘要: // 表单字段基类扩展 // // 类型参数: // T: // // TExtension: public abstract class FieldExtension
这里还要注意,DataField 方法返回的是当前实例,即谁继承FieldExtension就返回谁(比如F.DropDownList()有DataSource方法而F.TextBox()没有,如果返回统一类型将无法继承该控件实例的单独属性)。
FineUICore自己就解决了这个问题,比如 Label 方法,就在FieldExtension下,所有表单控件继承,
// // 摘要: // 标签文本 // // 参数: // param: public TExtension Label(string param);
注意该方法的返回类型是TExtension,泛型,哪来的呢,上层传过来的,比如 DropDownList控件,
// // 摘要: // 下拉列表控件扩展 public class DropDownListExtension : TextFieldExtension<DropDownList, DropDownListExtension>
看<DropDownList, DropDownListExtension>,他已经把自己的类型,通过T参数传到他的继承类中了,所以Label后还可以返回当前实例,落在表单的DataField中,应该这么写
/// <summary> /// 绑定数据字段 /// </summary> /// <typeparam name="T"></typeparam> /// <typeparam name="TExtension"></typeparam> /// <param name="f"></param> /// <param name="datafield"></param> /// <returns></returns> public static TExtension DataField<T, TExtension>(this FieldExtension<T, TExtension> f,string datafield) where T : Field where TExtension : FieldExtension<T, TExtension> { f.Attribute("data", datafield); return (TExtension)f; }
到此对.cshtml的扩展就结束了,下面是js的扩展,主要是用attr方法,查找 DataID 和 data 属性
if (F.Form) { $.extend(F.Form.prototype, { //得到数据 (是否验证) getdata: function (isv) { var t = this; var data = t.initData || {}; if (isv) { if (!F.validateForm(t.id, '_self', false, false)) { return false; } } var datael = $(t.el).find(".f-field[data]"); //循环表单项 $.each(datael, function (i, v) { var id = $(v).attr("id"); var d = $(v).attr("data").replace("Data_", ""); //如果存在data属性 if (d) { //取值 data[d] = F.ui[id].getValue(); //注意日期控件 取text,否则会提取出时间戳 if (F.ui[id].type == 'datepicker') { data[d] = F.ui[id].getText(); } } }) //返回json return data; }, //设置数据 setdata: function (data) { var t = this; t.initData = data; var datael = $(t.el).find(".f-field[data]"); //绑定dataid var dataid = $(t.el).attr("DataID"); if (dataid && dataid != '') { F.ui[t.id].beforDataID = F.ui[t.id].DataID; F.ui[t.id].DataID = data[dataid]; }; //循环表单项 $.each(datael, function (i, v) { var id = $(v).attr("id"); var d = $(v).attr("data").replace("Data_", ""); if (d && (typeof data[d]) != 'undefined') { //找到data属性,并赋值 F.ui[id].setValue(data[d]); } }) } }); }
扩展完成,使用时可以直接这样
表单控件(.cshtml)
F.Form().Width(900).LabelWidth(100).BodyPadding(5).EnableCollapse(true) .ID("Form1").Title("表单1") .DataIDField("Id")
表单项(.cshtml)
F.TextBox().Label("姓名").DataField("Name").Requ(true), F.DropDownList().Label("性别").DataField("Gend.Required(true) .Items( F.ListItem().Text("男").Value("1"), F.ListItem().Text("女").Value("0") ), F.TextBox().Label("入学年份").DataField("EntranceYear"), F.DropDownList().Label("是否在校").DataField("AtSchool") .Items( F.ListItem().Text("是").Value("1"), F.ListItem().Text("否").Value("0") ), F.TextBox().Label("所学专业").DataField("Major"), F.TextBox().Label("分组").DataField("Group")
js(.cshtml)
F.ready(function () { F.ui['Form1'].setdata(@Html.Raw(ViewBag.data)); })
后台.cs
public ActionResult Index() { MsStudent ms1 = new MsStudent(); //得到实体数据 ms1 = studentHelper.GetMsById(Convert.ToInt32(101)); ViewBag.data = JObject.FromObject(ms1).ToString(); return View(); }
具体效果,可以在FineUIMVC扩展中查看。
本文作者:没想好
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!