如何設計一個編輯窗體的基類


為什么我們需要一個編輯的基類呢?

我們發現對於編輯窗體而言,它們的工作基本的流程是大同小異,而且編輯窗體中每次都需要增加按鍵處理、是否有編輯內容未保存等提示,因此我們需要一個基類來把這些基本的事情完成。

下面,我們看看是如何實現這個基類的。

通用界面與基本的流程

通用的界面

我們的編輯界面通常是在一個列表界面中,通過點擊添加或者編輯按鈕,打開一個編輯窗體,他們通常長成下面的這個樣子:

基本的流程

我們總結一下基本的流程是下面這樣的:

基類的基本實現

構造函數

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);
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM