控件使用經驗-MVP模式+控件封裝

項目背景

幾年前參與了一個面向學校的人事管理軟件的開發,基於WinForm平臺。今天主要想談一談其中關於控件的使用經驗。這個項目咱們大量使用了第三方控件。因爲這個產品的生命週期很長,咱們在設計時要考慮表現層可能會有不一樣的形式,好比如今是WinForm之後可能會是WPF或者Web。另外也要考慮控件版本升級對產品的影響降到最低。數據庫

設計

基於上面的想法,咱們經過兩點來解決這些問題。MVP模式+控件封裝,能夠開發出更具彈性的View層。它能更有效的應對UI變化,包括控件升級這種小的UI變化,甚至是平臺遷移等這種大的UI變化。ide

MVP(Model-View-Presenter)模式主要是爲了表現層解耦,若是表現層的職責不單一,那麼有控件升級或者UI層使用新的平臺時花費的成本就會很高。使用MVC以後只有View層和控件相關,Presenter層實現UI邏輯。當View層變化時(控件升級或者新的UI形式),Presenter層、Model層都會被重用。函數

控件封裝能夠以一種統一的方式使用控件。全部使用到的控件所有封裝即便是.Net控件也進行封裝,不容許使用任何原生控件,只能使用封裝後的控件。咱們對控件的進行深度封裝,將不少功能在控件中實現。性能

控件封裝經驗

咱們以表格功能爲例來介紹咱們如何進行控件封裝。在咱們項目中對錶格功能的要求很是高,一方面功能要很是強大,並且具備很強的定製開發能力,另外一方面要求表格控件具備良好的性能。下面經過幾個UI瞭解咱們對錶格的要求。this

 

圖1spa

 

 

圖2設計

 

圖3code

圖1和圖2展現的是職員一覽畫面中,咱們不單單加載出了職員信息,並且加載了職員的照片,須要一次性從數據庫中加載幾千張職員照片,對錶格的性能要求很高。orm

圖3展現以時間軸方式顯示的職員狀態。點擊放大、縮小按鈕,時間刻度的粒度也會發生變化,並從新刷新數據。xml

經過以上的兩個示例能夠看出咱們對錶格的性能和擴展性要求很高。咱們綜合對比了Spread,FlexGrid,MutilRow這幾種表格控件,最終咱們選擇了FlexGrid控件。

FlexGrid控件封裝

圖4

圖4是咱們基於FlexGrid進行了深度封裝的類圖。在項目中不容許直接使用FlexGrid,只能使用咱們封裝後的JijiEditGrid等控件。咱們以JijiBaseGrid爲例來看看咱們是如何進行封裝。

 

下面節選了咱們JijBaseGrid中的一些功能。

功能

描述

處理

Option機制

記憶列寬、字段順序等

方法:LoadOption、SaveOption

列頭菜單

字段顯示/隱藏

屬性:NeedHeaderMenu(設計時不可用)

統一管理顏色

Grid的配色是否隨着Form走

屬性:IsColorManaged(設計時可用)

接口:IColorControl

拷貝到剪貼板

根據Option進行特殊處理,分隔符、日期格式等

方法:CopyGridRangeToClip(RealText realText)

事件:public event EventHandler DataCopy = delegate { };

特殊鍵

F9:自動調整列寬

Ctrl+A:全選

Ctrl+C:複製

Delete:刪除

PageDown:數據不滿一頁,PageDown按下時,跳轉到最後一行

事件處理函數:override void OnKeyDown

 

咱們僅僅選擇「特殊鍵」這個功能,看看在OnKeyDown中的處理。這裏主要處理各類特殊按鈕,好比F9等。

        /// <summary>
        /// Grid的按鍵押下事件
        /// </summary>
        /// <param name="e">參數</param>
        protected override void OnKeyDown(KeyEventArgs e)
        {
            base.OnKeyDown(e);

            // 記錄Control鍵是否按下
            this.controlDown = e.Control;

            switch (e.KeyCode)
            {
                case Keys.F9:
                    if (this.CanF9)
                    {
                        // 列寬自動調整
                        Color oldColor = this.BackColor;
                        this.AutoSizeCols();
                        this.BackColor = oldColor;
                    }
                    break;

                case Keys.Delete:
                    if (this.CanDeleteRow())
                    {
                        // 處理行刪除事件
                        this.RowDelete(this, new EventArgs());
                    }
                    else if (this.CanDeleteCellRange())
                    {
                        // 處理Cell範圍選中刪除事件
                        this.CellRangeDelete(this, new EventArgs());
                    }
                    break;

                case Keys.A:
                    if (e.Control)
                    {
                        // ctrl + A鍵的操做(全選)
                        int rowCount = this.GetRowCount();
                        if (rowCount > this.Rows.Fixed)
                        {
                            this.isControlA = true;

                            this.Select(this.Rows.Fixed, this.Cols.Fixed, false);
                            this.Select(this.Rows.Fixed, this.Cols.Fixed, rowCount, this.Cols.Count - 1, false);

                            this.isControlA = false;
                        }
                    }
                    break;

                case Keys.C:
                    if (e.Control && this.AllowCopy && this.DataCopy != null && this.DataCopy.Target != null)
                    {
                        // ctrl + C鍵的操做(復制)
                        this.DataCopy(this, new EventArgs());
                    }
                    break;

                case Keys.PageDown:
                    // 特殊處理數據不滿一頁,PageDown按下時,跳轉到最後一行
                    this.DoPageDownEvent();
                    break;
            }
        }

 

默認的FlexGrid是沒有這些功能的,咱們重寫OnKeyDown方法。根據本身的需求增長對各類特殊鍵的處理。

經過對控件進行全面的封裝,當有新的需求或者有需求變動時和控件相關的功能咱們只需在封裝的控件中進行修改便可。

相關文章
相關標籤/搜索