、
事出有因
在写程序的时候,经常会写上面这样的代码,把查询的结果显示到窗体上,我们怎么做的呢? 一行一行的进行赋值,这样的代码写起来最枯燥,而且还容易出错。大家有没有发现,上面的代码都在做相同的事情—赋值。相类似的代码写了三遍以上,就要考虑是不是能对这个过程进行封装。封装出一个方法,帮我们自动完成这些重复性的操作。
思考过程
所接触项目中也有写好的类似方法。只是它涉及到了很多其它的方法,一个套一个,抽离出来特别不方便。而且还有几个令人不爽的地方: 第一是,控件在命名的时候必须和相对应实体属性相同。比如说,姓名这一项,实体的属性名称为sname,那么控件的名称也必须是sname,显然这和我们所遵循的一般命名规范是相违背的。第二是,控件的可见性级别必须设置为Public ,要不然会赋不上值。
所以,在研究完他的方法后,对它重新进行了编写,做出了一些改进。弥补了上面的两个缺点,使其应用起来更加方便一些。
所用到的方法,题目中写提到了。编写第三方控件,听着挺高大上,其实就是对C#原有的控件,进行重写,增加一条自己用到的属性而已。在这里增加的属性我将它命名为DataField,用来保存数据库字段的名称。作用嘛?往下看就知道了。。
笔者在这用C#编写了一个Demo,用来说明如何编写第三方控件以及窗体的一键赋值。
具体实现过程
新建一个C#项目
添加一个接口 Interface1:
<span style="font-size:18px;"> interface Interface1 { //定义DataField属性 string DataField { get; set; } }</span>
添加两个类ComboxEx、ComboxEx:
using System.Windows.Forms; //添加引用 internal class TextBoxEx : TextBox, Interface1 { //该类继承TextBox控件和接口Interface1 #region Interface1 成员 public string DataField { get; set; } #endregion } internal class ComboxEx : ComboBox, Interface1 { #region Interface1 成员 public string DataField { get; set; } #endregion }
然后打开工具箱,我们会看到:
这就是我们封装的第三方控件。把它拖到窗体上,右击查看其属性
它多了一条DataField属性,我们可以给他赋上值SID(学生表的字段名—学号)同样再拖拽出几个控件并且赋值。
如图:
然后开始正式编写代码,添加一个实体类StuEntity:
注意:实体属性的名称要和数据库字段名称保持一致!
public class StuEntity { /// <summary> /// 学号 /// </summary> public string SID { get; set; } /// <summary> /// 姓名 /// </summary> public string sname { get; set; } /// <summary> /// 性别 /// </summary> public string sex { get; set; } /// <summary> /// 系别 /// </summary> public string department { get; set; } /// <summary> /// 年级 /// </summary> public string grade { get; set; } /// <summary> /// 班级 /// </summary> public string sclass { get; set; } }
需要说明的一点:这只是一个小Demo并没有采用分层的写法,把编写的方法全部放在了FrmHelper类中
public class FrmHelper { /// <summary> /// 获取实体,将DataTable的行赋值给实体类enStudent /// 这里可以采用机房中封装好的方法,将DataTable转换 /// 成实体类的泛型集合,可以省去这些赋值。 /// </summary> /// <param name="dr">DataTable的行</param> /// <returns>返回实体类enStudent</returns> public static StuEntity GetEntity(DataRow dr) { StuEntity enStudent = new StuEntity(); enStudent.SID = dr["SID"].ToString(); enStudent.sname = dr["sname"].ToString(); enStudent.sex = dr["sex"].ToString(); enStudent.department = dr["department"].ToString(); enStudent.grade = dr["grade"].ToString(); enStudent.sclass = dr["sclass"].ToString(); return enStudent; } /// <summary> /// 将实体类中属性的值,填充到窗体的控件上 /// </summary> /// <param name="enStudent"></param> public static void FillFormByEntity(StuEntity enStudent, Form thisfrm) { //遍历窗体上的控件 foreach (Control ctrl in thisfrm.Controls) { //是否继承了接口 if (ctrl is Interface1) { //是否属于文本框 if (ctrl is TextBoxEx) { ctrl.Text = GetValue(enStudent, ((TextBoxEx)ctrl).DataField); }//如果属于下拉框 else if (ctrl is ComboxEx) { ((ComboxEx)ctrl).Text = GetValue(enStudent, ((ComboxEx)ctrl).DataField); } //如果还有其他类型的控件,可在此进行扩展。 } } } /// <summary> /// 利用反射技术,动态的从实体中获取与控件相对应的值 /// </summary> /// <param name="enStudent">实体类</param> /// <param name="DataFiled">字段值</param> /// <returns></returns> public static string GetValue(StuEntity enStudent, string DataFiled) { PropertyInfo field = enStudent.GetType().GetProperty(DataFiled); return field.GetValue(enStudent, null).ToString(); } /// <summary> /// 执行查询语句,返回一个DateTable /// </summary> /// <returns>DateTable</returns> public static DataTable QueryTable() { using (SqlConnection connection = new SqlConnection("server=.; database=Re_Charge_sys;user id=sa;password=123456")) { SqlCommand cmd = connection.CreateCommand(); cmd.CommandText = @"select * from Student_info where SID ='110'"; DataTable dt = new DataTable(); DataSet ds = new DataSet(); try { connection.Open(); SqlDataAdapter sqlAdapter = new SqlDataAdapter(cmd); sqlAdapter.Fill(ds); dt = ds.Tables[0]; } catch (System.Data.SqlClient.SqlException ex) { throw new Exception(ex.Message); } return dt; } } }
客户端调用:
private void btnFillValue_Click(object sender, EventArgs e) { DataTable dt = FrmHelper.QueryTable(); StuEntity enStudent = FrmHelper.GetEntity(dt.Rows[0]); FrmHelper.FillFormByEntity(enStudent, this); } private void Form1_Load(object sender, EventArgs e) { cmbGrade.Items.AddRange(new String[] { "一年级", "二年级", "三年级", "四年级" }); cmbSex.Items.AddRange(new String[] { "男", "女" }); //cmbSex.Items.Add(new KeyValuePair<string, string>("男", "男")); //cmbSex.Items.Add(new KeyValuePair<string, string>("女", "女")); //cmbSex.DisplayMember = "Key"; //cmbSex.ValueMember = "Value"; }
点击赋值按钮,从数据库读取出的数据就会自动填写到界面控件当中。
谈谈第三方控件
当然通过这种方法也能增加其他的属性,比如NotEmpty ,把判断是否为空的方法写在接口里,然后让控件去继承。通过设置该属性的值为 True / False 决定控件内容是否可为空。通过这种方式就避免再去写方法去一个个判断,省时省力。说到这里我不得不感叹一下了:站在巨人的肩膀上。 其实现在互联网上已经有很多已经封装好的,强大的第三方控件。比如说现在所用的C1Studio,对常用控件进行了封装,增加很多特别方便实用的属性,
不得不说第三方控件现在挺吃香的,因为他给原来死的控件增加了生命力和色彩。
写在最后:
做程序员或者说做人,不能太实在、按部就班。
要多思考,多去寻找能“偷懒”的方法。
时刻想着,站在巨人的肩膀上。
给窗体控件赋值就写到这里,当然有赋值就有取值,将控件的值赋给实体,传到数据访问层再进行操作。也是MIS系统中经常用到的。方法和赋值类似,具体代码将在下篇博客中呈现给大家。
oノo════════════════════════════╲
│ヽ.学无止境, 分享至上。 │
│ 出自: http://blog.csdn.net/u010028869 .ヽ│
╲═════════════════════════════ヾ