• 表格批量编辑与Undo/Redo功能实现


    利用EAP.Entity提供的可以Undo/Redo的列表绑定数据到DataGridView,让表格批量编辑更方便更高效。

    1. 还是利用AccountGroup表的结构,然后得到实体AccountGroupModel:

    1     [System.Serializable()]
      2     public class AccountGroupModels : System.Collections.Generic.List<AccountGroupModel>
      3     {
      4 
      5         public AccountGroupModels()
      6         {
      7         }
      8 
      9         public AccountGroupModels(System.Collections.Generic.IEnumerable<AccountGroupModel> collection) :
     10             base(collection)
     11         {
     12         }
     13     }
     14 
     15     /// <summary>
     16     /// <para></para>
     17     /// </summary>
     18     [System.Serializable()]
     19     public partial class AccountGroupModel : EAP.Entity.DataObject<AccountGroupModel>
     20     {
     21         #region Member Property Region
     22         /// <summary>
     23         /// <para>主键</para>
     24         /// </summary>
     25         [EAP.Data.ColumnInfoAttribute(Visible = false, Queryable = true, DbColumn = "Id")]
     26         public int Id
     27         {
     28             get
     29             {
     30                 return GetValue<int>("Id");
     31             }
     32             set
     33             {
     34                 SetValue("Id", value);
     35             }
     36         }
     37 
     38         /// <summary>
     39         /// <para>名称</para>
     40         /// </summary>
     41         [EAP.Data.ColumnInfoAttribute(DbColumn = "Name")]
     42         public string Name
     43         {
     44             get
     45             {
     46                 return GetValue<string>("Name");
     47             }
     48             set
     49             {
     50                 SetValue("Name", value);
     51             }
     52         }
     53 
     54         /// <summary>
     55         /// <para>上级组别</para>
     56         /// </summary>
     57         [EAP.Data.ColumnInfoAttribute(DbColumn = "Parent")]
     58         public int Parent
     59         {
     60             get
     61             {
     62                 return GetValue<int>("Parent");
     63             }
     64             set
     65             {
     66                 SetValue("Parent", value);
     67             }
     68         }
     69 
     70         /// <summary>
     71         /// <para>可见性</para>
     72         /// </summary>
     73         [EAP.Data.ColumnInfoAttribute(DbColumn = "Visible")]
     74         public bool Visible
     75         {
     76             get
     77             {
     78                 return GetValue<bool>("Visible");
     79             }
     80             set
     81             {
     82                 SetValue("Visible", value);
     83             }
     84         }
     85 
     86         /// <summary>
     87         /// <para>修改者</para>
     88         /// </summary>
     89         [EAP.Data.ColumnInfoAttribute(DbColumn = "UpdateUser")]
     90         public string UpdateUser
     91         {
     92             get
     93             {
     94                 return GetValue<string>("UpdateUser");
     95             }
     96             set
     97             {
     98                 SetValue("UpdateUser", value);
     99             }
    100         }
    101 
    102         /// <summary>
    103         /// <para>修改时间</para>
    104         /// </summary>
    105         [EAP.Data.ColumnInfoAttribute(DbColumn = "UpdateDate")]
    106         public System.DateTime UpdateDate
    107         {
    108             get
    109             {
    110                 return GetValue<System.DateTime>("UpdateDate");
    111             }
    112             set
    113             {
    114                 SetValue("UpdateDate", value);
    115             }
    116         }
    117         #endregion
    118     }
    复制代码

    2. 定义业务接口:

    复制代码
     1     interface IAccountGroupManager
     2     {
     3         /// <summary>
     4         /// 加载Models
     5         /// </summary>
     6         /// <param name="name"></param>
     7         /// <returns></returns>
     8         AccountGroupModels GetModels(string name);
     9         /// <summary>
    10         /// 保存
    11         /// </summary>
    12         /// <param name="models">需要保存的列表</param>
    13         /// <param name="user">更新者</param>
    14         void Save(List<AccountGroupModel> models, string user);
    15         /// <summary>
    16         /// 加载所有可见的账户组
    17         /// </summary>
    18         /// <returns></returns>
    19         ValueTextList GetGroupList();
    20     }
    复制代码

     3. GetModels方法的实现 

    复制代码
     1         public AccountGroupModels GetModels(string name)
     2         {
     3             AccountGroupTable table = new AccountGroupTable();
     4             SelectStatement sql = DataAccess.DefaultDB
     5                 .Select(table, table.AllColumns())//读取所有字段
     6                 .OrderBy(table.UpdateDate.Desc);//按修改时间倒序
     7             if (!name.IsNullOrEmpty())//如果名称不为空,添加模糊查询条件
     8                 sql.Where(table.Name.Like("%" + name + "%"));
     9             using (SafeDataReader sdr = sql.ToSafeDataReader())
    10             {
    11                 AccountGroupModels models = new AccountGroupModels();
    12                 while (sdr.Read())
    13                 {
    14                     AccountGroupModel m = new AccountGroupModel();
    15                     m.BeginInit();//把model的状态设为Initializing,修改值时不会触发什么事件
    16                     sdr.Fetch(m, table);//把数据加载到model
    17                     m.EndInit();
    18                     models.Add(m);
    19                 }
    20                 return models;
    21             }
    22         }

    2. 定义业务接口:

    复制代码
     1     interface IAccountGroupManager
     2     {
     3         /// <summary>
     4         /// 加载Models
     5         /// </summary>
     6         /// <param name="name"></param>
     7         /// <returns></returns>
     8         AccountGroupModels GetModels(string name);
     9         /// <summary>
    10         /// 保存
    11         /// </summary>
    12         /// <param name="models">需要保存的列表</param>
    13         /// <param name="user">更新者</param>
    14         void Save(List<AccountGroupModel> models, string user);
    15         /// <summary>
    16         /// 加载所有可见的账户组
    17         /// </summary>
    18         /// <returns></returns>
    19         ValueTextList GetGroupList();
    20     }
    复制代码

     3. GetModels方法的实现 

    复制代码
     1         public AccountGroupModels GetModels(string name)
     2         {
     3             AccountGroupTable table = new AccountGroupTable();
     4             SelectStatement sql = DataAccess.DefaultDB
     5                 .Select(table, table.AllColumns())//读取所有字段
     6                 .OrderBy(table.UpdateDate.Desc);//按修改时间倒序
     7             if (!name.IsNullOrEmpty())//如果名称不为空,添加模糊查询条件
     8                 sql.Where(table.Name.Like("%" + name + "%"));
     9             using (SafeDataReader sdr = sql.ToSafeDataReader())
    10             {
    11                 AccountGroupModels models = new AccountGroupModels();
    12                 while (sdr.Read())
    13                 {
    14                     AccountGroupModel m = new AccountGroupModel();
    15                     m.BeginInit();//把model的状态设为Initializing,修改值时不会触发什么事件
    16                     sdr.Fetch(m, table);//把数据加载到model
    17                     m.EndInit();
    18                     models.Add(m);
    19                 }
    20                 return models;
    21             }
    22         }
    复制代码

     4. Save方法的实现

    复制代码
     1         public void Save(List<AccountGroupModel> models, string user)
     2         {
     3             Validator v = new Validator();//构建验证器
     4             using (DbTransaction tran = DataAccess.DefaultDB.BeginTransaction())//开始事务
     5             {
     6                 foreach (var m in models)
     7                 {
     8                     CheckModel(v, m, tran);//验证数据
     9                     m.UpdateUser = user;
    10                     m.UpdateDate = System.DateTime.Now;
    11                     if (m.DataState == DataState.Created)
    12                         AddModel(m, tran);
    13                     else if (m.DataState == DataState.Modified)
    14                         UpdateModel(m, tran);
    15                     else if (m.DataState == DataState.Deleted)
    16                         DeleteModel(m, tran);
    17                 }
    18                 if (!v.IsValid)//验证不通过时抛出异常
    19                     throw new ValidationException(v);
    20                 tran.Commit();
    21             }
    22         }
    复制代码

    5. CheckModel方法

    复制代码
     1         protected bool Exists(AccountGroupModel model, DbTransaction tran)
     2         {
     3             AccountGroupTable table = new AccountGroupTable();
     4             SelectStatement sql = DataAccess.DefaultDB
     5                 .Select(table, table.AllColumns(false).Count())
     6                 .SetTransaction(tran)
     7                 .Where(table.Name == model.Name);
     8             if (model.DataState != EAP.Entity.DataState.Created)
     9                 sql.Where(table.Id != model.Id);
    10             return sql.ToScalar<int>() > 0;
    11         }
    12 
    13         protected void CheckModel(Validator v, AccountGroupModel model, DbTransaction tran)
    14         {
    15             //名称不能为空,长度不能超过64字符
    16             if (v.Require(model.Name, "Name", model.DisplayIndex)
    17                 && v.MaxLength(model.Name, 64, "Name", model.DisplayIndex))
    18             {
    19                 //名称不能重复
    20                 v.Assert(!Exists(model, tran), "Name", model.DisplayIndex, ErrorText.Exists);
    21             }
    22             v.MaxLength(model.UpdateUser, 32, "UpdateUser", model.DisplayIndex);
    23         }
    复制代码

     6. 窗口中的代码

    1     public partial class DemoForm : KryptonForm
      2     {
      3         //业务接口
      4         IAccountGroupManager manager;
      5         //实体列表
      6         DataObjectList<AccountGroupModel> models = new DataObjectList<AccountGroupModel>();
      7 
      8         public DemoForm()
      9         {
     10             InitializeComponent();
     11             //创建接口的实现
     12             manager = new RefObjectCreator().Create<IAccountGroupManager>();
     13             //把实体绑定到BindingSource
     14             accountGroupModelBindingSource.DataSource = models;
     15             models.ListChanged += new EventHandler<ListChangedEventArgs<AccountGroupModel>>(models_ListChanged);
     16             CancelEdit();
     17         }
     18 
     19         void models_ListChanged(object sender, ListChangedEventArgs<AccountGroupModel> e)
     20         {
     21             btnUndo.Enabled = models.CanUndo;
     22             btnRedo.Enabled = models.CanRedo;
     23             btnSave.Enabled = models.HasChanged;
     24         }
     25 
     26         void LoadData()
     27         {
     28             //加载上级组别的数据
     29             ValueTextList parent = manager.GetGroupList();
     30             parent.Insert(0, new ValueTextPair(0, ""));
     31             parentBindingSource.DataSource = parent;
     32             //加载实现的数据
     33             AccountGroupModels source = manager.GetModels(txtName.Text);
     34             models.Clear();
     35             models.BeginInit();//加载时不触发绑定的事件
     36             models.AddRange(source);
     37             models.EndInit();
     38             accountGroupModelBindingSource.ResetBindings(false);
     39             CancelEdit();
     40         }
     41 
     42         void BeginEdit()
     43         {
     44             models.BeginEdit();
     45             grid.ReadOnly = false;
     46             btnNew.Enabled = true;
     47             btnDelete.Enabled = true;
     48             btnEdit.Enabled = false;
     49             btnCancel.Enabled = true;
     50             grid.StateNormal.DataCell.Back.Color1 = Color.Empty;
     51             idDataGridViewTextBoxColumn.ReadOnly = true;
     52             updateDateDataGridViewTextBoxColumn.ReadOnly = true;
     53             updateUserDataGridViewTextBoxColumn.ReadOnly = true;
     54         }
     55 
     56         void CancelEdit()
     57         {
     58             models.CancelEdit();
     59             grid.ReadOnly = true;
     60             btnNew.Enabled = false;
     61             btnDelete.Enabled = false;
     62             btnSave.Enabled = false;
     63             btnUndo.Enabled = false;
     64             btnRedo.Enabled = false;
     65             btnEdit.Enabled = true;
     66             btnCancel.Enabled = false;
     67             pnlErrorInfo.Visible = false;
     68             grid.StateNormal.DataCell.Back.Color1 = SystemColors.Info;
     69             accountGroupModelBindingSource.ResetBindings(false);
     70         }
     71 
     72         #region 工具条按钮事件
     73 
     74         private void btnSearch_Click(object sender, EventArgs e)
     75         {
     76             LoadData();
     77         }
     78 
     79         private void btnClear_Click(object sender, EventArgs e)
     80         {
     81             txtName.Clear();
     82         }
     83 
     84         private void btnEdit_Click(object sender, EventArgs e)
     85         {
     86             BeginEdit();
     87         }
     88 
     89         private void btnCancel_Click(object sender, EventArgs e)
     90         {
     91             CancelEdit();
     92         }
     93 
     94         private void btnSave_Click(object sender, EventArgs e)
     95         {
     96             try
     97             {
     98                 grid.EndEdit();
     99                 pnlErrorInfo.Visible = false;//隐藏错误信息
    100                 foreach (DataGridViewRow r in grid.Rows)
    101                 {
    102                     foreach (DataGridViewCell c in r.Cells)
    103                         c.ErrorText = "";
    104                 }
    105                 //获取需要保存的实体列表
    106                 List<AccountGroupModel> changed = models.GetChangedItems();
    107                 manager.Save(changed, "Demo");
    108                 LoadData();
    109             }
    110             catch (Exception exc)
    111             {
    112                 if (exc is ValidationException)//显示验证的异常信息
    113                 {
    114                     pnlErrorInfo.Visible = true;
    115                     lblErrorInfo.Text = "";
    116                     ValidationException ve = (ValidationException)exc;
    117                     foreach (ErrorInfo error in ve.ErrorInfos)
    118                     {
    119                         if (error.RowNum > -1)
    120                         {
    121                             string text = error.Errors.ToString();
    122                             grid.Rows[error.RowNum].Cells[FindColumn(grid, error.FiledName).Name]
    123                                 .ErrorText = text;
    124                             lblErrorInfo.Text += "[Row:" + (error.RowNum + 1) + "] "
    125                                 + error.FiledName + ":" + text + ";\r\n";
    126                         }
    127                     }
    128                 }
    129                 else
    130                     MessageBox.Show(exc.ToString(), "Error");
    131             }
    132         }
    133 
    134         private void btnNew_Click(object sender, EventArgs e)
    135         {
    136             accountGroupModelBindingSource.AddNew();
    137         }
    138 
    139         private void btnDelete_Click(object sender, EventArgs e)
    140         {
    141             if (grid.SelectedRows.Count > 0)
    142             {
    143                 foreach (DataGridViewRow row in grid.SelectedRows)
    144                     accountGroupModelBindingSource.Remove(row.DataBoundItem);
    145             }
    146             else if (accountGroupModelBindingSource.Current != null)
    147                 accountGroupModelBindingSource.Remove(accountGroupModelBindingSource.Current);
    148 
    149         }
    150 
    151         private void btnUndo_Click(object sender, EventArgs e)
    152         {
    153             grid.EndEdit();
    154             if (models.CanUndo)//撤销
    155                 SetFocused(models.Undo());
    156         }
    157 
    158         private void btnRedo_Click(object sender, EventArgs e)
    159         {
    160             grid.EndEdit();
    161             if (models.CanRedo)//恢复
    162                 SetFocused(models.Redo());
    163         }
    164 
    165         #endregion
    166 
    167         /// <summary>
    168         /// 聚焦到发生变化的行或者单元格
    169         /// </summary>
    170         /// <param name="edited"></param>
    171         void SetFocused(EditedObject<AccountGroupModel> edited)
    172         {
    173             accountGroupModelBindingSource.ResetBindings(false);
    174             grid.ClearSelection();
    175             if (edited.NewState == DataState.Modified)
    176             {
    177                 int index = models.IndexOf(edited.DataObject);
    178                 grid.Rows[index].Cells[FindColumn(grid, edited.PropertyName).Name].Selected = true;
    179             }
    180             else
    181             {
    182                 int index = models.IndexOf(edited.DataObject);
    183                 if (index != -1)
    184                     grid.Rows[index].Selected = true;
    185             }
    186         }
    187 
    188         private DataGridViewColumn FindColumn(DataGridView grid, string property)
    189         {
    190             //根据属性名查找DataGridViewColumn
    191             foreach (DataGridViewColumn col in grid.Columns)
    192             {
    193                 if (col.DataPropertyName == property)
    194                     return col;
    195             }
    196             return null;
    197         }
    198 
    199         private void grid_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
    200         {
    201             int index = 1;
    202             foreach (DataGridViewRow r in grid.Rows)//显示表格的行号
    203                 r.HeaderCell.Value = index++;
    204         }
    205     }
    复制代码

    7. 运行结果

    示例代码下载EntityDemo.zip

    【LeanEAP.NET】精益企业应用平台----系列目录

     
     
    标签: C#
  • 相关阅读:
    组织机构数据隔离(上级可看下级,同级屏蔽)的高效实现思路
    .NET Core 3.x 基于AspectCore实现AOP,实现事务、缓存拦截器
    .NET Core 3.x 基于Autofac的AOP缓存
    Web开发中【密码加密】详解
    python多线程 DBUtils操作数据库
    处理MariaDB Galera cluster初始化和启动报错两例
    搭建MariaDB Galera Cluster集群 10.3.8
    AzureWeb应用作为客户端携带证书访问其他链接办法
    CTF
    [KuangBin专题四]Silver Cow Party
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2531730.html
Copyright © 2020-2023  润新知