亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

WinForm怎么構建通用的速選組件

發布時間:2021-06-17 15:42:11 來源:億速云 閱讀:136 作者:chen 欄目:編程語言

本篇內容介紹了“WinForm怎么構建通用的速選組件”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

對于WinForm組件,大家并不陌生。在這里我們將為大家講解WinForm通用速選組件的構建,這也是通往WinForm開發的必經之路。

用戶界面中,需要用戶進行多項選擇時,我們通常會提供一組快速選擇(以下簡稱速選)按鈕:全選、反選、清空,以方便用戶操作。本文章將會構建一個通用速選組件來簡化操作,使用之后,您不需要編寫任何代碼,只需設置兩個屬性便可讓一個控件擁有速選的功能。

WinForm中常見的幾種多選形式如下圖:

WinForm怎么構建通用的速選組件

圖1

我們暫且將用于顯示選項的控件叫做“選項控件”,全選、反選、清空叫做“速選按鈕”。

四種形式采用了不同的控件用作選項控件、速選按鈕:

 選項控件速選按鈕
形式一CheckedListBoxLabel
形式二CheckBoxLinkLabel
形式三TreeViewButton
形式四DataGridViewPictureBox

實際使用中還可能會有其它形式的選項控件和速選按鈕,根據使用場合不同,選項控件和速選按鈕可以任意組合。這給我們編程帶來了麻煩,選項控件沒有統一的訪問接口,換一個選項控件就要編寫不同的選擇代碼。

想要將全選、反選、清空的選擇邏輯提取出來還真不容易。于是很多程序員就選擇了針對實際應用的組合(如形式一,CheckedListBox + Label)進行直接編碼。這樣導致大量相似的代碼充斥在項目之中,會帶來以下問題:

  1. 重復的編碼、調試、測試(主要是界面)工作;

  2. 一旦選項控件發生改變,就必須修改代碼,修改后還要測試;(可能性比較大,可能客戶不喜歡形式一,非要你修改成形式二)

這樣的直接編碼實際上已經違反了DRY原則,我們應該糾正。

面向對象要求我們封裝變化,我們這里不變的是速選的邏輯,變化的是選項控件和速選按鈕,變化是兩個方向的,有點接近橋模式的應用場景了。不過我對設計模式了解不深,不敢冒用,而且感覺這里速選按鈕的變化是比較簡單的,至少它們都有一個Click事件,也可以認為是不變的。

我們采用另外一種途徑,.Net其實已經給我們提供了一種擴展控件功能的方式(也正體現了面向對象的OCP原則),可以讓我們給控件賦予額外的功能。我們來看一個重要的接口:IExtenderProvider 接口,位于System.ComponentModel命名空間下。實現了這個接口的組件有ToolTip、ErrorProvider等,ToolTip、ErrorProvider這兩個組件可以向其它組件(控件是組件的一種)提供額外的功能,ToolStip能讓其它控件在用戶鼠標懸停時彈出一個小框顯示一些提示信息,ErrorProvider則能讓控件顯式錯誤信息。

我們要做的就是創建一個新的組件,實現IExtenderProvider接口,向控件(Button、Label等)提供速選的功能。這個組件我已經完成了,名字叫FastSelect,先不考慮實現原理、如何實現,我們先看下如何使用吧:

FastSelect是一個組件,會自動顯示在工具箱中,將其拖入窗體,將會顯示在設計器下方。

WinForm怎么構建通用的速選組件

圖2

選中全選按鈕(label1),屬性顯示窗口如下圖:

WinForm怎么構建通用的速選組件

圖3

分組中出現了一個新的分組:速選,其中有如上圖兩個屬性,***個屬性用于選擇選項控件,第二個屬性用于確定選擇方式(全選還是清空)。設置兩個屬性的值如上圖,完成后label1就可以全選分類中的所有選項了。

簡單說來,只需要向窗體置入一個控件(Button、Label、LinkLabel、Picture),簡單設置兩個屬性,這個控件就自動具有了速選功能,不需要任何代碼。當然得借助FastSelect組件。

這么神奇,是如何實現的呢?要從IExtenderProvider接口說起,這個接口可以向其他組件提供屬性,如上圖中的兩個屬性。有這里有兩點要說明一下:

  1. 向其它組件提供屬性,這個可以限定,比如僅只向Button提供。

  2. 提供屬性并不是真正給其他組件加上新的屬性,只是在WinForm設計時,在PropertyGrid中顯示額外屬性(后面會詳說)。

我們來看下FastSelect是如何實現的:

public enum SelectionType    {        清空,        反選,        全選,    }     [ProvideProperty("SelectionSource", typeof(Control))]    [ProvideProperty("SelectionType", typeof(Control))]    public partial class FastSelect : Component, IExtenderProvider    {             public bool CanExtend(object extendee)        {            if (extendee == null) return false;           if (extendee is Button || extendee is Label || extendee is PictureBox) return true;           return false;        }        [Category("速選"), Description("速選源控件"), Localizable(true)]        public Control GetSelectionSource(Control control)        {            ...        }        public void SetSelectionSource(Control control, Control selectionSource)        {            ...        }          [Category("速選"), Description("速選方式"), DefaultValue(SelectionType.清空), Localizable(true)]        public SelectionType GetSelectionType(Control control)        {                  }       public void SetSelectionType(Control control, SelectionType selectionType)       {           ...      }       ...        }

SelectionType枚舉不必多說,我們來看FastSelect,它繼承至Component,實現了IExtenderProvider接口。

CanExtend是IExtenderProvider接口的***成員,它用來標識可以給那些組件進行擴展,上面的代碼中我們限定了只可以給Button、Label、PictureBox進行擴展,也就是說其它類型的控件在屬性窗口中是看不到速選屬性的。CanExtend中沒有LinkLabel,是因為LinkLabel是Label的子類,Label有的它也會自動擁有。

Get(Set) SelectionSource、Get(Set)SelectionType有點類似屬性的get/set吧,只不過多了一個參數(***個參數control),傳入這個參數的是要進行屬性擴展的控件,還是讓我們看一下WinForm生成的代碼吧(在Form1.generated.cs中)

this.fastSelect.SetSelectionSource(this.label1, this.categoriesListBox);   this.fastSelect.SetSelectionType(this.label1, SelectionType.全選);

對照圖三,應該明白“提供屬性”的真正含義了吧。

我們再來看是如何實現選擇的,先看代碼片段:

public partial class FastSelect : Component, IExtenderProvider      {          private Dictionary sourceControlsDict;          private Dictionary typeDict;         public void SetSelectionSource(Control control, Control selectionSource)        {                           sourceControlsDict.Add(control, selectionSource);               control.Click += new EventHandler(control_Click);                      }          public void SetSelectionType(Control control, SelectionType selectionType)        {                         typeDict.Add(control, selectionType);                       }           void control_Click(object sender, EventArgs e)           {              Control control = sender as Control;             Control selectionSource = sourceControlsDict[control];              SelectionType selectType = typeDict[control];                if (selectionSource is DataGridView)              {                   DataGridView dataGridView = selectionSource as DataGridView;                   foreach (DataGridViewRow row in dataGridView.Rows)                       row.Selected = ChangeSelected(row.Selected, selectType);               }                         }             private bool ChangeSelected(bool isSelected, SelectionType type)           {             if (type == SelectionType.清空) return false;              else if (type == SelectionType.全選) return true;             else if (type == SelectionType.反選) return !isSelected;              else throw new NotImplementedException();           }                 }

一個窗體上只需要一個FastSelect組件,但它要為其它多個組件提供屬性,我們這里使用Dictionary保存這些屬性。

設置控件SelectionSource屬性時,其實是調用了SetSelectionSource方法,其中我們為控件注冊了Click事件,control_Click中根據不同的選項控件的類型(DataGridView、CheckedListBox等)和選擇類型進行相應的處理。這樣應該明白了吧。

“WinForm怎么構建通用的速選組件”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

池州市| 武胜县| 收藏| 中阳县| 阳谷县| 武冈市| 和平县| 洞头县| 霍林郭勒市| 抚远县| 延长县| 商城县| 定州市| 陆河县| 晴隆县| 新疆| 新乐市| 三门峡市| 灌阳县| 丘北县| 关岭| 台北县| 岢岚县| 图片| 和田市| 美姑县| 镇雄县| 虞城县| 临汾市| 勐海县| 宁波市| 同德县| 惠来县| 金华市| 道真| 平武县| 开封县| 阳曲县| 广水市| 昌平区| 咸宁市|