利用EAP.Entity提供的可以Undo/Redo的列表绑定数据到DataGridView,让表格批量编辑更方便更高效。
1. 还是利用的结构,然后得到实体AccountGroupModel:
View Code
1 [System.Serializable()] 2 public class AccountGroupModels : System.Collections.Generic.List3 { 4 5 public AccountGroupModels() 6 { 7 } 8 9 public AccountGroupModels(System.Collections.Generic.IEnumerable collection) : 10 base(collection) 11 { 12 } 13 } 14 15 /// 16 /// 18 [System.Serializable()] 19 public partial class AccountGroupModel : EAP.Entity.DataObject17 /// 20 { 21 #region Member Property Region 22 /// 23 /// 25 [EAP.Data.ColumnInfoAttribute(Visible = false, Queryable = true, DbColumn = "Id")] 26 public int Id 27 { 28 get 29 { 30 return GetValue ("Id"); 31 } 32 set 33 { 34 SetValue("Id", value); 35 } 36 } 37 38 ///主键 24 ///39 /// 41 [EAP.Data.ColumnInfoAttribute(DbColumn = "Name")] 42 public string Name 43 { 44 get 45 { 46 return GetValue名称 40 ///("Name"); 47 } 48 set 49 { 50 SetValue("Name", value); 51 } 52 } 53 54 /// 55 /// 57 [EAP.Data.ColumnInfoAttribute(DbColumn = "Parent")] 58 public int Parent 59 { 60 get 61 { 62 return GetValue ("Parent"); 63 } 64 set 65 { 66 SetValue("Parent", value); 67 } 68 } 69 70 ///上级组别 56 ///71 /// 73 [EAP.Data.ColumnInfoAttribute(DbColumn = "Visible")] 74 public bool Visible 75 { 76 get 77 { 78 return GetValue可见性 72 ///("Visible"); 79 } 80 set 81 { 82 SetValue("Visible", value); 83 } 84 } 85 86 /// 87 /// 89 [EAP.Data.ColumnInfoAttribute(DbColumn = "UpdateUser")] 90 public string UpdateUser 91 { 92 get 93 { 94 return GetValue修改者 88 ///("UpdateUser"); 95 } 96 set 97 { 98 SetValue("UpdateUser", value); 99 }100 }101 102 /// 103 /// 105 [EAP.Data.ColumnInfoAttribute(DbColumn = "UpdateDate")]106 public System.DateTime UpdateDate107 {108 get109 {110 return GetValue修改时间 104 ///("UpdateDate");111 }112 set113 {114 SetValue("UpdateDate", value);115 }116 }117 #endregion118 }
2. 定义业务接口:
1 interface IAccountGroupManager 2 { 3 ///4 /// 加载Models 5 /// 6 /// 7 ///8 AccountGroupModels GetModels(string name); 9 /// 10 /// 保存11 /// 12 /// 需要保存的列表13 /// 更新者14 void Save(Listmodels, string user);15 /// 16 /// 加载所有可见的账户组17 /// 18 ///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);//把数据加载到model17 m.EndInit();18 models.Add(m);19 }20 return models;21 }22 }
4. Save方法的实现
1 public void Save(Listmodels, 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 () > 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. 窗口中的代码
View Code
1 public partial class DemoForm : KryptonForm 2 { 3 //业务接口 4 IAccountGroupManager manager; 5 //实体列表 6 DataObjectListmodels = new DataObjectList (); 7 8 public DemoForm() 9 { 10 InitializeComponent(); 11 //创建接口的实现 12 manager = new RefObjectCreator().Create (); 13 //把实体绑定到BindingSource 14 accountGroupModelBindingSource.DataSource = models; 15 models.ListChanged += new EventHandler >(models_ListChanged); 16 CancelEdit(); 17 } 18 19 void models_ListChanged(object sender, ListChangedEventArgs 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 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 else130 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 #endregion166 167 /// 168 /// 聚焦到发生变化的行或者单元格169 /// 170 /// 171 void SetFocused(EditedObjectedited)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 else181 {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 //根据属性名查找DataGridViewColumn191 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. 运行结果
示例代码下载