表格批量编辑与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#
作者: Leo_wl
出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息查看更多关于表格批量编辑与Undo/Redo功能实现的详细内容...
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://www.haodehen.cn/did48923