为什么我们需要一个编辑的基类呢?
我们发现对于编辑窗体而言,它们的工作基本的流程是大同小异,而且编辑窗体中每次都需要增加按键处理、是否有编辑内容未保存等提示,因此我们需要一个基类来把这些基本的事情完成。
下面,我们看看是如何实现这个基类的。
通用界面与基本的流程
通用的界面
我们的编辑界面通常是在一个列表界面中,通过点击添加或者编辑按钮,打开一个编辑窗体,他们通常长成下面的这个样子:
基本的流程
我们总结一下基本的流程是下面这样的:
基类的基本实现
构造函数
- public EditFormBase(){ ModelBound = false; _skipDefaultProcessCmdKey = false; AutoRename = true;
- InitializeComponent(); Activated += EditFormBase_Activated; StartPosition = FormStartPosition.CenterScreen;}
- public EditFormBase(IListFormBase listFrm) : this(){ ListForm = listFrm;}
- 其要点如下:
-
ModelBound
:在窗体编辑时有效,知识是否加载了数据库中的Model,因为很多时候,我们的控件是有相关联动而产生另外的数据的,有时候在数据绑定的时候并不想要产生这些事件,这个时候这个属性就非常有用。比如收款金额,可能是**体积单价*体积**,但是也可能是录单人员手动输入的,这个时候,我们保存的内容包括:体积单价、体积、收款金额;而编辑的时候,这个自动计算的功能是不需要的。 -
_skipDefaultProcessCmdKey
:是否忽略现有的键盘按键的操作。基类中我重写了键盘按键事件,按ESC
关闭窗体,按Enter
提交表单。 -
AutoRename
:是否允许基类自动对窗体进行命名。假设实现类中的Title
写为“发货单”,那么,新增时基类自动命名为“新增发货单”;编辑时自动命名为“编辑发货单”。 -
EditFormBase_Activated
:在这个事件中才处理Model
的绑定,这样可以确保Model
的绑定在Form_Load
事件之后。 -
IListFormBase listFrm
:列表界面接口。这个接口要求列表界面对列表数据进行刷新,这样,我们在编辑和更新时候,就可以同时更新列表的数据了。因此,列表窗体必须实现这个接口。
窗体加载与激活
- ///窗体加载
- private void EditFormBase_Load(object sender, EventArgs e)
- {
- if (IsEdit)
- {
- if (AutoRename)
- Text = "编辑" + Text;
- }
- else
- {
- ModelBound = true;
- if (AutoRename)
- Text = "添加" + Text;
- }
- }
- ///窗体激活
- private void EditFormBase_Activated(object sender, EventArgs e)
- {
- if (!FormLoaded)
- {
- if (IsEdit)
- {
- BindEntity();
- ModelBound = true;
- AfterBindEntity();
- }
- FormLoaded = true;
- }
- }
提交表单
- //提交操作,一般在点击按钮之后触发
- protected void ReadySaveEntity(bool close)
- {
- if (CheckInput())
- {
- Cursor = Cursors.WaitCursor;
- string operation = IsEdit ? "编辑" : "添加";
- try
- {
- if (SaveOrUpdateEntity(IsEdit))
- {
- MessageBoxHelper.ShowTipsSlide("{0}成功!!!", operation);
- RefreshUi();
- if (close)
- {
- DialogResult = DialogResult.OK;
- Close();
- }
- else
- {
- ClearScreen();
- }
- }
- }
- catch (Exception ex)
- {
- OnSaveOrUpdateError(ex, operation);
- }
- finally
- {
- Cursor = Cursors.Default;
- }
- }
- }
- //实际的提交,是一个虚方法,需要子类实现,没有实现将会弹出警告框
- protected virtual bool SaveOrUpdateEntity(bool isEdit)
- {
- MessageBoxHelper.ShowTips("没有实现添加或者编辑记录的接口,请与开发人员联系");
- return false;
- }
列表更新与界面清空
- //都是有默认的实现,当然你可以可以自己重写
- protected virtual void RefreshUi()
- {
- if (ListForm != null)
- {
- ListForm.RefreshListView("");
- }
- else
- {
- MessageBoxHelper.ShowTips("没有实现刷新界面的接口,请与开发人员联系");
- }
- }
数据绑定、控件验证
- //都是空方法,需要子类实现
- protected virtual void BindEntity()
- {
- }
- protected virtual void AfterBindEntity()
- {
- }
使用实例
以下面的界面为例子,我们讲讲如何实现这个编辑窗体
其基本实现步骤如下:
继承基类
- public partial class SendOrderEdit : EditFormBase
- {
- public SendOrderEdit(IListFormBase list)
- : base(list)
- {
- InitializeComponent();
- }
- }
触发保存并新增、保存并关闭按钮
- //保存并新增
- private void btnSaveAndAdd_Click(object sender, EventArgs e)
- {
- ReadySaveEntity(false);
- IsEdit = false;
- }
- //保存并关闭
- private void btnSaveAndClose_Click(object sender, EventArgs e)
- {
- ReadySaveEntity(true);
- }
实现基本的操作流程
-
验证
CheckInput
-
数据绑定
BindEntity
-
提交数据库
SaveOrUpdateEntity
-
清空界面
ClearScreen
-
如果需要控制刷新列表的参数,需要重写刷新方法
RefreshUi
。
带保存按钮和关闭按钮的基类
为了更简化我们的操作和统一编辑界面,我们同时提供了下面这个编辑窗体基类,是带有保存按钮和关闭按钮的:
它的实现非常简单:
- public partial class BaseFormEditNew : EditFormBase
- {
- public BaseFormEditNew()
- {
- InitializeComponent();
- }
- public BaseFormEditNew(IListFormBase list)
- : base(list)
- {
- InitializeComponent();
- }
- private void btnCancel_Click(object sender, EventArgs e)
- {
- Close();
- }
- private void btnSave_Click(object sender, EventArgs e)
- {
- ReadySaveEntity(true);
- }
- }