MVC中有一点非常闪瞎人眼的功能就是,可以根据Model与View视图来直接将页面也数据模型进行绑定,那么我们在想客户端发送页面时不需要进行各种控件赋值,不需要操心怎么渲染,当客户提交表单给服务器时也不需要进行过多的处理直接就能叫表单进行模型化。
那么我们在WebFrom中能否实现类似的功能呢,答案是肯定的。
第一步:建立模型。也就是将表单看着是一个对象,建立相关的属性。
namespace Models { using System; using System.Collections.Generic; public partial class CST_cust_info { public int cust_id { get; set; } public string cust_no { get; set; } public string cust_full_name { get; set; } public string cust_master_org_no { get; set; } public string contract_type { get; set; } public string cust_short_name { get; set; } public string cust_mail { get; set; } } }
第二步:建立页面与之对应(这里需要理解一个概念就是表单无论怎么变,最终提交到服务器后服务器对于表单是只认name,不认识其他的。如果表单的那么重复他也不管简单的合起来,还有客户端认识的控件就是靠runat=”server“属性和id来识别,所以name和id这两个东西一定需要处理好,当然通常在runat=‘server‘的情况下,系统渲染的时候直接将id赋值给name属性)
<form id="formCC" runat="server"> <asp:DropDownList ID="txt_card_type_id" runat="server"> </asp:DropDownList> <asp:DropDownList ID="txt_person_sex" runat="server" Width="94px"> </asp:DropDownList> <asp:TextBox ID="txt_brith_date" runat="server"></asp:TextBox> <asp:TextBox ID="txt_certificate_date" runat="server" ></asp:TextBox> <asp:TextBox ID="txt_person_no" runat="server" ></asp:TextBox> </FROM>...
第三步:建立方法 让Model直接渲染到前台(这里只是简单的赋值,如果是通过render就更美妙了)
PS:1、这里面id名字因为项目中容易冲突,所以将这种反射交互的名称换成 Name=>"txt_"+Name模式来进行映射处理
2、这里需要了解的项目中经常使用的控件类型,一般居多的是WebControl 和HtmlInputControl,其中WebControl指的是继承WebControl这个类型的控件,一般有TextBox,Label等,HtmlInputControl控件就是一些<input runat="server">控件,两者区别在于渲染机制不一样,但是最后还是
/// <summary> /// 处理一对一信息 /// </summary> /// <param name="CustPage"></param> /// <param name="LableName"></param> /// <param name="CSTModel"></param> private static void FillMainCust<T>( CustPage CustPage, Dictionary<string, string> LableName, T CSTModel, int? sort = null) { if (CSTModel != null) { foreach (string key in LableName.Keys) { PropertyInfo pinfo = CSTModel.GetType().GetProperty(key); Control txtname = CustPage.FindControl<Control>("txt_" + key)); if (pinfo != null && txtname != null) { object PinValue = (pinfo.GetValue(CSTModel) ?? ""); string PinStr = ""; if (PinValue is DateTime || PinValue is DateTime?) { PinStr = ((DateTime)PinValue).ToString("yyyy-MM-dd"); } else { if (PinValue is decimal || PinValue is decimal?) { PinStr = ((Decimal)PinValue).ToString("0.00"); } else { PinStr = PinValue.ToString(); } } #region 根据类型赋值 if (txtname is TextBox) { ((TextBox)txtname).Text = PinStr; } else if (txtname is Label) { ((Label)txtname).Text = PinStr; } else if (txtname is HiddenField) { ((HiddenField)txtname).Value = PinStr; } #endregion #region 特殊处理 if (txtname is Label) { if (CustDictory.Special_Dictionary.Keys.Contains(key)) { ((Label)txtname).Text = P2PTable.GetSpecialValue(PinStr, CustDictory.Special_Dictionary[key]); } } #endregion #region 处理DropDownList赋值 if (txtname is DropDownList) { if (((DropDownList)txtname).Items.FindByValue(PinStr) != null) { ((DropDownList)txtname).SelectedValue = PinStr; } else { if (((DropDownList)txtname).Items.FindByText(PinStr) != null) { ((DropDownList)txtname).Items.FindByText(PinStr).Selected = true; } } } #endregion #region 处理隐藏控件赋值 if (txtname is System.Web.UI.HtmlControls.HtmlInputHidden) { ((System.Web.UI.HtmlControls.HtmlInputHidden)txtname).Value = PinStr; } #endregion } } } }
第四步: 提交时将from表单填充进入Model对象中 PS:1、此时就不需要考虑控件问题 只需要考虑From表单提交的数据即可,这里from表单提交我们已经在前面渲染的时候做好准备了
2、代码中为了节省性能所以就不遍历对象属性了,直接建立字典来保存要取的值,如果是不需要考虑这些可以直接取值
foreach (string key in LableName.Keys) { string value = CustPage.Request.Form["txt_" + key]; PropertyInfo pinfo = custInfo.GetType().GetProperty(key); if (value != null && pinfo != null) { object NewVlue = value.StringtoObject(pinfo); pinfo.SetValue(custInfo, NewVlue); } }
好~简单的一种反射机制与From表单特性结合的MV已经完成
这个示例我们需要了解的是:1、from表单是根据name进行提交的。
2、服务器控件最终都是要渲染给客户端的,有些控件是服务器不处理的
3、简单的一些反射使用
4、要正确理解服务端与客户端所干的事情