在Win中用Command模式实现可以撤销的数据操作.docx_第1页
在Win中用Command模式实现可以撤销的数据操作.docx_第2页
在Win中用Command模式实现可以撤销的数据操作.docx_第3页
在Win中用Command模式实现可以撤销的数据操作.docx_第4页
在Win中用Command模式实现可以撤销的数据操作.docx_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

“你们开发的系统如果能够像Excel那 样支持全选、反选、多选、撤销、导入、导出等命令;不要每次增加一条记录都必须按一下新增,完了以后再按一下保存,取而代之的是我想保存的时候一 按保存,就把我前面所有的操作全都保存,如果我的操作有误,可以撤销刚刚所做的操作。那真是爽死了。”很多的用户这样感慨。用户体验非常重要,很多的 时候,如果用户觉得你的系统不方便,他就会拒绝使用。这样,系统也就没有什么意义了。如果在给客户做演示的时候,能够充分展现你系统在易用性方面的优势, 那么中标几率就会大大的增加。用DataTable、DataGridView和Command设计模式完全可以前面用户所提到的功能。我们先分析一下,用户所提到的功能,实际上就是希望能够对界面层表示的数据方便的发出各种命令,这些命令可以通过一个个的按钮提供给用户调用。如果我们用DataTable来容纳业务数据,用DataGridView来表示这些数据,那么对“全选、反选、多选”等,就是针对DataGridView来说的,而对于“撤销、导入、批量保存”等则是对业务数据来说的,而DataTable则支持这些操作。下面是DataTable、DataRow、DataGridView、按钮和数据操作命令之间的关系简图。可以看出,数据操作命令就是Command模式中的Command,而按钮就是Invoker,而DataTable和DataGridView则是Receiver,在WinForm中,实际上我们主要是通过BindingSource来操作DataTable,所以对于DataTable这个间接的Receiver来说,其直接Receiver就是一个BindingSource。但是,不管是DataTable还是BindingSource都不能全部符合我们的要求,所以我们必须自己实现一个符合我们要求的Receiver,假设我们叫他DataCommandReceiverBase,为了能够进行可是化设计,我们让他继承自Component,其原型如下: public abstract class DataCommandReceiverBase:Component public abstract void New(); public abstract void Delete(); public abstract void UnDo(); public abstract void Save(); 对于“新增、删除、保存、撤销”等命令,我们把它们抽象为一个公共的类,叫做DataCommand,其原型如下: public abstract class DataCommand : Component public abstract void Do(); DataCommandReceiverBase _Receiver; public DataCommandReceiverBase Receiver get return _Receiver; set _Receiver = value; 然后,我们对每一个基本的操作,比如“新增”建立一个对应的DataCommand的子类,并重写Do函数,在该函数中调用Receiver相应的功能。如下所示: public class NewCommand : DataCommand protected override void Do() Receiver.New(); public class DeleteCommand : DataCommand protected override void Do() Receiver.Delete(); public class SaveCommand : DataCommand protected override void Do() Receiver.Save(); public class UndoCommand : DataCommand protected override void Do() Receiver.UnDo(); 对于给用户提供数据操作命令的按钮,我们叫他CommandButton,他包含有一个DataCommand的实例Command以便在用户按下按钮时执行用户的命令。其原型如下:public class CommandButton:Button DataCommand _Command; public DataCommand Command get return _Command; set if (_Command = value) return; _Command = value; protected override void OnClick(EventArgs e) if (_Command != null) _Command.Do(); base.OnClick(e); 现在,只要实现一个DataCommandReceiverBase的子类,我们的目的就达到了。要实现一个这样的类也非常的简单,稍微难一点的地方就是Undo方法的实现,如果用其他的平台我不知道,但是用.net 下面的DataTable,真的很容易,只要在目标DataTable的RowChanged事件和RowDeleted事件中把操作过的DataRow记录下来,在Undo的时候,取出最近的记录,然后调用DataRow的RejectChanges方法就可以搞定一切。其代码如下:public class DefaultDataCommandReceiver : DataCommandReceiverBase DataTable _SourceTable = null; List _HistoryList = new List(); BindingSource _BindingSource; public BindingSource BindingSource get return _BindingSource; set if (_BindingSource = value) return; if (_SourceTable != null) _SourceTable.RowChanged -= new DataRowChangeEventHandler(_SourceTable_RowChanged); _SourceTable.RowDeleted -= new DataRowChangeEventHandler(_SourceTable_RowDeleted); _SourceTable = null; if (value = null) _BindingSource = null; return; if (IsValidDataSource(value,ref _SourceTable) _BindingSource = value; if (_SourceTable != null) _SourceTable.RowChanged += new DataRowChangeEventHandler(_SourceTable_RowChanged); _SourceTable.RowDeleted += new DataRowChangeEventHandler(_SourceTable_RowDeleted); return; throw new Exception(BindingSource的DataSource必须是DataTable/DataSet/DataView); bool IsValidDataSource(BindingSource value, ref DataTable ReturnTable) if (value.DataSource is DataTable) | (value.DataSource is DataSet) | (value.DataSource is DataView) if (value.DataSource is DataTable) ReturnTable = value.DataSource as DataTable; else if (value.DataSource is DataSet) ReturnTable = (value.DataSource as DataSet).Tablesvalue.DataMember; else ReturnTable = (value.DataSource as DataView).Table; return true; if (value.DataSource is BindingSource) return IsValidDataSource(value.DataSource as BindingSource, ref ReturnTable); return false; void _SourceTable_RowDeleted(object sender, DataRowChangeEventArgs e) if (!BeginLogUpdate) return; LogRow(e.Row); void _SourceTable_RowChanged(object sender, DataRowChangeEventArgs e) if (!BeginLogUpdate) return; if (e.Action = DataRowAction.Add | e.Action = DataRowAction.Change) LogRow(e.Row); void LogRow(DataRow ARow) if (_HistoryList.Contains(ARow) _HistoryList.Remove(ARow); _HistoryList.Insert(0,ARow); bool _BeginLogUpdate = false; public bool BeginLogUpdate get return _BeginLogUpdate; set _BeginLogUpdate = value; public override void New() BindingSource.AddNew(); public override void Delete() if (BindingSource.Count = 0) return; (DataRowView)BindingSource.Current).Row.Delete(); public override void Save() if (_HistoryList.Count = 0) return; SaveDataToDb(); _SourceTable.AcceptChanges(); _HistoryList.Clear(); protected virtual void SaveDataToDb() / / Save the changed data into database / public override void UnDo()

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论