统一表单设计器,表的CRUD操作,统一到列表界面和编辑界面

10 篇文章 0 订阅

上一篇我们可以自动为每一个表生成列表和编辑界面,如果有多个表,将生成许多个编辑和列表界面,也是不方便的。

我们可以尝试一种只使用一个列表界面和一个编辑界面,兼容所有表(泛型T)的设计界面。

整体思路:为统一的、共同的列表界面(FrmGenerateList)和编辑界面(FrmGenerateEdit)增加一个泛型T,这个泛型T其实就是表名对应的类。使用时通过反射来映射这个泛型窗体即可。

注意:

列表窗体的类名是泛型的FrmGenerateList<T>

编辑窗体的类名也是泛型的FrmGenerateEdit<T>

新建Winform应用程序CommonFormDesignerDemo。(.net framework 4.5)。

添加引用 System.Configuration,NPOI,SqlSugar类库框架。

添加Mysql数据库操作类库MySql.Data.dll

可以直接利用我们的实体类工具生成表对应的实体类。

自动生成实体类

在解决方案项目添加配置文件:\Conf\DataGridViewConf_Form.xls,并将DataGridViewConf_Form.xls 文件的属性 【复制到输出目录】 设置为 【始终复制】

DataGridViewConf_Form.xls文件的设计如图:

将默认的Form1重命名为FrmNavigate,用于所有相关表的导航。

导航窗体 FrmNavigate的设计如下:

【一个TreeView和一个panel】

统一公共泛型列表窗体 FrmGenerateList 设计【DataGridView用于显示数据】

统一公共泛型编辑窗体 FrmGenerateEdit 设计

一、添加对MySql数据库基本的类SugarDao.cs,源程序如下

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using SqlSugar;

namespace CommonFormDesignerDemo
{
    /// <summary>
    /// SqlSugar
    /// </summary>
    public class SugarDao
    {
        //禁止实例化
        private SugarDao()
        {

        }

        /// <summary>
        /// 需添加对System.Configuration的引用
        /// </summary>
        /// <param name="index">1为Mysql连接 2为SqlServer连接</param>
        /// <returns></returns>
        public static string ConnectionString(int index = 1)
        {
            string reval = "server=localhost;Database=eve_db;Uid=root;Pwd=12345"; //这里可以动态根据cookies或session实现多库切换
            if (index == 1)
                reval = System.Configuration.ConfigurationManager.ConnectionStrings["MySqlDataConnect"].ConnectionString;//连接字符串
            else if (index == 2)
                reval = System.Configuration.ConfigurationManager.ConnectionStrings["SqlServerDataConnect"].ConnectionString;//连接字符串
            return reval;
        }
        public static SqlSugarClient GetInstance(SqlSugar.DbType dbType = SqlSugar.DbType.MySql, int index = 1)
        {
            return new SqlSugarClient(new ConnectionConfig()
            {
                DbType = dbType,
                ConnectionString = ConnectionString(index),
                InitKeyType = InitKeyType.Attribute,
                IsAutoCloseConnection = true,
                AopEvents = new AopEvents
                {
                    OnLogExecuting = (sql, p) =>
                    {
                        Console.WriteLine(sql);
                        Console.WriteLine(string.Join(",", p?.Select(it => it.ParameterName + ":" + it.Value)));
                    }
                }
            });
        }
        /// <summary>
        /// 检查数据库连接
        /// </summary>
        public static void CheckConnect()
        {
            var db = GetInstance();
            db.Open();
        }
    }
}

二、添加原生的数据库操作RawSql.cs,源程序如下

using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CommonFormDesignerDemo
{
    /// <summary>
    /// 原生的sql增删改查
    /// </summary>
    public class RawSql
    {
        /// <summary>
        /// 执行原生的Sql与sql参数的insert、update、delete等操作,返回受影响的行数
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="dict"></param>
        /// <param name="dbType">数据库类型,一般是mysql</param>
        /// <param name="index">额外的连接数据库,2为新的数据库连接字符串</param>
        /// <returns></returns>
        public static int ExecuteCommand(string sql, Dictionary<string, object> dict, SqlSugar.DbType dbType = SqlSugar.DbType.MySql, int index = 1)
        {
            List<SugarParameter> parameters = DictToList(dict);
            using (var db = SugarDao.GetInstance(dbType, index))
            {
                return db.Ado.ExecuteCommand(sql, parameters);
            }
        }

        /// <summary>
        /// 执行原生的Sql与sql参数的select查询等操作,返回首行首列的数据
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="dict"></param>
        /// <param name="dbType">数据库类型,一般是mysql</param>
        /// <param name="index">额外的连接数据库,2为新的数据库连接字符串</param>
        /// <returns></returns>
        public static object GetScalar(string sql, Dictionary<string, object> dict, SqlSugar.DbType dbType = SqlSugar.DbType.MySql, int index = 1)
        {
            List<SugarParameter> parameters = DictToList(dict);
            using (var db = SugarDao.GetInstance(dbType, index))
            {
                return db.Ado.GetScalar(sql, parameters);
            }
        }

        /// <summary>
        /// 执行原生的Sql与sql参数的select查询等操作,返回一个数据表
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="dict"></param>
        /// <param name="dbType">数据库类型,一般是mysql</param>
        /// <param name="index">额外的连接数据库,2为新的数据库连接字符串</param>
        /// <returns></returns>
        public static DataTable GetDataTable(string sql, Dictionary<string, object> dict, SqlSugar.DbType dbType = SqlSugar.DbType.MySql, int index = 1)
        {
            List<SugarParameter> parameters = DictToList(dict);
            using (var db = SugarDao.GetInstance(dbType, index))
            {
                return db.Ado.GetDataTable(sql, parameters);
            }
        }

        /// <summary>
        /// 字典转参数列表
        /// </summary>
        /// <param name="dict"></param>
        /// <returns></returns>
        private static List<SugarParameter> DictToList(Dictionary<string, object> dict)
        {
            List<SugarParameter> parameters = new List<SugarParameter>();
            for (int i = 0; dict != null && i < dict.Count; i++)
            {
                KeyValuePair<string, object> keyValuePair = dict.ElementAt(i);
                parameters.Add(new SugarParameter(keyValuePair.Key, keyValuePair.Value));
            }
            return parameters;
        }

        /// <summary>
        /// 查询表的相关项,生成一个内存表
        /// </summary>
        /// <param name="selectItems"></param>
        /// <param name="where_expression"></param>
        /// <param name="dictAddPara"></param>
        /// <param name="tableName"></param>
        /// <param name="tableNameAs"></param>
        /// <param name="orderfild"></param>
        /// <returns></returns>
        public static DataTable Select_By_Expression(string selectItems, string where_expression, Dictionary<string, object> dictAddPara, string tableName, string tableNameAs, string orderfild = "")
        {
            DataTable dataTable = new DataTable(tableName);
            using (var db = SugarDao.GetInstance())
            {
                if (!selectItems.Contains(orderfild))
                {
                    orderfild = "";
                }
                var datax = db.Queryable(tableName, tableNameAs).Where(where_expression).AddParameters(dictAddPara).Select(selectItems).OrderByIF(orderfild != "", orderfild);
                try
                {
                    dataTable = datax.ToDataTable();
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"【查询出现异常】表【{tableName}】-{ex.Message}");
                }
                return dataTable;
            }
        }
    }
}

三、添加读写Excel操作NpoiExcelOperateUtil.cs,源程序如下

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CommonFormDesignerDemo
{
    public static class NpoiExcelOperateUtil
    {
        #region Excel操作
        /// <summary>
        /// Excel的第一个工作簿(Sheet)转化成DataTable
        /// 使用EXCEL的第一个工作簿,默认为Sheet1
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        public static DataTable ExcelToTable(string file)
        {
            DataTable dt = new DataTable();
            IWorkbook workbook;
            string fileExt = Path.GetExtension(file).ToLower();
            using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
            {
                //XSSFWorkbook 适用XLSX格式,HSSFWorkbook 适用XLS格式
                if (fileExt == ".xlsx")
                {
                    workbook = new XSSFWorkbook(fs);
                }
                else if (fileExt == ".xls")
                {
                    workbook = new HSSFWorkbook(fs);
                }
                else
                {
                    return null;
                }
                //第一个工作簿
                ISheet sheet = workbook.GetSheetAt(0);
                if (sheet == null)
                {
                    return null;
                }
                return ExcelToTable(file, sheet.SheetName);
            }
        }
        /// <summary>
        /// Excel的指定Sheet转化成内存表
        /// </summary>
        /// <param name="file">路径</param>
        /// <param name="sheetName">sheet名称</param>
        /// <returns></returns>
        public static DataTable ExcelToTable(string file, string sheetName)
        {
            DataTable[] dataTables = ExcelToTable(file, new List<string>() { sheetName });
            if (dataTables != null && dataTables.Length > 0)
            {
                return dataTables[0];
            }
            return null;
        }

        /// <summary>
        /// 一个excel文件的多个Sheet转化成内存表数组,
        /// 每个Sheet都对应一个数据表
        /// </summary>
        /// <param name="file">路径</param>
        /// <param name="list_SheetName">sheet名称集合</param>
        /// <returns></returns>
        public static DataTable[] ExcelToTable(string file, List<string> list_SheetName)
        {
            int count = list_SheetName.Count;
            DataTable[] dtS = new DataTable[count];
            //===============================//
            IWorkbook workbook;
            string fileExt = Path.GetExtension(file).ToLower();
            using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
            {
                //XSSFWorkbook 适用XLSX格式,HSSFWorkbook 适用XLS格式
                if (fileExt == ".xlsx")
                {
                    workbook = new XSSFWorkbook(fs);
                }
                else if (fileExt == ".xls")
                {
                    workbook = new HSSFWorkbook(fs);
                }
                else
                {
                    return null;
                }
                ISheet[] sheetS = new ISheet[count];
                for (int k = 0; k < count; k++)
                {
                    dtS[k] = new DataTable(list_SheetName[k]);
                    sheetS[k] = workbook.GetSheet(list_SheetName[k]);
                    ISheet sheet = sheetS[k];
                    if (sheet == null)
                    {
                        continue;
                    }
                    DataTable dt = new DataTable(list_SheetName[k]);
                    //表头  
                    IRow header = sheet.GetRow(sheet.FirstRowNum);
                    List<int> columns = new List<int>();
                    for (int i = 0; i < header.LastCellNum; i++)
                    {
                        object obj = GetValueType(header.GetCell(i));
                        if (obj == null || obj.ToString() == string.Empty)
                        {
                            dt.Columns.Add(new DataColumn("Columns" + i.ToString()));
                        }
                        else
                            dt.Columns.Add(new DataColumn(obj.ToString()));
                        columns.Add(i);
                    }
                    //数据  
                    for (int i = sheet.FirstRowNum + 1; i <= sheet.LastRowNum; i++)
                    {
                        DataRow dr = dt.NewRow();
                        bool hasValue = false;
                        foreach (int j in columns)
                        {
                            dr[j] = GetValueType(sheet.GetRow(i).GetCell(j));
                            if (dr[j] != null && dr[j].ToString() != string.Empty)
                            {
                                hasValue = true;
                            }
                        }
                        if (hasValue)
                        {
                            dt.Rows.Add(dr);
                        }
                    }
                    dtS[k] = dt;
                }
            }
            return dtS;
        }

        /// <summary>
        /// Datable导出成Excel
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="file"></param>
        public static void TableToExcel(DataTable dt, string file)
        {
            IWorkbook workbook;
            string fileExt = Path.GetExtension(file).ToLower();
            if (fileExt == ".xlsx")
            {
                //workbook = new XSSFWorkbook();
                workbook = new HSSFWorkbook();
            }
            else if (fileExt == ".xls")
            {
                workbook = new HSSFWorkbook();
            }
            else
            {
                workbook = null;
            }
            if (workbook == null)
            {
                return;
            }
            ISheet sheet = string.IsNullOrEmpty(dt.TableName) ? workbook.CreateSheet("Sheet1") : workbook.CreateSheet(dt.TableName);
            //表头  
            IRow row = sheet.CreateRow(0);
            for (int i = 0; i < dt.Columns.Count; i++)
            {
                ICell cell = row.CreateCell(i);
                cell.SetCellValue(dt.Columns[i].ColumnName);
            }

            //数据  
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                IRow row1 = sheet.CreateRow(i + 1);
                for (int j = 0; j < dt.Columns.Count; j++)
                {
                    ICell cell = row1.CreateCell(j);
                    cell.SetCellValue(dt.Rows[i][j].ToString());
                }
            }

            //转为字节数组  
            MemoryStream stream = new MemoryStream();
            workbook.Write(stream);
            var buf = stream.ToArray();

            //保存为Excel文件  
            using (FileStream fs = new FileStream(file, FileMode.Create, FileAccess.Write))
            {
                fs.Write(buf, 0, buf.Length);
                fs.Flush();
            }
        }

        /// <summary>
        /// 获取单元格类型
        /// </summary>
        /// <param name="cell"></param>
        /// <returns></returns>
        private static object GetValueType(ICell cell)
        {
            if (cell == null)
                return null;
            switch (cell.CellType)
            {
                case CellType.Blank: //BLANK:  
                    return null;
                case CellType.Boolean: //BOOLEAN:  
                    return cell.BooleanCellValue;
                case CellType.Numeric: //NUMERIC:  
                    return cell.NumericCellValue;
                case CellType.String: //STRING:  
                    return cell.StringCellValue;
                case CellType.Error: //ERROR:  
                    return cell.ErrorCellValue;
                case CellType.Formula: //FORMULA:  
                default:
                    return "=" + cell.CellFormula;
            }
        }
        #endregion
    }
}

四、添加对数据列表的操作辅助类 DataGridViewUtil.cs,源程序如下

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CommonFormDesignerDemo
{
    /// <summary>
    /// 将Excel的配置映射到一个内存数据表中,然后为DataGridView设置数据绑定,以及自动生成列
    /// </summary>
    public class DataGridViewUtil
    {
        /// <summary>
        /// 初始化设置DataGridView的列和相关数据绑定
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="dgvw"></param>
        public static void DataGridViewIni(DataTable dt, ref DataGridView dgvw)
        {
            dgvw.Columns.Clear();
            string tableName = dt.TableName;
            try
            {
                if (dt != null && dt.Rows.Count > 0)
                {
                    if (!dt.Columns.Contains("En_Name"))
                    {
                        MessageBox.Show($"{tableName}表的UI配置文件错误,请检查--不存在En_Name列");
                        return;
                    }
                    if (!dt.Columns.Contains("Another_Name"))
                    {
                        MessageBox.Show($"{tableName}表的UI配置文件错误,请检查--不存在Another_Name列");
                        return;
                    }
                    if (!dt.Columns.Contains("Use"))
                    {
                        MessageBox.Show($"{tableName}表的UI配置文件错误,请检查--不存在Use列");
                        return;
                    }
                    if (!dt.Columns.Contains("Table_Name"))
                    {
                        MessageBox.Show($"{tableName}表的UI配置文件错误,请检查--不存在Table_Name列");
                        return;
                    }
                    int columnCount = dt.Rows.Count;
                    if (dt.Rows[0]["Table_Name"] == null || tableName != dt.Rows[0]["Table_Name"].ToString().Trim())
                    {
                        MessageBox.Show($"{tableName}表的UI配置文件错误,请检查--表名与表中Table_Name不匹配");
                        return;
                    }

                    for (int i = 0; i < columnCount; i++)
                    {
                        string isUse = dt.Rows[i]["Use"].ToString().Trim();
                        if (isUse != "1")
                        {
                            continue;//不添加
                        }
                        string columnName = dt.Rows[i]["En_Name"].ToString();
                        string columnDescription = dt.Rows[i]["Another_Name"].ToString();
                        DataGridViewColumn dgvc = new DataGridViewColumn();
                        dgvc.CellTemplate = new DataGridViewTextBoxCell();
                        dgvc.Name = "dgvc_" + columnName;
                        int minWidth = 50;
                        bool rtn = int.TryParse(dt.Rows[i]["Min_Width"].ToString(), out minWidth);
                        if (!rtn)
                        {
                            minWidth = 50;
                        }
                        dgvc.MinimumWidth = minWidth;
                        dgvc.DataPropertyName = columnName;
                        dgvc.HeaderText = (columnDescription == null || columnDescription.Trim().Length == 0) ? columnName : columnDescription;
                        dgvw.Columns.Add(dgvc);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"{tableName}表的UI配置文件错误,请检查:" + ex.Message);
            }
            return;
        }
    }
}

五、自动生成控件表单的辅助类 AutoGenerateUtil.cs,源程序如下

using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CommonFormDesignerDemo
{
    /// <summary>
    /// 自动生成窗体相关控件代码 以及绑定内容,以及读取控件的值绑定到实体类的属性上等相关操作类
    /// 斯内科 2021-02-01
    /// </summary>
    public class AutoGenerateUtil
    {
        /// <summary>
        /// 获取主键列 和 条码列的名称
        /// </summary>
        /// <param name="_primaryKeyField"></param>
        /// <param name="_barcodeField"></param>
        public static void GetPrimaryKeyAndBarcodeField<T>(out string _primaryKeyField, out string _barcodeField)
        {
            _primaryKeyField = "CoreId";
            _barcodeField = "Barcode";
            Type type = typeof(T);
            //调用实例化方法(非静态方法)需要创建类型的一个实例
            object instanceObject = Activator.CreateInstance(type);
            //遍历所有可交互控件,获取控件的Tag以及对应的值,并为属性赋值
            IEnumerable<PropertyInfo> propertyCollection = type.GetProperties().Where(property => property.CustomAttributes.Count() > 0);
            //查找主键列名
            PropertyInfo propertyPrimaryKey = propertyCollection.Where(property => property.CustomAttributes.
              Where(attrData => attrData.NamedArguments.Where(attrArg => attrArg.MemberName == "IsPrimaryKey").Count() > 0).Count() > 0).FirstOrDefault();
            if (propertyPrimaryKey == null)
            {
                MessageBox.Show("没有配置实体类的主键列特性:IsPrimaryKey");
                return;
            }
            _primaryKeyField = propertyPrimaryKey.Name;

            //找到指定的条码列 [SqlSugar.SugarColumn(ColumnDescription = "Barcode")]
            PropertyInfo propertyBarcode = propertyCollection.Where(property => property.CustomAttributes.
              Where(attrData => attrData.NamedArguments.Where(attrArg => attrArg.MemberName == "ColumnDescription" && Convert.ToString(attrArg.TypedValue.Value) == "Barcode").Count() > 0).Count() > 0).FirstOrDefault();
            if (propertyBarcode == null)
            {
                MessageBox.Show($"没有配置实体类的条码列【查询条件列】特性:ColumnDescription = \"Barcode\"");
                return;
            }
            _barcodeField = propertyBarcode.Name;
        }

        /// <summary>
        /// 使用表设计器初始化DataGridView的列绑定,以及增加 编辑和删除列
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="dgw_Data"></param>
        public static void InitialDataGridViewColumns(DataTable dt, DataGridView dgw_Data)
        {
            dgw_Data.AutoGenerateColumns = false;
            DataGridViewUtil.DataGridViewIni(dt, ref dgw_Data);
            //增加编辑、删除列
            DataGridViewButtonColumn dgvcEdit = new DataGridViewButtonColumn();
            dgvcEdit.Name = "dgvcEdit";
            dgvcEdit.HeaderText = "编辑";
            dgvcEdit.Text = "编辑";
            dgvcEdit.ReadOnly = true;
            dgvcEdit.UseColumnTextForButtonValue = true;//显示按钮列的单元格的文本
            dgw_Data.Columns.Add(dgvcEdit);

            DataGridViewButtonColumn dgvcDelete = new DataGridViewButtonColumn();
            dgvcDelete.Name = "dgvcDelete";
            dgvcDelete.HeaderText = "删除";
            dgvcDelete.Text = "删除";
            dgvcDelete.ReadOnly = true;
            dgvcDelete.UseColumnTextForButtonValue = true;
            dgw_Data.Columns.Add(dgvcDelete);
        }

        /// <summary>
        /// 绑定查询的数据到DataGridView上
        /// </summary>
        /// <param name="keyword">查询的条件</param>
        /// <param name="barcodeField">查询的字段</param>
        /// <param name="selectItemCollection">选择的列集合,以逗号拼接</param>
        /// <param name="currentTableName">查询的表名</param>
        /// <param name="dgw_Data">要绑定的DataGridView</param>
        public static void BindDataList(string keyword, string barcodeField, string selectItemCollection, string currentTableName, DataGridView dgw_Data)
        {
            string tableNameAs = "tb";//表的别名
            Dictionary<string, object> dictAddPara = new Dictionary<string, object>();//SQL中的参数以及对应的值
            List<string> conditionCollection = new List<string>();
            //如果关键字不为空
            if (keyword.Length > 0)
            {
                conditionCollection.Add($"{tableNameAs}.{barcodeField}=@PackBarcode");
                dictAddPara.Add("PackBarcode", keyword);
            }

            //默认使用and连接
            string where_expression = string.Join(" and ", conditionCollection);
            string tableName = currentTableName;//查找的表名
            DataTable dtTemp = new DataTable(currentTableName);
            dtTemp = RawSql.Select_By_Expression(selectItemCollection, where_expression, dictAddPara, tableName, tableNameAs);
            dgw_Data.DataSource = dtTemp;
        }

        /// <summary>
        /// 初始化创建相关设计类的所有控件信息
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="form"></param>
        public static void InitialCreateControls(DataTable dt, Form form)
        {
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                string formVisible = dt.Rows[i]["Form_Visible"].ToString();
                if (formVisible != "1")
                {
                    //如果不显示就 忽略
                    continue;
                }
                string chineseName = dt.Rows[i]["Ch_Name"].ToString();//标签中文名
                string englishName = dt.Rows[i]["En_Name"].ToString();//英文名
                string dataType = dt.Rows[i]["Data_Type"].ToString();//数据类型
                string defaultValue = dt.Rows[i]["Default_Value"].ToString();//默认值
                string formCollection = dt.Rows[i]["Form_Collection"].ToString();//组合下拉框 或者 单选按钮的项集合,使用|(竖线)分割
                string formMin = dt.Rows[i]["Form_Min"].ToString();//数字显示框的下限值
                string formMax = dt.Rows[i]["Form_Max"].ToString();//数字显示框的上限值
                string formLocationX = dt.Rows[i]["Form_Location_X"].ToString();//起始位置坐标X
                string formLocationY = dt.Rows[i]["Form_Location_Y"].ToString();//起始位置坐标Y
                int locationX;//X坐标
                int locationY;//Y坐标
                int.TryParse(formLocationX, out locationX);
                int.TryParse(formLocationY, out locationY);
                FormCategory formCategory;
                if (!Enum.TryParse(dt.Rows[i]["Form_Category"].ToString(), true, out formCategory))
                {
                    //默认使用文本框
                    formCategory = FormCategory.TextBox;
                }
                Label lbl = AutoGenerateUtil.SetLabel(chineseName, englishName, locationX + 5 - 120, locationY);
                switch (formCategory)
                {
                    case FormCategory.None:
                        break;
                    case FormCategory.TextBox:
                        form.Controls.Add(lbl);//增加标签显示

                        TextBox txb = SetTextBox(englishName, defaultValue, locationX, locationY);
                        form.Controls.Add(txb);
                        break;
                    case FormCategory.ComboBox:
                        form.Controls.Add(lbl);//增加标签显示

                        ComboBox cbo = SetComboBox(englishName, defaultValue, formCollection, locationX, locationY);
                        form.Controls.Add(cbo);
                        break;
                    case FormCategory.RadioButton:
                        form.Controls.Add(lbl);//增加标签显示

                        //这里使用GroupBox包含所有的单选按钮
                        GroupBox grp = SetGroupAndRadioButton(englishName, formCollection, locationX, locationY);
                        form.Controls.Add(grp);
                        break;
                    case FormCategory.DateTimePicker:
                        form.Controls.Add(lbl);//增加标签显示

                        DateTimePicker dtp = SetDateTimePicker(englishName, locationX, locationY);
                        form.Controls.Add(dtp);
                        break;
                    case FormCategory.NumericUpDown:
                        form.Controls.Add(lbl);//增加标签显示

                        NumericUpDown numericUpDown = SetNumericUpDown(englishName, dataType, formMin, formMax, locationX, locationY);
                        form.Controls.Add(numericUpDown);
                        break;
                }
            }
        }

        /// <summary>
        /// 绑定控件的初始值【从数据库中读取】
        /// </summary>
        /// <param name="dataTable"></param>
        public static void BindControlValue(DataTable dataTable, Form form)
        {
            if (dataTable == null || dataTable.Rows.Count < 1)
            {
                return;
            }
            DataRow dataRow = dataTable.Rows[0];
            for (int i = 0; i < form.Controls.Count; i++)
            {
                Control control = form.Controls[i];
                if (control is Label || control is Button || control.Tag == null)
                {
                    //不考虑标签 或者 Tag为null的控件
                    continue;
                }
                string fieldName = Convert.ToString(control.Tag);
                //NumericUpDown控件的Tag特殊处理,使用二元组,第一个项代表绑定的列名(字段名),第二个项代表数据类型
                if (control is NumericUpDown)
                {
                    fieldName = (control.Tag as Tuple<string, string>).Item1;
                }
                //如果数据表的列集合中不含有该字段,则忽略
                if (!dataTable.Columns.Contains(fieldName))
                {
                    continue;
                }

                //为指定的控件赋值
                if (control is TextBox)
                {
                    ((TextBox)control).Text = dataRow[fieldName].ToString();
                }
                else if (control is ComboBox)
                {
                    ComboBox cbo = control as ComboBox;
                    for (int index = 0; index < cbo.Items.Count; index++)
                    {
                        if (cbo.Items[index].ToString() == dataRow[fieldName].ToString())
                        {
                            cbo.SelectedIndex = index;
                            break;
                        }
                    }
                }
                else if (control is GroupBox)
                {
                    //设置RadioButton的选中
                    GroupBox grp = control as GroupBox;
                    for (int index = 0; index < grp.Controls.Count; index++)
                    {
                        RadioButton rdo = grp.Controls[index] as RadioButton;
                        if (rdo != null && rdo.Text == dataRow[fieldName].ToString())
                        {
                            rdo.Checked = true;
                            break;
                        }
                        else if (rdo != null)
                        {
                            rdo.Checked = false;
                        }
                    }
                }
                else if (control is DateTimePicker)
                {
                    ((DateTimePicker)control).Value = Convert.ToDateTime(dataRow[fieldName]);
                }
                else if (control is NumericUpDown)
                {
                    ((NumericUpDown)control).Value = Convert.ToDecimal(dataRow[fieldName]);
                }
            }
        }

        /// <summary>
        /// 遍历所有可交互控件,获取控件的Tag以及对应的值,并为实体类的对应属性赋值
        /// </summary>
        /// <param name="type"></param>
        /// <param name="instanceObject"></param>
        public static void SetInstanceObjectPropertyValues(Type type, object instanceObject, Form form)
        {
            for (int i = 0; i < form.Controls.Count; i++)
            {
                Control control = form.Controls[i];
                if (control is Label || control is Button || control.Tag == null)
                {
                    //不考虑标签 或者 Tag为null的控件
                    continue;
                }
                //找出控件的数据对象 也就是属性名(字段名、列名)
                string fieldName = Convert.ToString(control.Tag);
                //NumericUpDown控件的Tag特殊处理,使用二元组,第一个项代表绑定的列名(字段名),第二个项代表数据类型
                if (control is NumericUpDown)
                {
                    fieldName = (control.Tag as Tuple<string, string>).Item1;
                }
                PropertyInfo propertyInfoName = type.GetProperty(fieldName);
                //如果类不存在该属性,则忽略
                if (propertyInfoName == null)
                {
                    continue;
                }

                //为指定的控件赋值
                if (control is TextBox)
                {
                    propertyInfoName.SetValue(instanceObject, ((TextBox)control).Text);
                }
                else if (control is ComboBox)
                {
                    ComboBox cbo = control as ComboBox;
                    propertyInfoName.SetValue(instanceObject, ((ComboBox)control).Text);
                }
                else if (control is GroupBox)
                {
                    //设置RadioButton的选中
                    GroupBox grp = control as GroupBox;
                    for (int index = 0; index < grp.Controls.Count; index++)
                    {
                        RadioButton rdo = grp.Controls[index] as RadioButton;
                        if (rdo != null && rdo.Checked)
                        {
                            propertyInfoName.SetValue(instanceObject, rdo.Text);
                            break;
                        }
                    }
                }
                else if (control is DateTimePicker)
                {
                    propertyInfoName.SetValue(instanceObject, ((DateTimePicker)control).Value);
                }
                else if (control is NumericUpDown)
                {
                    NumericUpDown numericUpDown = control as NumericUpDown;
                    string dataType = (numericUpDown.Tag as Tuple<string, string>).Item2;
                    if (dataType != null && dataType.IndexOf("int", StringComparison.CurrentCultureIgnoreCase) >= 0)
                    {
                        propertyInfoName.SetValue(instanceObject, Convert.ToInt32(numericUpDown.Value));
                    }
                    else if (dataType != null && dataType.IndexOf("decimal", StringComparison.CurrentCultureIgnoreCase) >= 0)
                    {
                        propertyInfoName.SetValue(instanceObject, numericUpDown.Value);
                    }
                    else
                    {
                        propertyInfoName.SetValue(instanceObject, Convert.ToSingle(numericUpDown.Value));
                    }
                }
            }
        }

        /// <summary>
        /// 设置Label标签控件
        /// </summary>
        /// <param name="chineseName"></param>
        /// <param name="englishName"></param>
        /// <param name="locationX"></param>
        /// <param name="locationY"></param>
        /// <returns></returns>
        private static Label SetLabel(string chineseName, string englishName, int locationX, int locationY)
        {
            Label lbl = new Label();
            //如果字体较多 就设置为两行。如果字体的宽度少于16个空格【八个中文宽度大小】,就补充空格数:(16 - bufferSize.Length)
            byte[] bufferSize = Encoding.GetEncoding("gbk").GetBytes(chineseName);
            if (bufferSize.Length > 16)
            {
                lbl.Size = new Size(110, 26);
            }
            else
            {
                chineseName = chineseName.PadLeft(chineseName.Length + 16 - bufferSize.Length);
                lbl.AutoSize = true;
            }
            lbl.Name = $"lbl{englishName}";
            lbl.Text = chineseName;
            lbl.Location = new Point(locationX, locationY);
            return lbl;
        }

        /// <summary>
        /// 设置文本框控件
        /// </summary>
        /// <param name="englishName"></param>
        /// <param name="defaultValue"></param>
        /// <param name="locationX"></param>
        /// <param name="locationY"></param>
        /// <returns></returns>
        private static TextBox SetTextBox(string englishName, string defaultValue, int locationX, int locationY)
        {
            TextBox txb = new TextBox();
            txb.Name = $"txb{englishName}";
            txb.Text = defaultValue;
            txb.Location = new Point(locationX, locationY);
            txb.Size = new Size(200, 21);
            txb.Tag = englishName;//增加控件 绑定的列名(字段名)
            return txb;
        }

        /// <summary>
        /// 设置组合框控件
        /// </summary>
        /// <param name="englishName"></param>
        /// <param name="defaultValue"></param>
        /// <param name="formCollection"></param>
        /// <param name="locationX"></param>
        /// <param name="locationY"></param>
        /// <returns></returns>
        private static ComboBox SetComboBox(string englishName, string defaultValue, string formCollection, int locationX, int locationY)
        {
            ComboBox cbo = new ComboBox();
            cbo.Name = $"cbo{englishName}";
            cbo.Text = defaultValue;
            cbo.Location = new Point(locationX, locationY);
            if (!string.IsNullOrEmpty(formCollection))
            {
                string[] itemArray = formCollection.Split('|');
                for (int index = 0; index < itemArray.Length; index++)
                {
                    cbo.Items.Add(itemArray[index]);
                }
            }
            cbo.Size = new Size(200, 21);
            cbo.Tag = englishName;//增加控件 绑定的列名(字段名)
            return cbo;
        }

        /// <summary>
        /// 设置分组框和单选按钮集合【多个单选按钮放入在同一个分组框中】
        /// </summary>
        /// <param name="englishName"></param>
        /// <param name="formCollection"></param>
        /// <param name="locationX"></param>
        /// <param name="locationY"></param>
        /// <returns></returns>
        private static GroupBox SetGroupAndRadioButton(string englishName, string formCollection, int locationX, int locationY)
        {
            //这里使用GroupBox包含所有的单选按钮
            GroupBox grp = new GroupBox();
            grp.Name = $"grp{englishName}";
            //grp.Text = chineseName;
            grp.Location = new Point(locationX, locationY - 20);
            grp.Size = new Size(200, 40);
            grp.Tag = englishName;//增加控件 绑定的列名(字段名)

            if (string.IsNullOrEmpty(formCollection))
            {
                formCollection = "选项一";
            }
            string[] itemArr = formCollection.Split('|');
            for (int index = 0; index < itemArr.Length; index++)
            {
                RadioButton rdo = new RadioButton();
                rdo.Name = $"rdo{englishName}{index + 1}";
                rdo.Text = itemArr[index];
                rdo.Location = new Point(10 + 70 * index, 20);
                rdo.AutoSize = true;
                if (index == 0)
                {
                    rdo.Checked = true;//设置第一项为选中
                }
                grp.Controls.Add(rdo);
            }
            return grp;
        }

        /// <summary>
        /// 设置日期时间选择控件
        /// </summary>
        /// <param name="englishName"></param>
        /// <param name="locationX"></param>
        /// <param name="locationY"></param>
        /// <returns></returns>
        private static DateTimePicker SetDateTimePicker(string englishName, int locationX, int locationY)
        {
            DateTimePicker dtp = new DateTimePicker();
            dtp.Name = $"dtp{englishName}";
            dtp.Value = DateTime.Now;
            dtp.Location = new Point(locationX, locationY);
            dtp.Format = DateTimePickerFormat.Custom; //设置日期格式为2020-08-05
            dtp.CustomFormat = "yyyy-MM-dd HH:mm:ss";
            dtp.Tag = englishName;//增加控件 绑定的列名(字段名)
            return dtp;
        }

        /// <summary>
        /// 设置数字显示框控件
        /// NumericUpDown控件的Tag特殊处理,使用二元组,第一个项代表绑定的列名(字段名),第二个项代表数据类型
        /// </summary>
        /// <param name="englishName"></param>
        /// <param name="dataType"></param>
        /// <param name="formMin"></param>
        /// <param name="formMax"></param>
        /// <param name="locationX"></param>
        /// <param name="locationY"></param>
        /// <returns></returns>
        private static NumericUpDown SetNumericUpDown(string englishName, string dataType, string formMin, string formMax, int locationX, int locationY)
        {
            NumericUpDown numericUpDown = new NumericUpDown();
            numericUpDown.Name = $"numericUpDown{englishName}";
            //numericUpDown.Value = DateTime.Now;
            numericUpDown.Location = new Point(locationX, locationY);
            numericUpDown.Size = new Size(200, 121);
            decimal decMin;
            decimal decMax;
            decimal.TryParse(formMin, out decMin);
            decimal.TryParse(formMax, out decMax);
            numericUpDown.Minimum = decMin;
            if (decMax > decMin)
            {
                numericUpDown.Maximum = decMax;
            }
            //如果是int类型
            if (dataType != null && dataType.IndexOf("int", StringComparison.CurrentCultureIgnoreCase) >= 0)
            {
                numericUpDown.DecimalPlaces = 0;
            }
            else if (dataType != null && dataType.IndexOf("decimal", StringComparison.CurrentCultureIgnoreCase) >= 0)
            {
                //decimal设置为4位小数
                numericUpDown.DecimalPlaces = 4;
            }
            else
            {
                //float,double设置为2位小数
                numericUpDown.DecimalPlaces = 2;
            }

            //NumericUpDown控件的Tag特殊处理,使用二元组,第一个项代表绑定的列名(字段名),第二个项代表数据类型
            numericUpDown.Tag = Tuple.Create(englishName, dataType);//增加控件 绑定的列名(字段名)
            return numericUpDown;
        }
    }

    /// <summary>
    /// 表单(字段)对应的控件类型
    /// </summary>
    public enum FormCategory
    {
        /// <summary>
        /// 自增或者默认当前时间的字段显示
        /// </summary>
        None = -1,
        /// <summary>
        /// 文本框,比如条码
        /// </summary>
        TextBox = 0,
        /// <summary>
        /// 组合框,下拉等选项
        /// </summary>
        ComboBox = 1,
        /// <summary>
        /// 单选按钮控件
        /// </summary>
        RadioButton = 2,
        /// <summary>
        /// 日期时间字段
        /// </summary>
        DateTimePicker = 3,
        /// <summary>
        /// 数字显示框
        /// </summary>
        NumericUpDown = 4
    }
}

六、统一列表窗体FrmGenerateList.cs的主要程序如下(忽略设计器自动生成的代码):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CommonFormDesignerDemo
{
    public partial class FrmGenerateList<T> : Form where T : class, new()
    {
        /// <summary>
        /// 表Excel设计器
        /// </summary>
        DataTable dt = new DataTable("FormDesign");
        /// <summary>
        /// 表名 或者 Excel工作簿名
        /// </summary>
        string CurrentTableName = "test_msg";
        /// <summary>
        /// 所有英文名称集合【列集合】,以英文逗号(,)拼接
        /// </summary>
        string selectItems = string.Empty;
        /// <summary>
        /// 主键字段名
        /// </summary>
        string primaryKeyField = string.Empty;
        /// <summary>
        /// 条码字段名
        /// </summary>
        string barcodeField = string.Empty;
        public FrmGenerateList(string sheetName)
        {
            InitializeComponent();
            this.Text = this.Text + $"_表单【{sheetName}】";
            CurrentTableName = sheetName;
            //获取主键列 和 条码(查询条件对应的字段)列的名称
            AutoGenerateUtil.GetPrimaryKeyAndBarcodeField<T>(out primaryKeyField, out barcodeField);
            dt = NpoiExcelOperateUtil.ExcelToTable(AppDomain.CurrentDomain.BaseDirectory + "Conf\\DataGridViewConf_Form.xls", sheetName);

            //所有英文名称集合【列集合】
            string[] DataPropertyNameArr = new string[dt.Rows.Count];
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                DataPropertyNameArr[i] = dt.Rows[i]["En_Name"].ToString();
            }
            selectItems = string.Join(",", DataPropertyNameArr);

            AutoGenerateUtil.InitialDataGridViewColumns(dt, dgw_Data);
        }

        private void FrmGenerateList_Load(object sender, EventArgs e)
        {
            btnQuery_Click(null, e);
        }

        private void btnQuery_Click(object sender, EventArgs e)
        {
            AutoGenerateUtil.BindDataList(txbBarcode_query.Text.Trim(), barcodeField, selectItems, CurrentTableName, dgw_Data);
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            FrmGenerateEdit<T> frmGenerateEdit = new FrmGenerateEdit<T>(CurrentTableName, primaryKeyField);
            DialogResult dialog = frmGenerateEdit.ShowDialog();
            if (dialog == DialogResult.OK)
            {
                btnQuery_Click(null, e);//刷新
            }
        }

        private void dgw_Data_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex < 0 || e.ColumnIndex < 0)
            {
                return;
            }
            int coreId = Convert.ToInt32(dgw_Data[$"dgvc_{primaryKeyField}", e.RowIndex].Value);
            if (dgw_Data.Columns[e.ColumnIndex].Name == "dgvcEdit") //编辑操作
            {
                FrmGenerateEdit<T> frmGenerateEdit = new FrmGenerateEdit<T>(coreId, CurrentTableName, primaryKeyField);
                DialogResult dialog = frmGenerateEdit.ShowDialog();
                if (dialog == DialogResult.OK)
                {
                    btnQuery_Click(null, e);//刷新
                }
            }
            else if (dgw_Data.Columns[e.ColumnIndex].Name == "dgvcDelete") //删除操作
            {
                DialogResult dialog = MessageBox.Show($"您确定要删除该条记录吗?一经删除,不可恢复!\n当前编号【{coreId}】", "警告", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                if (dialog != DialogResult.Yes)
                {
                    return;
                }
                try
                {
                    //根据主键值删除
                    using (var db = SugarDao.GetInstance())
                    {
                        db.Deleteable<T>(coreId).ExecuteCommand();
                    }
                    //CRUD_test_msg.DeleteByCoreId(coreId);
                    btnQuery_Click(null, e);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "删除时出现异常");
                }
            }
        }
    }
}

七、统一编辑窗体FrmGenerateEdit.cs的主要程序如下(忽略设计器自动生成的代码):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CommonFormDesignerDemo
{
    public partial class FrmGenerateEdit<T> : Form where T : class, new()
    {
        /// <summary>
        /// 添加【insert=true】 还是 修改【update=false】 表单
        /// </summary>
        bool isAdd = true;
        int coreId = -1;
        DataTable dt = new DataTable("FormDesign");
        /// <summary>
        /// 表名 或者 Excel工作簿名
        /// </summary>
        string CurrentTableName = "test_msg";
        /// <summary>
        /// 当前主键列名
        /// </summary>
        string PrimaryKeyField = "CoreId";
        public FrmGenerateEdit(string sheetName, string primaryKeyField)
        {
            InitializeComponent();
            isAdd = true;
            CurrentTableName = sheetName;
            dt = NpoiExcelOperateUtil.ExcelToTable(AppDomain.CurrentDomain.BaseDirectory + "Conf\\DataGridViewConf_Form.xls", sheetName);
        }

        public FrmGenerateEdit(int _coreId, string sheetName, string primaryKeyField) : this(sheetName, primaryKeyField)
        {
            coreId = _coreId;
            isAdd = false;
        }

        private void FrmGenerateEdit_Load(object sender, EventArgs e)
        {
            AutoGenerateUtil.InitialCreateControls(dt, this);

            //如果是修改表单,则从数据库中读取数据行,并为文本框赋值
            if (!isAdd)
            {
                DataTable dataTable = new DataTable("xxx");
                using (var db = SugarDao.GetInstance())
                {
                    dataTable = db.Queryable<T>().Where($"{PrimaryKeyField}=@CoreId", new Dictionary<string, object>() { { "CoreId", coreId } }).ToDataTable();
                }
                if (dataTable == null || dataTable.Rows.Count < 1)
                {
                    MessageBox.Show($"没有找到符合条件的记录,该行数据不存在或者已经被删除,当前编号【{coreId}】");
                    return;
                }
                AutoGenerateUtil.BindControlValue(dataTable, this);
            }
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            try
            {
                Type type = typeof(T);// typeof(HansMySqlSugar.Models.test_aa);
                //调用实例化方法(非静态方法)需要创建类型的一个实例
                object instanceObject = Activator.CreateInstance(type);
                //遍历所有可交互控件,获取控件的Tag以及对应的值,并为属性赋值
                AutoGenerateUtil.SetInstanceObjectPropertyValues(type, instanceObject, this);

                T test_aaObj = (T)instanceObject;
                int affectCount = -1;
                if (isAdd)
                {
                    using (var db = SugarDao.GetInstance())
                    {
                        affectCount = db.Insertable(test_aaObj).ExecuteCommand();
                    }
                }
                else
                {
                    //更新一条数据 按照 主键
                    PropertyInfo propertyInfoName = type.GetProperty($"{PrimaryKeyField}");
                    //如果类不存在主键属性,则报警
                    if (propertyInfoName == null)
                    {
                        MessageBox.Show($"没有找到关键主键字段【{PrimaryKeyField}】,无法更新");
                    }
                    //必须为主键CoreId赋值,否则CoreId将为默认值0,就完了
                    propertyInfoName.SetValue(instanceObject, coreId);
                    using (var db = SugarDao.GetInstance())
                    {
                        affectCount = db.Updateable(test_aaObj).Where($"{PrimaryKeyField}=@CoreIdUpdate", new Dictionary<string, object>() { { "CoreIdUpdate", coreId } }).ExecuteCommand();
                    }
                }
                MessageBox.Show($"保存【{(isAdd ? "添加" : "更新")}】表【{CurrentTableName}】信息成功,受影响的行数【{affectCount}】");
                this.DialogResult = DialogResult.OK;
            }
            catch (Exception ex)
            {
                MessageBox.Show($"保存【{(isAdd ? "添加" : "更新")}】表信息【{CurrentTableName}】失败,异常信息:\n{ex.Message}");
            }
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.Cancel;
            this.Close();
        }
    }
}

八、导航窗体FrmNavigate.cs的主要程序如下(忽略设计器自动生成的代码):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CommonFormDesignerDemo
{
    public partial class FrmNavigate : Form
    {
        public FrmNavigate()
        {
            InitializeComponent();
        }

        private void FrmNavigate_Load(object sender, EventArgs e)
        {
            //这里也可以通过Excel配置表单的工作簿名集合,或者 从数据库的表名集合加载
            tvTables.Nodes[0].Nodes.AddRange(new TreeNode[] 
            {
                new TreeNode("input_output_log"),
                new TreeNode("input_output_msg"),
                new TreeNode("pallet_bind_pack")
            });
            tvTables.ExpandAll();
        }

        private void tvTables_AfterSelect(object sender, TreeViewEventArgs e)
        {
            panel1.Controls.Clear();
            if (e.Node.Parent == null)
            {
                //如果是根节点,就不考虑
                return;
            }
            /* 直接实例化对应的窗体
            Form formEx = new Form();
            switch (e.Node.Text)
            {
                case "input_output_log":
                    formEx = new FrmGenerateList<CommonFormDesignerDemo.Models.input_output_log>(e.Node.Text);
                    break;
                case "input_output_msg":
                    formEx = new FrmGenerateList<CommonFormDesignerDemo.Models.input_output_msg>(e.Node.Text);
                    break;
                case "pallet_bind_pack":
                    formEx = new FrmGenerateList<CommonFormDesignerDemo.Models.pallet_bind_pack>(e.Node.Text);
                    break;
            }
            formEx.TopLevel = false;
            formEx.Parent = panel1;
            panel1.Controls.Add(formEx);
            formEx.Show();
            */

            System.Reflection.Assembly assembly = System.Reflection.Assembly.Load(Application.ProductName);
            Type typeGeneric = assembly.GetType($"{Application.ProductName}.Models.{e.Node.Text}");
            Type typeForm = typeof(FrmGenerateList<>);
            Type type = typeForm.MakeGenericType(typeGeneric);
            //反射泛型窗体类
            object instanceObject = Activator.CreateInstance(type, e.Node.Text);
            Form form = instanceObject as Form;
            form.TopLevel = false;//一定要将TopLevel设置为false,否则不能添加
            form.Parent = panel1;
            panel1.Controls.Add(form);
            form.Show();            
        }
    }
}

九、运行如图:

点击添加 或者 编辑 按钮

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
使用JdbcTemplate实现用户CRUD操作非常简单和高效。JdbcTemplate是Spring框架提供的一个持久化框架,通过对JdbcTemplate进行配置和应用可以实现对数据库的访问和操作。 首先,我们需要创建一个User类来示用户的实体,包含用户名、密码、邮箱等属性。然后,在数据库中创建一个用户结构与User类对应。接下来,在Spring配置文件中配置数据源和JdbcTemplate。在配置文件中指定数据源的连接信息,然后将数据源和JdbcTemplate配置为Spring容的bean。 在代码中,我们可以通过@Autowired注解将JdbcTemplate注入到UserService类中,然后就可以使用JdbcTemplate对用户进行CRUD操作了。例如,要插入一个新用户,可以使用JdbcTemplate的update方法执行SQL插入语句。要删除一个用户,可以使用JdbcTemplate的update方法执行SQL删除语句。要更新一个用户的信息,可以使用JdbcTemplate的update方法执行SQL更新语句。要查询一个用户的信息,可以使用JdbcTemplate的queryForObject方法执行SQL查询语句。 使用JdbcTemplate实现用户CRUD操作具有很多优势。首先,它可以将所有的JDBC操作封装在一个类中,简化了代码的编写。其次,它提供了丰富的方法来执行SQL语句,可以满足各种不同的数据库操作需求。同时,它还支持事务管理,可以保证数据库操作的一致性和完整性。 总的来说,通过使用JdbcTemplate实现用户CRUD操作可以提高代码的可读性和可维护性,同时还可以让开发者更加专注于业务逻辑的实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

斯内科

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值